Sub bijiaotest() Dim num1 AsInteger, num2 AsInteger num1 = 10 num2 = 20 '比较运算符> < >= <= = <> Dim result AsBoolean result = num1 > num2 MsgBox result '结果是0,根据布尔值和integer,False就是0,True是1 '如果Dim result As Boolean,那么就会显示为False result = num1 < num2 MsgBox result '结果是-1 / TRUE '>=,大于或等于,都能成立 result = num1 <= num2 MsgBox result '结果是-1 / TRUE '=,等于,为了方便区分,可以在判断的式子里面加上括号进行区分 result = (num1 * 2 = num2) MsgBox result '结果是-1 / TRUE '<>,不等于 result = num1 <> num2 MsgBox result '结果是-1 / TRUE
Sub ForNextTest() Dim num AsInteger '用法一:连续展示某个信息5次 'num=1表示先设置num变量的值为1,只有在第一次的时候才会进行赋值,后面只会判断是否超出条件(>5) 'to 5 表示,当num > 5 的时候,循环停止 For num = 1To5 MsgBox num & ":循环结构" 'next num表示每次循环num的值加1 'num = num + 1 Next num '第一次循环,Num=1;弹出窗口,显示:1:循环结构;Num=2 '第二次循环,Num=2;弹出窗口,显示:2:循环结构;Num=3 '第三次循环,Num=3;弹出窗口,显示:3:循环结构;Num=4 '第四次循环,Num=4;弹出窗口,显示:4:循环结构;Num=5 '第五次循环,Num=5;弹出窗口,显示:5:循环结构;Num=6;6 > 5,循环结束
'用法二:计算1~100的求和结果 '如果求和结果过大,可以把total改成long Dim total AsInteger total = 0 For num = 1To3 total = total + num Next num MsgBox total
EndSub
Step的应用场景
控制变量在每次循环的时候,加多少的值,不加默认加1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
OptionExplicit Sub StepTest() Dim num AsInteger, total AsInteger '计算1~100里面的奇数求和结果 '1+3+5+7+……+99 'step 2 ,就是每次next num,每次加2的意思 '不写step 2 ,就是默认每次+1 For num = 1To100Step2 total = total + num Next num MsgBox total EndSub
如何中断For循环
Exit For:这句话作用就是满足条件时退出for循环,一般搭配 If 来用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
OptionExplicit Sub StepTest() Dim num AsInteger, total AsInteger '让For循环中途退出 '计算1~50相加的结果,但是前面还是写的1到100 For num = 1To100 If num > 50Then 'Exit For:这句话作用就是满足条件时退出for循环,一般搭配if来用 ExitFor EndIf total = total + num Next num MsgBox num MsgBox total EndSub
嵌套for循环
大循环执行一次,小循环可能执行好几次
不建议嵌套3次for循环,一般只嵌套两次for循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
OptionExplicit
Sub ForForNextTest() Dim num1 AsInteger, num2 AsInteger Dim total AsLong For num1 = 1To3 For num2 = 1To3 total = total + num1 * num2 Next num2 Next num1
'子过程(子函数、子程序) Sub SubTest() '包裹了一系列的指令代码, Dim num AsInteger, total AsInteger For num = 1To10 total = total + num Next num MsgBox total ExitSub '表示中断这个子程序的执行 '后面的代码不会再执行了 MsgBox total EndSub
上面的代码,For num = 1 To 10,若是想要这个10变成一个可变的数字,可以在Sub SubTest()的括号里,声明一个参数,这个参数就是变量。所以可以改成Sub SubTest(ToNum As Integer),此时就可以把下面的改成For num = 1 To ToNum,这时就获得了一个有参数的子过程,也就可以调用这个子过程,并且传入一个参数,那执行的时候,传入的值就会替换掉ToNum。
如何调用这种有参数的子过程?——可以再去写一个子过程Sub Test()(无参数),来进行调用。
可以多次计算,1到10,1到100,1到1000,的结果。
这样就无需修改第一部分Sub SubTest(ToNum As Integer)的代码,因为有时含有参数的子程序会非常长,若是每次都要去代码内部修改,很有可能会出错(误删代码or修改错误),风险较高;所以我们就把固定功能的代码,保持不动,只需要把参数进行调整、传入进去。
Sub SubTest(ToNum AsInteger, AddStep AsInteger) Dim num AsInteger, total AsLong For num = 1To ToNum Step AddStep total = total + num Next num MsgBox total ExitSub
Sub ArrayTest() '声明定义一维数组 Dim MyArray(0To2) AsInteger '为一维数组赋值 MyArray(0) = 0 MyArray(1) = 100 MyArray(2) = 200 '访问某一个模块中的数据 MsgBox MyArray(2) '遍历方式访问一维数组 Dim index AsInteger For index = 0To2 MsgBox MyArray(index) Next index 'LBound表示数组的最小的角标 'UBound表示数组的最大的角标 'lower,upper '这种方法的优点在于,如果后期数组增级了个数,那么遍历数组的时候,就不需要修改循环的条件了 For index = LBound(MyArray) To UBound(MyArray) MsgBox MyArray(index) Next index EndSub
Sub ArrayTest2() '声明定义一维数组 '若没有指定最小的角标,就默认最小角标为0;我们设置的数字,就是最大的角标 'Dim MyArray(3) As Integer就相当于Dim MyArray(0,3) As Integer '======== '如果加上了Option Base 1,就表示Dim MyArray(3) As Integer是从1开始,相当于Dim MyArray(1,3) As Integer '这时那么如果有MyArray(0) = 100在,就会报错“下标越界”,必须删去or注释掉这一行
Dim MyArray(3) AsInteger 'MyArray(0) = 100 MyArray(1) = 200 MyArray(2) = 300 MyArray(3) = 400 Dim index AsInteger For index = LBound(MyArray) To UBound(MyArray) MsgBox MyArray(index) Next index EndSub
Sub MyDynArray() '定义一个一维动态数组,括号空的 Dim MyDynArray() AsInteger 'redim:明确动态数组的最小角标和最大角标 ReDim MyDynArray(1To3) '为一维动态数组进行赋值 MyDynArray(1) = 100 MyDynArray(2) = 200 MyDynArray(3) = 300 'for循环,遍历数组 Dim index AsInteger ' For index = LBound(MyDynArray) To UBound(MyDynArray) ' MsgBox MyDynArray(index) ' Next index '可以通过redim多次调整角标 '又一次使用了redim,对这个数组的角标进行了调整,调整成了1-4; '注意!!!redim调整动态数组的时候,之前的赋值都会自动抹除,即为0 '
ReDim MyDynArray(1To4) '如果需要保留之前的赋值,就在redim后面加一个Preserve '加一个Preserve,就可以保留历史的赋值数据 '如果要运行查看效果,需要将上面未加preserve的代码注释掉 ReDimPreserve MyDynArray(1To4) '如果只对4位置进行赋值400,那么位置1-3的值就会是0 MyDynArray(4) = 400 For index = LBound(MyDynArray) To UBound(MyDynArray) MsgBox MyDynArray(index) Next index EndSub
Sub ForEachTest() 'for循环时,遍历的都是一些基本的数据类型,比如整数、小数、文本、日期等等 '遍历对象,需要用for each '操作方法类似 Dim book As Workbook 'workbook 既是对象,也可以是一种数据类型——工作簿类型 ForEach book In Workbooks 'for each表示遍历,workbooks表示现在打开的所有工作簿 '也就是去遍历每一个打开的工作簿,每一个工作簿的名称都会赋值给变量book MsgBox book.Name Next book
Sub ForEachTest2() Dim sheet As Worksheet '定义一个变量,为Worksheet类型 ForEach sheet In Worksheets 'Worksheets表示:当前工作簿中的这些工作表 '遍历工作表,并且把每个工作表赋值给变量sheet MsgBox sheet.Name Next sheet EndSub
Sub ForEachTest3() Dim cell As Range ' '方法一:for each ' For Each cell In Range("A5:A10") ' MsgBox cell.Value ' '如果不想弹窗太多,可以把数据范围弄小一点 ' Next cell ' '方法二:for循环 Dim index AsInteger, RowIndex AsInteger, ColumnIndex AsInteger Dim Rng As Range Set Rng = Range("A5:A10") 'Set的应用:这里的Rng是个对象类型 For RowIndex = 1To Rng.Rows.Count 'Rng.Rows.Count:表示的是Range("A5:A10"),这里面有多少行,即行的数量 For ColumnIndex = 1To Rng.Columns.Count '可以弹窗显示 'MsgBox Rng.Cells(RowIndex, ColumnIndex) '弹窗显示如果很多,就可以把这部分数据安排到别的单元格区域去 Range("C14").Offset(RowIndex, ColumnIndex) = Rng.Cells(RowIndex, ColumnIndex)
Sub StringTest2() Dim str AsString str = "本节课是关于字符串的拆分" ' 'left,mid,right函数 ' Debug.Print VBA.Left(str, 3) ' Debug.Print VBA.Right(str, 3) ' '2个参数,表示截取哪个字符串,要从左/右截取字符串的长度 ' ' Debug.Print VBA.Mid(str, 4) '第3个参数,不填默认从指定的字符串开始,往后的所有内容都会获取到 ' Debug.Print VBA.Mid(str, 4, 3) '第3个参数,填了就表示,从第4个文字开始,想要获取几个长度的文字 ' ' ' ' ' '有固定放分隔符,需要定义一个数组,由于不知道长度,就是不知道会拆分成几个,就定义1个动态数组 ' Dim SplitStr() As String ' str = "ACV-KJH-OMS-LLX" ' ' 'split函数:根据特定的字符对文本字符串进行拆分 ' SplitStr = Split(str, "-", 2) ' '第1个参数表示,需要进行拆分的字符串 ' '第2个参数表示,根据哪个分隔符拆分 ' '第3个参数表示,我们想要把这个文本的字符串,想要拆分成几份,那么在从左往右拆分时,已拆到这个数量时,就不继续拆分,即使后面还有这个拆分符;不填的话就是有多少拆多少 ' '第4个参数,有3中可选,我们这里进行更加详细的说明 ' ' ' '想要展示数组,需要通过for循环,遍历数组内容 ' Dim index As Integer ' For index = LBound(SplitStr) To UBound(SplitStr) ' Debug.Print SplitStr(index) ' Next index ' ' '第4个参数就表示,假如是用英文字母做拆分符号,那么是否采用大小写敏感 str = "JKavcFGAJKLAHYH" '这个字符串里,有大写的A和小写的a '假定我们就用字母Dd,把这个文本的字符串进行拆分 '大小写敏感,表示和大小写相关,那么只会对A进行拆分,a不进行拆分 'SplitStr = Split(str, "A", , vbBinaryCompare) '与数据库有关,目前暂时不学习,目前只涉及到excel,而不是数据库 'SplitStr = Split(str, "A", , vbDatabaseCompare) '大小写不敏感,表示和大小写吧相关,A和a都会进行拆分 SplitStr = Split(str, "A", , vbTextCompare) '想要展示数组,需要通过for循环,遍历数组内容 Dim index AsInteger For index = LBound(SplitStr) To UBound(SplitStr) Debug.Print SplitStr(index) Next index EndSub
拆分字符串应用案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Function GetOrderPart(OrderInfoRange As Range, index AsInteger) '编写一个子函数,函数名是GetOrderPart,"意思是获得订单编号对应部分“; '订单编号是类似ABC-123-jlj这样的数据 '第一个参数:设置了1个range类型的变量作为参数,指引用的单元格,也就是想要用短横线作为分隔符的原始数据/针对哪个单元格中的内容进行拆分 '第二个参数:用短横线作为分隔符,拆分后的字符串会有好几个,我们想要输出其中的第几个
'想要查找字母d出现的次数 Dim index AsInteger, count AsInteger index = 1 '只要还有“d”存在,就继续执行 While index <> 0 '不加这段代码的话,档要查找的字符串是整个字符串的第一个字母的时候,会有bug '因为是从整个字符串的第二个字母开始查找的,那么第一个位置的字符串就会查找不到 If count = 0Then index = 0 EndIf
'从上一次查找到的位置的右边开始,继续查找“d”的位置 index = InStr(index + 1, str, "A", vbBinaryCompare) '如果不为0,就继续查找 If index <> 0Then count = count + 1 EndIf Debug.Print index Wend Debug.Print "Count=" & count
Sub ExceptionTest1() Dim Num As Variant Num = InputBox("请输入一个数字:") '输出输入的数字的平方根 ' Debug.Print VBA.Sqr(Num) '假如输入的是负数/文本/空值,就会报错 '思路一:用if和msgbox If Num < 0Then MsgBox "请不要输入负数" ElseIfNot VBA.IsNumeric(Num) Then MsgBox "请输入数字" Else Debug.Print VBA.Sqr(Num) EndIf ' EndSub
Sub ExceptionTest2() Dim Num As Variant '如果出现错误,就跳过其他代码,直接跳转到相应标签 '如果没有这行代码,那么输入负数/文本/空值时,就会提示错误 OnErrorGoTo ErrorHandler Num = InputBox("请输入一个数字:") Debug.Print VBA.Sqr(Num) '没有错误,不再显示错误信息 '如果没有这段代码,那么输入正数时,代码运行没有任何错误时,也会弹窗“请确认输入一个正数” ExitSub ErrorHandler: MsgBox "请确认输入一个正数" EndSub
Sub ExceptionTest3() Dim Num As Variant '出现错误,跳过继续执行;可以跳过不止一次 '没有这段代码,代码执行会报错;加上这段代码,就代码不会报错,只是继续往下执行:弹窗“异常” OnErrorResumeNext Num = InputBox("请输入一个数字:") Debug.Print VBA.Sqr(Num) ExitSub MsgBox "VBA异常处理1" '如果不想要下面的代码出现错误时,和上面是一样的处理方式,那么就用这段代码 '重置错误默认处理方式 OnErrorGoTo0 Debug.Print 1 / 0'不会在立即窗口出现结果,因为有上面的代码,所以出现错误就跳过了,继续执行接下来的代码 MsgBox "VBA异常处理2" EndSub
OptionExplicit Sub DebugTest1() '编译错误 '查看代码,确保代码语法没有问题 '比如这里少了个括号或者英文引号之类的 Range("A1").Value = 100 EndSub
Sub DebugTest2() '运行时错误 '执行代码的时候,如果代码行数很多,遇到了“运行时错误”,且不知道哪一行代码错了 '1. 可以点击【调试】按钮,它会提示你哪一行代码错了 '2. 还可以通过注释某一行代码的方式,去缩小错误排查范围 '3. 也可以通过逐语句执行的方式 Dim Num AsInteger For Num = 1To10 Range("A" & Num).Value = Num * 100 Range("A" & Num).Interior.Color = vbRed Next Num EndSub
Sub DebugTest3() '1. 明确非常常见的错误:程序没有语法错误,而是程序执行的结果并没有出现预期的结果,逻辑性错误。 '2. 针对程序的逻辑性错误,就需要通过变量或者表达式在执行的过程中的内容判定逻辑问题出在哪里。 '3. 有三种方式查看变量的内容。本地窗口、监控窗口、立即窗口 '4. 打断点:希望程序在哪个位置停止运行,方便我们查看当前状态下的变量以及表达式的内容。 '1. 可以逐行写注释,来展示思路 '2. 还可以通过打断点的方式,就是在这行代码的左侧,点一下红色,会有个红点 '这个红点的意思就是:程序运行时,到达这个断点之后,就停止了运行,可以查看到达这个断点的时候,各个变量的数值是多少(有点麻烦) '3. 想要看到各个变量的值,还可以去【视图-本地窗口】,可以看到当前的子程序中,所有的相关的变量所发生的变化 '4. 【视图-立即窗口】,输入【?Num1】,然后回车,可以展示当前变量的值 '5. 【视图-监视窗口】,可以指定想要监视某个变量,比如想要监视变量num1,就鼠标点在num1处,右击,点击“添加监视”; '【监视窗口】,除了可以监视变量,还可以监视表达式,比如想要监视【Num1 * Num2】的结果,就鼠标左键选中代码中的Num1 * Num2,然后右击“添加监视”;监视【Num2 & "*" & Num1 & "=" & (Num1 * Num2)】也可以 Dim Num1 AsInteger, Num2 AsInteger '将num1作为行数 For Num1 = 1To9 '将num2作为列数 For Num2 = 1To9 '只有行数大于列数的时候,才会执行相应的内容设置代码 If Num1 >= Num2 Then '设置相应单元格的内容 Cells(Num1, Num2) = Num2 & "*" & Num1 & "=" & (Num1 * Num2) EndIf Next Num2 Next Num1 EndSub
Sub MsgBoxTest() '参数一:prompt,作用就是设置弹出的窗口的内容 'MsgBox "VBA is very useful" '参数二:图标 + 按钮 + 默认按钮 'MsgBox "VBA is very useful?", vbYesNo + vbQuestion + vbDefaultButton2
'参数三:设置弹出的窗口的标题 MsgBox "VBA is very useful?", vbYesNo + vbQuestion + vbDefaultButton2, "询问" EndSub
Sub InputboxTest() Dim name AsString name = InputBox("请输入你的名字", "输入个人信息", "吴明") If name = ""Then MsgBox "请务必输入自己的姓名", vbExclamation, "警告" Else Range("A1").Value = name EndIf EndSub
' 输入数字,就生成多少个新sheet Sub AddWorksheet() Dim result AsString result = InputBox("请问想要输入几张工作表", "输入数字", "1") If result = ""Then MsgBox "清确定已经录入数字并点击确定按钮", vbExclamation, "说明" Else ' input返回的值的类型是文本类型,但是sheets对象的add方法的count参数需要整数类型 ' 方法一:隐式类型转换 ' result存储的内容是文本类型,但是它默认转换为了整数类型 'Sheets.Add Count:=result ' 方法二:显式类型转换【更推荐】 'VBA.CInt(result)可以把result转换为整数类型,然后再传递给count这个参数 Sheets.Add Count:=VBA.CInt(result) EndIf EndSub
Sub InputboxTest1() Dim num AsInteger '在Excel中创建一个简单的输入框,要求用户输入一个数字,并在用户输入后在一个消息框中显示该数字。 '使用application下的InputBox的好处在于有一个type函数 '存在内置的数据验证 '1——数字 num = Application.InputBox(prompt:="请输入一个数字", Type:=1) MsgBox num EndSub
Sub InputboxTest2() Dim rangeselected As Range '8——range对象形式的单元格引用 Set rangeselected = Application.InputBox(prompt:="选择单元格区域", Type:=8) '设置选择的单元格区域样式 rangeselected.Interior.Color = vbRed '弹窗之后可以直接选中单元格区域,会自动识别出【$D$28:$D$31】这样的编码 EndSub
Sub InputboxTest4() Dim rangeselected As Range '0——公式 '8——range对象形式的单元格引用 Set rangeselected = Application.InputBox(prompt:="选择单元格区域", Type:=8) '设置单元格区域中每一个单元格的公式 rangeselected.FormulaLocal = Application.InputBox(prompt:="请输入公式", Type:=0) EndSub
Sub InputboxTest5() '64——数组 Dim Nums As Variant Nums = Application.InputBox(prompt:="选择转换为数组的区域", Type:=64) '可以用二维,但是这里写的是一维 Dim index AsInteger For index = LBound(Nums, 1) To UBound(Nums, 1) Debug.Print Nums(index, 1) Next index EndSub