专业的编程技术博客社区

网站首页 > 博客文章 正文

VBA|正确使用过程和自定义函数(vba 定义)

baijin 2024-11-08 10:20:57 博客文章 3 ℃ 0 评论

过程是一个VBA语句块,包含在声明语句(Function、Sub、Get和Set)和匹配的End声明中。

VBA中的所有可执行语句都必须位于某个过程内。可以将整个应用程度编写为单个大的过程,但如果将它分解为多个较小的过程,代码就更容易阅读和理解。

1 VBA过程类型

1.1 VBA子过程:用于执行代码后不返回值的情况。它们以关键字Sub开头,并以关键字End Sub结束。在Excel中录制的宏就是这种过程。

1.2 Function函数过程:用于执行代码后返回计算结果的情况。它们以关键字Function开头,以关键字End Function结束。使用Function函数过程可创建Excel的扩展函数。

1.3 Property过程:用于自定义对象。使用属性过程可设置和获取对象属性的值,或者设置对另外一个对象的引用。

2 VBA子过程与Function函数过程的区别

2.1 Sub子过程不能返回值,而Function函数过程可以返回一个值,因此可以像Excel内部函数一样在表达式中使用Function函数。

2.2 Sub过程可作为Excel中的宏来调用,而Function函数不会出现在“选择宏”对话框中,如果要在工作表中调用Function函数,则可以像使用Excel内部函数一样使用该函数。

2.3 在VBA中,Sub过程可作为独立的基本语句调用,而Function函数通常作为表达式的一部分。

3 Sub过程结构

[Private | Public | Friend] [Static] Sub 过程名 [(参数列表)]

[语句序列1]

[Exit Sub]

[语句序列2]

End Sub

如:

Sub 手工创建Sub过程()

MsgBox "这是手工输入代码创建的Sub过程!"

End Sub

4 Function函数的语法结构

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

[语句序列1]

[函数名=表达式1]

[Exit Function]

[语句序列2]

[函数名=表达式2]

End Sub

如:

Function fTest1(a As Integer, b As Integer) As Integer

Dim t As Integer

Randomize

If a > b Then

t = a

a = b

b = t

End If

fTest1 = Int(Rnd * (b - a)) + a

End Function

5 Sub子过程调用

5.1 用Call语句调用

Call 过程名(过程参数列表) ‘没有参数,可以写成:Call 过程名

5.2 将过程作为一个语句

Call Test(a,b)

Call Test a, b

6 调用Function函数过程

6.1 在工作表的公式中调用

“公式”选项卡→“插入函数”→在”或选择类别“选择框内选择”用户定义“,即可看到自定义的函数,如下:

6.2 在VBA代码中调用

在VBA代码中,可以像VBA内部函数一样调用这种用户自定义的Function函数。

Sub 生成随机数()

Dim R As Integer, l As Integer, u As Integer

l = Val(InputBox("请输入随机数的下限:", "设置下限", 1))

u = Val(InputBox("请输入随机数的上限:", "设置上限", 100))

R = fTest1(l, u)

MsgBox "生成的随机数为:" & R

End Sub

7 过程参数的形参与实参结合的方式

7.1 按位置结合

Function fTest1(a As Integer, b As Integer) As Integer

...

End Function

Call fTest1(1,100)

7.2 按命名参数方式结合

Call fTest1(a:=1,b:=100) '两个参数的位置可以随意

7.3 按位置和名称混合结合参数

Call fTest1(1,b:=100)

8 过程参数传递方式(传值或传地址)

在VBA中,实参可通过传值和传地址两种方式将数据传递给形参。

定义过程时,在形参的前面添加ByVal关键字,则该参数就按传值方式传递;否则就按传地址(默认)方式传递。

8.1 按传值方式传递参数

Sub 传值测试(ByVal a As Integer)

a = a + 1

Debug.Print "子过程中的变量A=" & a

End Sub

Sub 调用传值测试()

Dim b As Integer

b = 3

Debug.Print "主程序中变量B=" & b

传值测试 b

Debug.Print "主程序中变量B=" & b

End Sub

上述代码在“立即窗口”中的显示结果:

主程序中变量B=3

子过程中的变量A=4

主程序中变量B=3

由上面的结果可知,值并没有真正传递过去。

8.2 按传地址方式传递参数

Sub 传地址测试(ByRef a As Integer)

a = a + 1

Debug.Print "子过程中的变量A=" & a

End Sub

Sub 调用传地址过程()

Dim b As Integer

b = 3

Debug.Print "主程序中变量B=" & b

传地址测试 b

Debug.Print "主程序中变量B=" & b

End Sub

上述代码在“立即窗口”中的显示结果:

主程序中变量B=3

子过程中的变量A=4

主程序中变量B=4

9 数组作为参数

Sub 求最大数(a() As Integer)

Dim i As Integer, max As Integer

max = a(LBound(a))

For i = LBound(a) To UBound(a)

If a(i) > max Then max = a(i)

Next

Debug.Print "最大数:" & max

End Sub

Sub 测试求最大数()

Dim MyArray(5) As Integer, i As Integer

For i = 0 To 5

MyArray(i) = i * 2

Next

求最大数 MyArray()

End Sub

10 设置可选参数

“可选参数”在过程定义中由关键字Optional指示:

Sub 可选参数(strName As String, strSex As String, Optional ID)

With Worksheets("sheet3")

.Range("A2") = strName

.Range("B2") = strSex

If Not IsMissing(ID) Then

.Range("C2") = ID

End If

End With

End Sub

Public Sub 调用可选参数过程1()

可选参数 "wwu", "male"

