VBA入门教程

 

1、 语法,编程的基础

1.1 VBA中有哪些数据类型

VBA里的数据类型有:字节型(Byte)、整数型(Integer), 长整数型(Long), 单精度浮点型(Single), 双精度浮点型(Double),货币型(Currency)等等

数据类型类型标识符字节
字符串型 String $ 字符长度0-64500
字节型 Byte 1
布尔型 Boolean 2
整数型 Integer % 2
长整型 Long & 4
单精度型 Single 4
双精度型 Double # 8
日期型 Date 8
货币型 Currency @ 8
小数点型 Decimal 14
变体型 Variant 以上任意类型
对象型 Objecrt 4

2、 存储数据的容器:常量和变量

2.1 声明变量
  • 语法:Dim 变量名 As 数据类型
Dim Str As String  //(Str就是装String类型的数据)
Dim str As String*10 //(表示最多装10个字节数据)

 

使用变量类型声明符(简写模式)如上图所示类型标识符

Dim Str$ (这里$字符串, 原来美元就是一个字符串丫)

  • 声明多个变量(逗号隔开)

    Dim str As String, num As Integer,
    
    • 1

相当于:

Dim str As String
Dim num As Integer

 

  • 如果不指定变量类型

Dim Str (默认是Variant类型)

什么是Variant

所有数据类型统称,它表现所有数据类型,意味它很大(一般不要声明为Variant,你计算都不知道应该给你这个变量分配多少内存,杀鸡焉用牛刀一个道理)

  • 强制声明所有变量

方法一:在模块的第一句手动输入代码:“Option Explicit”,它会强制检查。

方法二:在工具菜单栏中有设置选项,在每一次插入模块自动会添加 Option Explicit

还可以声明变量的作用域(也就是变量在哪里有效)

语法一: Public 变量名 As 数据类型

语法二:Private 变量 As 数据类型

语法三:Static 变量名As 数据类型

例如:

Public str As String 
Private str As String
Static str As String

 

  • 变量的作用域
作用域描述
单个过程  
单个模块  
所有模块  

把数量存储到变量里

2.2 基本数据类型变量赋值
  • 语法 【Let】 变量名称 =数据 (【】表示可以省略)

简写为 变量名称=数据

Option Explicit ‘强制语法检查

Sub 第一个宏()
    Dim str As String     '声明变量名为str,类型为String
	Let str = "一起来学VBA"  '将“一起来学VBA”赋值给str变量,那么str就代表这个字符串
	Range("A1").Value = str   '将字符串转换填充单元格A1
End Sub

 

  • 给对象变量赋值,语法

Set 变量名称 = 对象(Set不能省略)

Option Explicit

Sub 第一个宏()
   Dim rng As Range       '声明一个Range变量,可以表示单元格
   Set rng = Worksheets("Sheet2").Range("A1")  '将工作表Sheet1的A1单元格对象赋值给rng
   rng.Value = "学习VBA就是这么简单"    '这时候rng就代表A1单元格
End Sub

 

2.3 使用常量

常量通常用来存储一些固定的不会被修改的值,如圆周率π,各种税率 (其实就是取有意义变量代替值)

所以只能赋值一次

  • 语法: Const 变量名称 As 数据类型 = 数值

常量作用域类似变量,在过程中定义,过程内可用(本地常量),过程外定义,模块级常量, public + 过程外定义 公共常量

2.4、 使用数组

2.4.1 什么是数组

数组类似你买一盒饼干,分成几个格,每一个的饼都是一样的。

数组特点:

数据共享同一个名称,即数组名
数组有多个同种类型的变量组成
数组中的元素按次序存储在数组中,通过索引号进行区分
数组也是变量

2.4.2 语法:
  • 一维数组

Dim 数组名(a to b) As 数据类型

Dim num (1 to 50) As String (表示50个字符串打包成的数组)。

给数组赋值

num(1) = “1号” (序号为1 放入一个字符串为"1号")

num(2)=“2号” (序号为2 放入一个字符串为 “2号”)

简写 Dim arr(49) As String 相对于 Dim arr(0 to 49) As String (注意是从0开始的)

例子:

Option Explicit

Sub 第一个宏()
  Dim num(1 To 10) As String
  num(1) = "1号"
  num(2) = "2号"
  num(3) = "3号"
  Range("A1") = num(1)
  Range("A2") = num(2)
  Range("A3") = num(3)
End Sub

 

以上是一维数组,就像排队买早餐

  • 二维数组

Dim 数组名(a to b,c to d) As 数据类型

如果要在电影院确定你位置这时候需要二维数组,也就是第几排第几列

