函数是一段可重复使用的代码块,用于执行特定任务并返回一个值
函数的基本结构
Function AddNumbers(a As Integer, b As Integer) As Integer
'函数名:Addnumbers
'参数:a和b都是整数
'返回值:整数
'计算两个数的和
AddNumbers = a + b
End Function
Sub UseFunction()
Dim result As Integer
'调用AddNumbers函数
result = AddNumbers(2, 3)
'显示结果
MsgBox result
End Sub
1.调用工作表函数进行 求和/查找最大值最小值
在对工作表的单元格区域进行求和计算时,使用干工作表Sum函数比使用VBA代码遍历单元格进行累加求和效率要高得多
Sub UseSumFunction()
Dim total As Double
Dim rng As Range
' 设置要计算的范围
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1:A100")
' 使用WorksheetFunction对象调用SUM函数
total = Application.WorksheetFunction.Sum(rng)
'这里的Sum也可以换成其他Excel自带函数,比如Max/Min等
' 显示结果
MsgBox "The sum is: " & total
End Sub
2.不重复的录入
在工作表中录入数据时,有时希望能限制重复值的录入,比如在A列单元格只能录入唯一的编号,此时可以利用工作表的Change事件结合工作表的CountIf函数来判断所录入的人员编号是否重复
Private Sub Worksheet_Change(ByVal Target As Range)
' 声明变量
Dim rng As Range
' 检查是否只有一个单元格被改变,且在A列
If Target.Cells.Count > 1 Or Target.Column <> 1 Then Exit Sub
' 设置要检查的范围(A列)
Set rng = Me.Range("A:A")
' 检查输入值是否在A列中重复
If Application.CountIf(rng, Target.Value) > 1 Then
' 如果重复,显示消息框
MsgBox "不能输入重复的编号!", 64
' 禁用事件以避免无限循环
Application.EnableEvents = False
' 清除输入的值
Target.Value = ""
' 重新启用事件
Application.EnableEvents = True
End If
End Sub
3.获得当月的最后一天
在实际工作中经常需要根据给定的日期计算其所属月份的最后一天,此时可以使用DateSerial函数完成计算
这个函数的一个特殊用法是,当我们将”日”参数设为0时,它会返回上个月的最后一天。我们可以利用这个特性来获取当月的最后一天。
Sub Serial()
' 声明变量
Dim DateStr As String
' 使用DateSerial函数计算当月最后一天
DateStr = Day(DateSerial(Year(Date), Month(Date) + 1, 0))
' 显示结果
MsgBox "本月的最后一天是" & Month(Date) & "月" & DateStr & "号"
End Sub
4.进行四舍五入计算
可以使用VBA内置的Round函数
Round函数返回一个数值,该数值是按照指定的小数位数进行四舍五入运算的结果
Round的基本语法是:
Round(number, num_digits)
number表示要四舍五入的数字
num_digits表示要保留的小数位数,默认为0
Sub DemonstrateRounding()
' 声明变量
Dim originalNumber As Double
Dim roundedNumber As Double
' 示例 1: 四舍五入到整数
originalNumber = 3.7
roundedNumber = Round(originalNumber)
Debug.Print "3.7 四舍五入到整数: " & roundedNumber ' 输出: 4
' 示例 2: 四舍五入到一位小数
originalNumber = 3.14159
roundedNumber = Round(originalNumber, 1)
Debug.Print "3.14159 四舍五入到一位小数: " & roundedNumber ' 输出: 3.1
' 示例 3: 四舍五入到两位小数
originalNumber = 2.718
roundedNumber = Round(originalNumber, 2)
Debug.Print "2.718 四舍五入到两位小数: " & roundedNumber ' 输出: 2.72
' 示例 4: 处理负数
originalNumber = -4.5
roundedNumber = Round(originalNumber)
Debug.Print "-4.5 四舍五入到整数: " & roundedNumber ' 输出: -5
' 示例 5: 四舍五入到十位
originalNumber = 1234
roundedNumber = Round(originalNumber, -1)
Debug.Print "1234 四舍五入到十位: " & roundedNumber ' 输出: 1230
End Sub
5.常用的字符串函数
Len(Str)
功能:返回字符串的长度(字符数)。
例如:Len(“AbcD EFG hijk Lmn”) 将返回 16。
Left(Str, 8)
功能:返回字符串左边指定数量的字符。
例如:Left(“AbcD EFG hijk Lmn”, 8) 将返回 “AbcD EFG”。
Right(Str, 6)
功能:返回字符串右边指定数量的字符。
例如:Right(“AbcD EFG hijk Lmn”, 6) 将返回 “k Lmn”。
Mid(Str, 2, 5)
功能:从指定位置开始,返回字符串中指定数量的字符。
例如:Mid(“AbcD EFG hijk Lmn”, 2, 5) 将返回 “bcD E”。
UCase(Str)
功能:将字符串转换为大写。
例如:UCase(“AbcD EFG hijk Lmn”) 将返回 “ABCD EFG HIJK LMN”。
LCase(Str)
功能:将字符串转换为小写。
例如:LCase(“AbcD EFG hijk Lmn”) 将返回 “abcd efg hijk lmn”。
6.使用日期函数
Date函数返回当前系统日期
currentDate = Date()
Now函数返回当前的日期和时间
currentDateTime = Now()
Yea,Month,Day函数返回年月日
Sub ShowDateComponents()
Dim someDate As Date
someDate = #1/15/2023#
MsgBox "年: " & Year(someDate) & vbNewLine & _
"月: " & Month(someDate) & vbNewLine & _
"日: " & Day(someDate)
End Sub
DateAdd函数向日期添加指定的时间间隔
语法:DateAdd(interval,number,date)
Sub AddToDate()
Dim startDate As Date
startDate = #1/1/2023#
MsgBox "30天后: " & DateAdd("d", 30, startDate) & vbNewLine & _
"2个月后: " & DateAdd("m", 2, startDate) & vbNewLine & _
"1年后: " & DateAdd("yyyy", 1, startDate)
End Sub
DateDiff函数计算两个日期之间的时间间隔
语法:DateDiff(interval,startdate,enddate)
Sub CalculateDateDifference()
Dim date1 As Date, date2 As Date
date1 = #1/1/2023#
date2 = #12/31/2023#
MsgBox "相差的天数: " & DateDiff("d", date1, date2) & vbNewLine & _
"相差的月数: " & DateDiff("m", date1, date2) & vbNewLine & _
"相差的周数: " & DateDiff("ww", date1, date2)
End Sub
DateSerial函数根据指定的年月日创建日期
语法:DateSerial(year,month,day)
Sub CreateDate()
Dim newDate As Date
newDate = DateSerial(2023, 12, 31)
MsgBox "创建的日期: " & newDate
End Sub
WeekDay函数返回表示一周中某一天的数字(1-7)
星期日表示1
语法:WeekDay(date,[firstdayofweek])
Sub ShowWeekDay()
Dim someDate As Date
someDate = #8/13/2024#
MsgBox "8/13/2024 是星期 " & WeekdayName(Weekday(someDate))
End Sub
7.格式化数值、日期和时间
Format函数是VBA中的常见函数,可以实现数值、日期和时间格式的转变
' 定义一个名为FromatCurrent的子程序
Sub FromatCurrent()
' 使用MsgBox显示格式化后的数字,格式为两位小数,并在末尾添加换行符
MsgBox Format(123456.789, "0.00") & Chr(13)
' 使用Format函数格式化数字为两位小数,并在末尾添加换行符
& Format(123456.789, "0.00") & Chr(13)
' 使用Format函数格式化数字,添加千位分隔符和两位小数,并在末尾添加换行符
& Format(123456.789, "##,##0.00") & Chr(13)
' 使用Format函数格式化负数,使用美元符号,括号表示负值,并在末尾添加换行符
& Format(-123456.789, "$#,##0.00;($#,##0.00)") & Chr(13)
' 使用Format函数格式化负数,使用日元符号,括号表示负值,并在末尾添加换行符
& Format(-123456.789, "¥#,##0.00(¥#,##0.00)") & Chr(13)
' 使用Format函数格式化当前日期为"年-月-日"格式,并在末尾添加换行符
& Format(Date, "yyyy-mm-dd") & Chr(13)
' 使用Format函数格式化当前日期为"年月日"格式(无分隔符),并在末尾添加换行符
& Format(Date, "yyyymmdd") & Chr(13)
' 使用Format函数将当前日期格式化为长日期格式,并在末尾添加换行符
& Format(Date, "Long Date") & Chr(13)
' 使用Format函数格式化当前时间为"时:分:秒"格式,并在末尾添加换行符
& Format(Now, "hh:mm:ss") & Chr(13)
' 使用Format函数格式化当前时间,包含AM/PM标识
& Format(Now, "hh:mm:ss AMPM")
' 结束子程序
End Sub
8.将数字转换成人民币大写(可以在单元格中调用该函数)
需要把代码插入到模块中
Public Function RMBDX(M As Double) As String
' 步骤1: 将输入数字转换为中文大写
RMBDX = Replace(Application.Text(Round(M + 0.00000001, 2), "[DBnum2]"), "〇", "零")
' 步骤2: 分离整数部分和小数部分
Dim intPart As String, decPart As String
intPart = Left(RMBDX, Len(RMBDX) - 2)
decPart = Right(RMBDX, 2)
' 处理整数部分
If intPart <> "" Then
intPart = intPart & "元"
End If
' 处理小数部分
Select Case decPart
Case "零零"
decPart = "整"
Case Else
If Left(decPart, 1) = "零" Then
decPart = Right(decPart, 1) & "分"
Else
decPart = Left(decPart, 1) & "角" & Right(decPart, 1) & "分"
End If
End Select
' 合并整数和小数部分
RMBDX = intPart & decPart
' 步骤3: 清理结果
RMBDX = Replace(Replace(Replace(Replace(RMBDX, "零元", ""), "零零", "零"), "零角", ""), "零分", "")
' 处理特殊情况
If RMBDX = "" Then RMBDX = "零元整"
End Function
9.判断工作表是否为空表
遍历所有工作表,并且弹出msgbox,显示哪些工作表是空表
Sub AnalyzeAllSheets()
Dim ws As Worksheet
Dim emptySheets As New Collection
Dim nonEmptySheets As New Collection
' 禁用屏幕更新以提高性能
Application.ScreenUpdating = False
' 遍历所有工作表
For Each ws In ThisWorkbook.Worksheets
If IsSheetEmpty(ws) Then
' 如果工作表为空,添加到空表集合
emptySheets.Add ws.Name
Else
' 如果工作表不为空,添加到非空表集合
nonEmptySheets.Add ws.Name
End If
Next ws
' 重新启用屏幕更新
Application.ScreenUpdating = True
' 显示结果
DisplayResults emptySheets, nonEmptySheets
End Sub
Function IsSheetEmpty(ws As Worksheet) As Boolean
' 检查已使用区域是否只有一个单元格,且该单元格为空
IsSheetEmpty = (ws.UsedRange.Cells.Count = 1 And ws.UsedRange.Cells(1).Value = "")
End Function
Sub DisplayResults(emptySheets As Collection, nonEmptySheets As Collection)
Dim msg As String
Dim i As Long
' 构建消息字符串
msg = "空白工作表 (" & emptySheets.Count & "):" & vbNewLine
For i = 1 To emptySheets.Count
msg = msg & " - " & emptySheets(i) & vbNewLine
Next i
msg = msg & vbNewLine & "非空工作表 (" & nonEmptySheets.Count & "):" & vbNewLine
For i = 1 To nonEmptySheets.Count
msg = msg & " - " & nonEmptySheets(i) & vbNewLine
Next i
' 显示消息框
MsgBox msg, vbInformation, "工作表分析结果"
End Sub
10.查找指定工作簿是否打开
如果需要判断指定名称的工作簿是否已经打开
函数部分
Function IsWorkbookOpen(workbookName As String) As Boolean
Dim wb As Workbook
' 遍历所有打开的工作簿
For Each wb In Workbooks
' 比较工作簿名称(不区分大小写)
If StrComp(wb.Name, workbookName, vbTextCompare) = 0 Then
IsWorkbookOpen = True
Exit Function
End If
Next wb
' 如果没有找到匹配的工作簿,返回 False
IsWorkbookOpen = False
End Function
调用方法
Sub TestIsWorkbookOpen()
Dim workbookName As String
workbookName = "Example.xlsx"
If IsWorkbookOpen(workbookName) Then
MsgBox "工作簿 '" & workbookName & "' 已打开。"
Else
MsgBox "工作簿 '" & workbookName & "' 未打开。"
End If
End Sub
11.取得应用程序的安装路径
Function GetAppPathFromRegistry(appName As String) As String
Dim ws As Object
Dim regPath As String
Dim appPath As String
Set ws = CreateObject("WScript.Shell")
' 尝试从 HKEY_LOCAL_MACHINE 读取
regPath = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" & appName & "\"
On Error Resume Next
appPath = ws.RegRead(regPath)
On Error GoTo 0
' 如果在 HKLM 中没有找到,尝试 HKEY_CURRENT_USER
If appPath = "" Then
regPath = "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" & appName & "\"
On Error Resume Next
appPath = ws.RegRead(regPath)
On Error GoTo 0
End If
GetAppPathFromRegistry = appPath
End Function
Sub TestGetAppPath()
Dim appPath As String
' 尝试获取 Notepad++ 的路径(假设已安装)
appPath = GetAppPathFromRegistry("notepad++.exe")
If appPath <> "" Then
MsgBox "Notepad++ 的路径是: " & appPath, vbInformation
Else
MsgBox "未能找到 Notepad++ 的路径。", vbExclamation
End If
End Sub
12.数组的使用
数组时一种数据结构,用于存储同一类型的多个元素。可以将数组想象成一个有编号的盒子列表,每个盒子可以存放一个值。
VBA中,有几种不同类型的数组:
静态数组:大小固定,在声明时确定
动态数组:大小可变,可以在运行时调整
多维数组:可以有多个维度,如二维、三维等
声明数组
'声明静态数组
Dim myArray(6) As Integer ' 声明一个包含 7 个元素的整数数组(索引 0 到 6)
'声明动态数组
Dim myDynamicArray() As String ' 声明一个动态字符串数组
ReDim myDynamicArray(10) ' 调整数组大小为 11 个元素(索引 0 到 10)
'声明静态数组和声明动态数组在语法上的区别是,
'静态数组在声明时就确定了大小,且声明后大小不可改变
'动态数组在声明时不指定大小,可以在程序运行时调整其大小
'声明多维数组
Dim myMatrix(2, 2) As Double ' 声明一个 3x3 的二维数组
初始化数组
' 使用 Array 函数(返回 Variant 类型的数组)
Dim fruits As Variant
fruits = Array("Apple", "Banana", "Cherry")
' 逐个赋值
Dim numbers(2) As Integer
numbers(0) = 10
numbers(1) = 20
numbers(2) = 30
' 使用 For 循环
Dim i As Integer
For i = 0 To 2
numbers(i) = i * 10
Next i
数组函数
VBA提供了几个有用的数组函数
LBound(array):返回数组的下界(最小索引)
UBound(array):返回数组的商界(最大索引)
Erase array:清除数组内容(对动态数组,还会释放内存)
遍历数组
Sub LoopThroughArray()
Dim numbers(4) As Integer
Dim i As Integer
' 初始化数组
For i = 0 To 4
numbers(i) = i * 10
Next i
' 遍历并打印数组元素
For i = LBound(numbers) To UBound(numbers)
Debug.Print numbers(i)
Next i
End Sub
1 thought on “9.函数的使用——《VBA常用技巧代码解析》”