End Sub

Public Sub 调用可选参数过程1()

可选参数 "wwu", "male", "2012"

End Sub

11 设置可变参数

“可变参数”在过程定义中由关键字ParamArray和一个Variant数组定义:

Sub MySum(intTotal As Integer, ParamArray intNum())

Dim i As Integer, j As Integer

For i = LBound(intNum) To UBound(intNum)

intTotal = intTotal + intNum(i)

Next

End Sub

Sub 调用可变参数()

Dim i As Integer

MySum i, 1, 2, 3, 4, 5, 6, 7, 8

Debug.Print i

End Sub

12 过程的递归调用

“递归”过程是指调用自身的过程。在递归调用中,一个过程执行的某一步要用到它自身的上一步(或上几步)的结果。

Function fact(ByVal n As Integer) As Long

If n <= 1 Then

fact = 1

Else

fact = fact(n - 1) * n

End If

End Function

Sub test()

Debug.Print fact(8)

End Sub

13 常用过程实例

13.1 计算个人所得税


个人所得税税率表(3500起征)





级数全月应纳税所得额税率速算扣除数(元)
1全月应纳税额不超过1500元3%0
2全月应纳税额超过1500元至4500元10%105
3全月应纳税额超过4500元至9000元20%555
4全月应纳税额超过9000元至35000元25%1005
5全月应纳税额超过35000元至55000元30%2755
6全月应纳税额超过55000元至80000元35%5505
7全月应纳税额超过80000元45%13505

Public Function taxes(curP As Currency, Optional dep As Integer = 3500)

Dim curT As Currency

curP = curP - dep '3500为扣除数

If curP > 0 Then

Select Case curP

Case Is <= 1500

curT = curP * 0.03

Case Is <= 4500

curT = curP * 0.1 - 105

Case Is <= 9000

curT = curP * 0.2 - 555

Case Is <= 35000

curT = curP * 0.25 - 1005

Case Is <= 55000

curT = curP * 0.3 - 2755

Case Is < 80000

curT = curP * 0.35 - 5505

Case Else

curT = curP * 0.45 - 13505

End Select

taxes = curT

Else

taxes = 0

End If

End Function

公式对应值
=taxes(4000)15
=taxes(7000)245
=taxes(4000,5000)0
=taxes(7000,5000)95

13.2 将数值转换为表格的列号

Public Function NumtoCol(Numbers As Integer) As String

Dim i1 As Integer, i2 As Integer, i3 As Integer

Dim s1 As String, s2 As String, s3 As String

i2 = Numbers \ 26

i3 = i2 \ 26 '第3位

i2 = i2 Mod 26 '第2位

i1 = Numbers Mod 26 '第1位

If i2 > 0 And i1 = 0 Then

i1 = 26

i2 = i2 - 1

End If

If i3 > 0 And i2 = 0 Then

i2 = 26

i3 = i3 - 1

End If

s3 = Chr(i3 + 64)

s2 = Chr(i2 + 64)

s1 = Chr(i1 + 64)

If s3 = "@" Then

If s2 = "@" Then

NumtoCol = s1

Else

NumtoCol = s2 & s1

End If

Else

NumtoCol = s3 & s2 & s1

End If

End Function

Sub 显示列号()

With Worksheets("sheet1")

.Activate

.Range("AZ1").Select

End With

MsgBox Selection.Column

End Sub

Sub 测试显示列号()

Dim intCol As Integer

intCol = Val(InputBox("请输入列号(1~16384):"))

If intCol < 1 Or intCol > 16384 Then

MsgBox "输入的数据超过范围,请重新输入!"

Exit Sub

End If

MsgBox "列号:" & intCol & ",对应的字母为:" & NumtoCol(intCol)

End Sub

13.3 大写金额转换函数

Function CapsMoney(curMoney As Currency) As String '转换中文大写金额函数

Dim curMoney1 As Long

Dim i1 As Long '保存整数部分(元部分)

Dim i2 As Integer '保存十分位(角部分)

Dim i3 As Integer '保存百分位(分部分)

Dim s1 As String, s2 As String, s3 As String '保存转换后的字符串

curMoney1 = Round(curMoney * 100) '将金额扩大100倍,并进行四舍五入

i1 = Int(curMoney1 / 100) '获取元部分

i2 = Int(curMoney1 / 10) - i1 * 10 '获取角部分

i3 = curMoney1 - i1 * 100 - i2 * 10 '获取分部分

s1 = Application.WorksheetFunction.Text(i1, "[dbnum2]")

'将元部分转为中文大写

s2 = Application.WorksheetFunction.Text(i2, "[dbnum2]")

'将角部分转为中文大写

s3 = Application.WorksheetFunction.Text(i3, "[dbnum2]")

'将分部分转为中文大写

s1 = s1 & "元" '整数部分

If i3 <> 0 And i2 <> 0 Then '分和角都不为0

s1 = s1 & s2 & "角" & s3 & "分"

If i1 = 0 Then '元部分为0

s1 = s2 & "角" & s3 & "分"

End If

End If

If i3 = 0 And i2 <> 0 Then '分为0,角不为0

s1 = s1 & s2 & "角整"

If i1 = 0 Then '元部分为0

s1 = s2 & "角整"

End If

End If

If i3 <> 0 And i2 = 0 Then '分不为0,角为0

s1 = s1 & s2 & s3 & "分"

If i1 = 0 Then '元为0

s1 = s3 & "分"

End If

End If

If Right(s1, 1) = "元" Then s1 = s1 & "整" '为"元"后加上一个"整"字

CapsMoney = s1

End Function

-End-

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表