Dim 电影院 (1 to 10, 1 to 30) As String (表示电影院10行,每行30十个座位)

简写 Dim 电影院(9, 29) As String (因为从0开始,所以减一)

三维数组类似: 空间坐标, x,y,z轴

Dim 坐标 (1 to 10, 1 to 20, 1 to 2) As String (可以认为是x轴范围1到10, y轴范围为1到20, z轴坐标1到2所组成所有点)

当然还有四维数组、五维数组等等。一般用的最多的只有一、二数组。

2.4.3 声明动态数组

语法: Dim 数组名称 ()

(既然动态,表示刚开始时候不知道到底装多少元素,所以括号里什么也没有写,只知道是数组数据类型)

如果知道确定大小之后可以采用 ReDim (Re 在英语中就是再一次意思) 关键词进行定义大小

代码:

Option Explicit

Sub 统计单元格()
    Dim arr() As String
    Dim n As Long
    '统计A列有多少个非空单元格
    n = Application.WorksheetFunction.CountA(Range("A:A"))
    MsgBox ("A列所有单元格的数量:" & n)
    '重新定义数组大小
    ReDim arr(1 To n) As String
End Sub

 

2.4.4其他常用的创建数组的方式

方法一: 使用Array函数创建数组

语法:Array(元素1,元素2) (注意括号和逗号都是英文,记住一点就是设计涉及软件都是英文的状态的符号,这是也是刚开始最容易犯的错误,怎么也找不到错误的位置)

Option Explicit

Sub ArrayTest()
   Dim arr As Variant
   '将1到10十个自然数赋给数组arr
   arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
   MsgBox "arr数组的第二个元素为(注意编号从0开始):" & arr(1)
End Sub

 

方法二: 使用Split 函数创建数组 (Split:就是分割意思)

语法: Split(“字符串”, “以字符作为分割线”)

Option Explicit

Sub SplitTest()

   Dim arr As Variant

   '利用split 生成数组
   arr = Split("坚持不懈,直到成功", ",")
   MsgBox "arr数组的第二个元素为(注意编号从0开始):" & arr(1)
    
End Sub

 

方法三: 通过Range对象直接创建数组 (Range是VBA用得最多,它代表单元格范围,可以单个,也可以是多个)

Option Explicit

Sub RngArrTest()
   Dim arr As Variant    '定义变量

   arr = Range("A3:C11").Value  '首先将单元A3到C11存到变量arr中

   Range("A13:C17").Value = arr '然后将新的值写入单元格中


End Sub

 

  • UBound和LBound函数 (计算索引值)

用到数组最关心的数组什么时候数组最后一个元素,所有这个用这个函数解决你疑虑

语法: UBound(arr) (upper取第一个字母,表示大,也就是数组最后一个元素的序号是多少)

LBound(arr) (Lower 取第一个字母,表示小, 也就是数组第一个元素的序号是多少)

那么数组中有多少个元素呢?

UBound(arr) - LBound(arr) + 1

Option Explicit

Sub RngArrTest()
   Dim arr(10 To 50)  '定义数组,从10到50
   MsgBox "数组的最大索引号是: " & UBound(arr) & Chr(13) _
    & "数组的最小索引号是:" & LBound(arr) & Chr(13) _
    & "数组的元素个数是:" & UBound(arr) - LBound(arr) + 1


End Sub

 

对于多维数组求索引号

Option Explicit

Sub RngArrTest()
   Dim arr(1 To 10, 1 To 100)  '定义二维数组

   MsgBox "第一维的最大索引号是:" & UBound(arr, 1) & Chr(13) _
    & "第二维的最小索引号是:" & LBound(arr, 2)
    
End Sub

 

Join 函数,(这个函数和Split函数刚好相反,它将字符串连成一个字符串 )

语法: Join (数组 , “连接符”)

Option Explicit

Sub JoinTest()
   Dim arr As Variant, txt As String

   arr = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

   txt = Join(arr, "-")

   MsgBox txt
    
End Sub


 

将数组写入单元格区域

批量写入数据,利用转置(也就是行变成列,列变成行)

Option Explicit

Sub ArrToRng1()
   Dim arr As Variant

   arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

   '将数组批量写入单元格

   Range("A1:A9").Value = Application.WorksheetFunction.Transpose(arr)

   Range("B1:B9").Value = arr

End Sub

 

3、运算符

3.1 算术运算符

3.2 比较运算符

3.3 连接运算符

只有两种 *&* 和 *+*

&: 只能字符串拼接

