第8章 VBA程序设计基础
程序概念 维基解释(zh.wikipedia.org) http://zh.wikipedia.org/zh-cn/%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80
另一种解释 参见Wiki解释http://www.wikilib.com/wiki?title=%E7%A8%8B%E5%BA%8F&variant=zh-cn 计算机程序或者软件程序(通常简称程序)是指一组指示计算机每一步动作的指令,通常用某种程序设计语言编写,运行于某种目标体系结构上。打个比方,一个程序就像一个用汉语(程序设计语言)写下的红烧肉菜谱(程序),用于指导懂汉语的人(体系结构)来做这个菜。 通常,计算机程序要经过编译和链接而成为一种人们不易理解而计算机理解的格式,然后运行。未经编译就可运行的程序通常称之为脚本程序。
A Joke(SQL版) 某女技术人员的征婚信息 SELECT * FROM 男人 WHERE (未婚=true or 离异=true) and 穷光蛋=false and 有房=true and 有车=true 结果有人回帖: (0 row(s) affected)
A Joke(C语言版)
姑娘爱小伙(伪C语言版) result love(boy, girl ){ if( boy.有房() and boy.有车()){ boy.set(nothing); return girl. 嫁给(boy); }
姑娘爱小伙 (搞笑版) if( girl.愿意等 ()){ while(!(boy.赚钱 > 100,000 and girl.感情 > 8 )){ for ( day=1; day <=365; day++){ if( (day == 情人节 or day == girl.生日)& and boy.givegirl(玫瑰)) girl.感情++; else girl. 感情--; boy.拼命赚钱(); }//for }//while
姑娘爱小伙(搞笑版) if( boy.有房() and boy.有车() ){ boy.set(nothing); return girl.嫁给(boy); } else{ 年龄++; girl.感情--; return girl.goto( another_boy);
姑娘爱小伙(搞笑版)完整版 result love(boy, girl ){ if( boy.有房() and boy.有车()){ boy.set(nothing); return girl. 嫁给(boy); } if( girl.愿意等 ()){ while(!(boy.赚钱 > 100,000 and girl.感情 > 8 )){ for ( day=1; day <=365; day++){ if( (day == 情人节 or day == girl.生日)& and boy.givegirl(玫瑰)) girl.感情++; else girl. 感情--; boy.拼命赚钱(); }//for }//while if( boy.有房() and boy.有车() ){ return girl.嫁给(boy); else{ 年龄++; girl.感情--; }//if愿意等 return girl.goto( another_boy);
程序可读性 缩格 对齐
8 结构化程序设计基础 程序设计过程 算法 程序流程图及示例
8.1 程序设计过程 程序设计即是计算机用户根据解决某一问题的步骤,按一定的逻辑关系,将一系列的指令组合在一起。
8.2 算法(1) 程序的设计过程,核心问题是设计一个合理、有效的算法。 一般认为,算法就是在有限的时间内,可以根据明确规定的运算规则,在有穷步骤内得出确切计算结果的机械步骤或能运行的计算程序。
8.2 算法(2) 算法特性: (1)有序性:每个步骤被执行的顺序是确定的。 (2)有限性:即解题步骤是有限的,无穷的步骤意味无解。 (3)确定性:多次运行同样一个程序,其结果相同。 此外,算法可以没有输入(因为输入由计算机自动产生),但一定要有输出,输出用来表示问题是否有解。
8.2 算法(3) 三种基本控制结构:顺序、分支、循环 顺序结构是程序设计中最基本的结构。在该结构中,程序的执行是按命令出现的先后顺序依次执行的。 分支结构是按给定的选择条件成立与否来确定程序的走向。分支结构可分为双重分支选择和多重分支选择。在任何条件下,无论分支多少,只能选择其一。
8.2 算法(4) 三种基本控制结构:顺序、分支、循环 循环结构是一种重复结构,即某一程序段将被反复执行若干次。按循环的嵌套层次,循环可分为简单循环结构和循环嵌套(也称为多重循环)结构。按循环体执行的条件性质,循环又可分为While循环和Until循环。无论何种类型的循环结构,都要确保循环的重复执行能够终止。
8.2 算法(5) 结构化程序是指仅由三种基本控制结构组成的程序,它具有以下特点: (1) 整个程序模块化。 (2) 每个模块只有一个入口和一个出口。 (3) 每个模块都应能单独执行,且无死循环。 (4) 采用黑箱的思想,宏观地描述任何一个程序,可以将它看成为顺序结构。
8.3 程序流程图及示例 ANSI流程图 N-S图
1. ANSI流程图(1) 起止框:表示程序的开始或结束 处理框:表示对数据进行处理 输入/输出框:表示数据的输入、输出操作 判断框 箭头:表示程序流向 连接符号:表示图标之间相互连接关系 判断框:表示根据条件决定程序走向 过程:表示该流程部分是一个过程 输入/输出框:表示数据的输入、输出操作 处理框:表示对数据进行处理 起止框:表示程序的开始或结束
1. ANSI流程图(2) 顺序结构
1. ANSI流程图(3) 条件分支结构
1. ANSI流程图(4) 循环结构 While型循环结构 Until型循环结构
1. ANSI流程图(5) 多重条件分支结构
2. N-S图 (1) 顺序结构 语句块1 语句块2 语句块3
2. N-S图 (2) 条件分支结构
2. N-S图 (3) 多重分支选择语句
2. N-S图 (4) 循环结构 While型循环结构 Until型循环结构
8.3 程序的控制语句结构 顺序结构程序 分支结构程序 循环结构程序
2.分支结构程序(1) 双重分支选择语句 语句格式: If <条件> Then <语句块1> [Else 假 真 条件 语句块1 语句块2 双重分支选择语句 语句格式: If <条件> Then <语句块1> [Else <语句块2>] End If
2.分支结构程序(2) 双重分支选择语句 语句格式: If <条件> Then <语句块1> [Else <语句块2>] End If 语句块1 语句块2 条件 真 假
2.分支结构程序(3) 多重分支选择语句 If <条件1> Then [<语句块1>] [ElseIf <条件2> Then [<语句块2>]] ... [ElseIf <条件n> Then [<语句块n>]] [Else [<语句块>]] End If 多重分支选择语句
2.分支结构程序(4) 多重分支选择语句 If <条件1> Then [<语句块1>] [ElseIf <条件2> Then [<语句块2>]] ... [ElseIf <条件n> Then [<语句块n>]] [Else [<语句块>]] End If 多重分支选择语句
2. 分支结构程序(5) 例6-8:从键盘随机输入成绩分数,根据成绩分数来判断该成绩属于优、良、中还是差。规定: 90≤成绩≤100为优; 80≤成绩<90为良; 60≤成绩<80为中; 成绩<60为差; 其它为非法输入。
2. 分支结构程序(6) Public Sub multicase() Dim grade As Integer grade = Val(InputBox("请输入成绩")) If grade <= 100 And grade >= 90 Then Debug.Print Str(grade) & "的成绩为:" & "优" '缩格的目的是增加可读性 ElseIf grade < 90 And grade >= 80 Then Debug.Print Str(grade) & "的成绩为:" & "良" ElseIf grade < 80 And grade >= 60 Then Debug.Print Str(grade) & "的成绩为:" & "中" ElseIf grade < 60 And grade > 0 Then Debug.Print Str(grade) & "的成绩为:" & "差" Else Debug.Print "您输入的成绩不对!" End If End Sub
2.分支结构程序(3) 多重分支选择语句 Select Case <测试表达式> [Case <条件表达式1> [<语句块1>]] ... [Case Else [<语句块>]] End Select 多重分支选择语句
2.分支结构程序(4) 多重分支选择语句 Select Case <测试表达式> [Case <条件表达式1> [<语句块1>]] ... [Case Else [<语句块>]] End Select 多重分支选择语句
例子 【例8-4】从键盘随机输入成绩分数,根据成绩分数来判断该成绩属于优、良、中还是差。规定: 90≤成绩≤100为优; 80≤成绩<90为良; 60≤成绩<80为中; 成绩<60为差; 其他为非法输入。
Public Sub multicase() Dim grade As Integer grade = Val(InputBox("请输入成绩")) Select Case grade Case 90 To 100 MsgBox( Str(grade) & "的成绩为:" & "优") Case 80 To 90 MsgBox( Str(grade) & "的成绩为:" & "良") Case 60 To 80 MsgBox( Str(grade) & "的成绩为:" & "中") Case 0 To 60 MsgBox( Str(grade) & "的成绩为:" & "差") Case Else MsgBox( "您输入的成绩不对!") End Select End Sub
分支嵌套 VBA允许在If…Else…End If的<语句块>中使用If…Else…End If语句 If语句的嵌套 【例8-6】随机输入年份,判断该年是否为闰年。判断闰年的条件是:年份如能被4整除但不能被100整除,是闰年;若年份能被400整除,则是闰年。
分析:当随意输入一年份时,该年份如不能被4整除,则该年肯定不是闰年。 问题是当该年份能被4整除时,有可能是闰年,也可能不是闰年。 因为100是4的倍数,400又是100的倍数。 因此我们首先判断该年份是否被4整除, 再判断是否被100整除, 最后判断是否被400整除。
Public Sub LeapYear1() Dim nyear As Integer nyear = Val(InputBox("请输入年份")) If nyear / 4 = Int(nyear / 4) Then If nyear / 100 = Int(nyear / 100) Then If nyear / 400 = Int(nyear / 400) Then Debug.Print "闰年" Else Debug.Print "非闰年" End If End Sub
3. 循环结构程序(1) DO WHILE循环 语句格式: Do While <条件表达式> <语句块> [Exit Do] Loop
3. 循环结构程序(2) 循环语句的使用要注意下列几点: (1)Do While和Loop子句要配对使用,Loop的作用是使循环回到循环的开始,即到Do While语句。 (2)在第一次执行到Do While语句时,循环条件必须为真,才能进入循环体。在执行完成循环体语句后,再判断循环条件是否为真,如果为真,则继续循环,直到循环条件为假时,才退出循环语句,执行Loop后面的语句。
3. 循环结构程序(3) 循环语句的使用要注意下列几点: (3)循环体中,一定存在一条或若干条语句在改变循环条件。如果循环条件恒为真,则是死循环。 (4)要小心改变循环条件,如果不适当的修改循环条件,则循环将不能按预先的设想进行,程序也达不到预期的效果。 (5)为增加程序的可读性,使程序清晰易懂,必须使用缩格。 (6)关于Exit Do语句使用参见本节后面的内容。
3. 循环结构程序(4) 例6-11:求1加到10的累加和S=1+2+3+…+8+9+10 Public Sub sum_example() Do While i <= 10 '循环条件, 使用缩格,提高可读性 Debug.Print i '此处输出变量i的值是方便理解循环的过程 s = s + i '求累加,即循环不变式 Debug.Print s; '输出s的结果,理解每次累加结果的变化 i = i + 1 '改变循环变量的值 Loop Debug.Print s '循环体外输出结果 End Sub
3. 循环结构程序(5) 循环阅读理解 循环条件是什么? 什么时候进入循环? 什么时候退出循环? 循环体内如何改变循环条件? 循环变量的作用?
3. 循环结构程序(6) 在循环中处理循环不变式的一般结构
3. 循环结构程序(8) 循环结构中的Exit Do命令 Do While <循环条件> <循环体1> If <条件> Exit Do End If <循环体2> Loop
Do Until循环语句 Do Until <条件表达式> <循环体> [Exit Do] Loop
For循环结构程序(10) For循环语句格式: For < 循环变量> = <循环初值> To <循环终值>[ Step <步长> ] <语句块> [Exit For] Next
3. 循环结构程序(11) 例6-15:求N!,即求N的阶乘。 Public Sub 求阶乘() Dim i, n, p As Integer p = 1 n = Val(InputBox("请输入n的值:")) For i = 1 To n Step 1 'Step 1可以省略。 p = p * i '循环不变式,完成累乘。 Next Debug.Print Str(n) & "的阶乘是:" & Str(p) End Sub
While Wend循环语句 While <循环条件> [<语句块>] Wend
例 Public Sub WhileWend() Dim i As Integer Dim s As Double i = 1 While i <= 100 s = s + (-1) ^ (i + 1) / i i = i + 1 Wend Debug.Print "s="; s End Sub
3. 循环结构程序(12) 循环的嵌套 循环体内又嵌套循环的情况称为多重循环或循环嵌套。 处于循环体内的循环称为内循环,处于外层的循环称为外循环。 内外循环的层次必须分明,不允许有交叉现象出现。 内外循环的循环变量不要同名。 在嵌套情况下,Exit Do语句使控制跳到下方离其最近的Loop之后。
3. 循环结构程序(14) 例8-13:打印如图所示对称三角图形,要求第一行的*在第10列。 *** ***** ******* Public Sub 三角状星型输出() Dim i, j As Integer For i = 1 To 4 '控制输出的行数 Debug.Print Tab(11 - i); "*"; '确定每行第一个*所在的列数 For j = 1 To 2 * i - 2 '控制每行除第一个以外的星号的个数 Debug.Print "*"; '输出后继的* Next j Debug.Print '输出另起一行 Next i End Sub * *** ***** ******* Public Sub 三角状星型输出() Dim i, j As Integer For i = 1 To 4 '循环用来控制输出的行数本例为共4行,循环4次 Debug.Print Tab(11 - i); "*"; '确定每行第一个*所在的列数 For j = 1 To 2 * i - 2 '循环次数控制每行除第一个以外的星号的个数 Debug.Print "*"; '输出后继的* Next j Debug.Print '输出另起一行 Next i End Sub
求素数 例8-14:输入一个大于1的正整数,判断该数是否是素数。 要判断x是否能够被3整除 分析:所谓素数又称为质数,是指只能被1和它自身整除的数。 要判断x是否能够被3整除 使用条件表达式:x/3 = int(x/3)。
分析 对于输入的数据x,判断它是否为素数的过程,就是修改上面条件表达式的分母,让分母的数值从2变到x-1,如果分母从2到x-1都不能整除x,则x是素数。 实际上程序可以改进,只需让分母从2变到int(x/2)。
Public Sub 求素数() Dim flag As Boolean Dim i, x As Integer flag = True '设置标志,假定为素数 x = Val(InputBox("请输入整数数据")) '通过循环将x除以2到int(x/2)的数, '如果有整除发生,则x不是素数,退出循环。 For i = 2 To Int(x / 2) If x / i = Int(x / i) Then '另一种条件表达式为x mod i = 0 flag = False Exit For End If Next '下面的if语句为输出结果, '通过判断标志flag来决定x是否为素数。 If flag Then Debug.Print Str(x) + "是素数。" Else Debug.Print Str(x) + "不是素数。" End Sub
6.4 数组的应用 数组在使用之前,必须加以定义,然后才能使用该数组。 数组定义或数组说明语句格式为: DIMENSION <数组名1>(<数值表达式1>[,<数值表达式2>,...]) [,<数组名2>(<数值表达式1>[,<数值表达式2>,...])...]
例子 dimension A(N) dimension B(n,m) B(1,1),B(1,2),...,B(1,m) … A(N-1) A(N) B(1,1),B(1,2),...,B(1,m) B(2,1),B(2,2),...,B(2,m) … B(n,1),B(n,2),...,B(n,m)
例子:排序 例6-21:随机输入N个数据到数组,并对数组的数据进行降序排列。
江西财经大学信息管理学院 《数据库应用》课程组2007 例子:排序程序 Public Sub 数据排序() Dim a(1 to 10), i, j, t As Double For i = 1 To 10 a(i) = Val(InputBox(“请输入数据到数组” & "A(" & i & ")", "数组输入", "1")) Next I '输出排序前结果 Debug.Print a(i); Next i Debug.Print For i = 1 To 10 – 1 '下面为排升序的程序 For j = i + 1 To 10 If a(i) > a(j) Then t = a(i): a(i) = a(j): a(j) = t End If Next j For i = 1 To 10 '输出排序后的结果 End Sub 江西财经大学信息管理学院 《数据库应用》课程组2007
定义数组,输出原始数据 Dim a(1 to 10), i, j, t As Double For i = 1 To 10 a(i) = Val(InputBox("请输入数据到数组" & "A(" & i & ")", "数组输入", "1")) Next i '输出排序前结果 Debug.Print a(i); Debug.Print
例子:排序(3) *下面对数组进行排序 For i = 1 To 10 - 1 For j = i + 1 To 10 If a(i) > a(j) Then t = a(i): a(i) = a(j): a(j) = t End If Next j Next i
例子:排序(4) '输出排序后的结果 For i = 1 To 10 Debug.Print a(i); Next i
VBA程序调试方法 单步执行 查看变量值
习题 编一个程序,将华氏温度F=68度变换成摄氏温度C,并将结果显示出来 以循环方式输出1到10的数字 求0~100之间奇数之和 计算公式为:C=5×(F-32)÷9 以循环方式输出1到10的数字 求0~100之间奇数之和
习题 求S=1!+2!+3!+…+5!的值。 S=2+4+6+…+100 Y=1+1/2+1/3+ … +1/30
习题 学分在12分以下的收费4000元,若超过12学分,则超过部分每学分加收200元,编一个程序计算收费,输入学分U,求应缴学费T 4000+200(U-12) U>12
习题 假定对齐的列为20列,编写程序输出下列二种图形 # ## ### #### ##### ###### # ## ### ####