+:会根据两个表达式判断,如果两个表达式是数字,它会执行加法算法,其他情况和&一样功能字符串拼接

3.4 逻辑运算符

4、条件分支

4.1 方法一:If … then

语法:
if  条件  then

执行语句1  (当条件满足的执行,也就是条件=true)

Else     

执行语句2   (当条件不满足的执行,也就是条件=false)

End if      (结束if语句结构)

 

举例:

Option Explicit
 
Sub iftest()  
   If Range("A1") = "" Then        
        MsgBox "单元格A1为空"   
   Else   
        MsgBox "单元格A1有值"   
   End If
End Sub

 

4.2 方法二:Select Case 语句

语法:
Select Case  值(条件可以数值表达式或字符串表达式)
Case   (含有Is或To 表达式)
语句1                          (上面为true执行) 
Case   (含有Is或To 表达式)
语句2                         (上面为true执行) 
  ......
Case Else 
语句 n
End Select 

案例:

Option Explicit
 
Sub caseTest()
 
  Dim score As String    '定义变量保存结果
  
  Select Case Range("A1")   '获取单元格A1的值
  
  Case Is >= 90
  
    score = "优"
    
  Case Is >= 80
    
    score = "良"
 
  Case Is >= 70
    
    score = "中"
    
  Case Is >= 60
  
    score = "及格"
    
 Case Else
 
    score = "不及格"
    
End Select
 
    Range("B1") = score   '将值写到单元格B1
 
End Sub

5 、循环结构

5.1 方法一:For … Next 语句

语法:

For  循环变量    Step  数字             (Step表示步长,每隔多少数字,这个是可选的)

  循环体

Next     (下一个)

案例:

Option Explicit
 
Sub caseTest()
 
  Dim score As String, i#    '定义变量保存结果,你是否记得#代表整数
  
  For i = 1 To 10 Step 1
  
      Select Case Range("A" & i) '获取单元格Ai的值
      
          Case Is >= 90
          
            score = "优"
            
          Case Is >= 80
            
            score = "良"
        
          Case Is >= 70
            
            score = "中"
            
          Case Is >= 60
          
            score = "及格"
            
         Case Else
         
            score = "不及格"
        
    End Select
     
    Range("B" & i) = score  '将值写到单元格Bi
 
Next i
End Sub

5.2 方法二:Do While

Do  [While  逻辑表达式]    (为true执行,这是可选的)

<循环体>

[Exit Do]        (退出循环)

[循环体]

Loop

备注:“[]” 表示可选

 

案例

Option Explicit
 
Sub caseTest()
 
  Dim score As String, i#    '定义变量保存结果,你是否记得#代表整数
 
 i = 1
 
 Do While Range("A" & i) <> ""  '表示A列直到为空单元格
  
      Select Case Range("A" & i) '获取单元格Ai的值
      
          Case Is >= 90
          
            score = "优"
            
          Case Is >= 80
            
            score = "良"
        
          Case Is >= 70
            
            score = "中"
            
          Case Is >= 60
          
            score = "及格"
            
         Case Else
         
            score = "不及格"
        
    End Select
     
    Range("B" & i) = score  '将值写到单元格Bi
    
    i = i + 1
    
 Loop
 
End Sub

 

5.3 Do Until 语句

#### 语法1:
Do [Until 逻辑表达式]  

<循环体>

[Exit Do]

[循环体]

Loop

备注:“[]” 可选的

##### 语法2:

Do 

<循环体>

[Exit Do]

[循环体]

Loop [Until 逻辑表达式]

 

案例:

Option Explicit
 
Sub caseTest()
 
  Dim score As String, i#    '定义变量保存结果,你是否记得#代表整数
 
 i = 1
 
 Do Until Range("A" & i) = ""  '表示A列直到为空单元格(条件满足是退出循环)
  
      Select Case Range("A" & i) '获取单元格Ai的值
      
          Case Is >= 90
          
            score = "优"
            
          Case Is >= 80
            
            score = "良"
        
          Case Is >= 70
            
            score = "中"
            
          Case Is >= 60
          
            score = "及格"
            
         Case Else
         
            score = "不及格"
        
    End Select
     
    Range("B" & i) = score  '将值写到单元格Bi
    
    i = i + 1
    
 Loop
 
End Sub

 

5.4 For Each … Next 语句

打印工作簿中所有工作表

Option Explicit
 
'打印工作簿中所有工作表 
Sub forEachTest()
 
    Dim sht As Worksheet, i As Integer
    
    i = 1
    
    For Each sht In Worksheets
    
        Range("A" & i) = sht.Name
        
        i = i + 1
        
    Next sht
    
 
End Sub

6 其他的常用语句

6.1 GoTo语句, 让程序转到另一条语句去执行

尽量不要用,虽然用起来灵活,但是可读性差,尽量将GoTo转换成其他结构选择结构和循环结构(所以这里不打算涉及)

6.2 With语句,让代码更加简单

Option Explicit
 
Sub notWithTest()
 
    Worksheets("Sheet2").Range("A1").Font.Name = "仿宋"  '设置字体
    
    Worksheets("Sheet2").Range("A1").Font.Size = 12   '设置字号
    
    Worksheets("Sheet2").Range("A1").Font.Bold = True '字体加粗
    
    Worksheets("Sheet2").Range("A1").Font.ColorIndex = 3 '设置字体颜色
 
    
 
End Sub
 
 
 
Sub withTest()
    
    With Worksheets("Sheet2").Range("A1").Font
    
        .Name = "仿宋"
        
        .Size = 12
        
        .Bold = True
        
        .ColorIndex = 3
        
    End With
 
End Sub

7 Sub过程

语法:
[Private|Public] [Static] Sub 过程名([参数列表])  (如果不写默认是Public, Static表示保存该过程里声明的本地变量)

[语句块]

[Exit Sub]    (退出过程)

[语句块]

End Sub

7.1 过程的调用

###方法一:输入过程名以及参数、参数用逗号隔开

Sub caseTest()
  
 Dim i#    '定义变量保存结果,你是否记得#代表整数
    
For i = 1 To 10 Step 1
  
 rank (i)
  
Next i
 
End Sub
 
 
Sub rank(i)
 
    Dim score As String
    
     Select Case Range("A" & i) '获取单元格Ai的值
        
          Case Is >= 90
            
            score = "优"
              
          Case Is >= 80
              
            score = "良"
          
          Case Is >= 70
              
            score = "中"
              
          Case Is >= 60
            
            score = "及格"
              
         Case Else
           
            score = "不及格"
          
    End Select
    
    Range("B" & i) = score  '将值写到单元格Bi
   
End Sub


###方法二:在过程名称以及参数前使用Call关键字,参数用括号括起来,并用逗号隔开

语法: Call 过程名 [(参数1,参数2,...)]

上面例子只要将 rank(i)   修改成 Call rank(i) 即可

###方法三:利用 Application 对象的Run方法

语法:  Application.Run 表示过程名的字符串(或字符串变量) , 变量一,变量二。。。。

上面例子:将rank(i)  修改成 Application.Run "rank", i

8 自定义函数、Function过程

Function与Sub的区别就是Function有返回值,而Sub没有

语法:

[Public | Private] [Static] Function 函数名([参数列表])     (As 数据类型)

[语句块]

[函数名=过程结果]

[Exit Function]

[语句块]

[函数名=过程结果]

End Function

 

 

案例:

Function countColor(arr As Range, c As Range)
   
    Application.Volatile True
    
    Dim rng As Range
    For Each rng In arr
     
         If rng.Interior.Color = c.Interior.Color Then
         
             countColor = countColor + 1
        
         End If
    
    Next rng
End Function

9代码排版

9.1 更改长行代码为短行代码

采用 “ _” 空格下划线进行换行,多行合并为一行

Sub test()
    Application.Workbooks("Book1").Worksheets("Sheet1") _ 
        .Range("A1:D100").Font.Bold = True
  
End Sub

 

9.2 合并为一行

Sub test()
   Dim a%, b%, c%: a = 1: b = 2: c=3
End Sub

 

10 ASCII码的表格chr()

chr(10)换行符
chr(13) 回车
chr(32) 空格
chr(9) tab
chr(34) 双引号
   
   
   

11 案例分析

11.1 下划线转驼峰命名

Sub 下划线转驼峰()
'获取下划线的值,并全部转换为小写
For i = 1 To 100 Step 1
    If Not IsEmpty(Cells(i, 1)) Then
         x = LCase(Cells(i, 1))
         '按下划线取值
         arr = Split(x, "_")
         For j = 1 To (UBound(arr) - LBound(arr)) Step 1
            Cells(i, 2) = arr(0) & UCase(Left(arr(j), 1)) & Right(arr(j), Len(arr(j)) - 1)
            Cells(i, 3) = UCase(Left(arr(0), 1)) & Right(arr(0), Len(arr(0)) - 1) & UCase(Left(arr(j), 1)) & Right(arr(j), Len(arr(j)) - 1)
         Next
    End If
Next
End Sub

 

posted @ 2023-04-15 21:39  快乐58  阅读(130)  评论(0)    收藏  举报