本人日常办公中使用VBA实现办公自动化已经有较长时间,积累了一定的经验,在此总结分享出来,希望对大家有所启发。
Excel的录制宏代码可以解决大部分的办公自动化需求,但是依然有很多录制下来的代码使用起来不是很方便,如果对某些片段进行修改,往往会隐藏各种各样的bug,因此需要对常见的语句进行学习和了解,后面对其进行修改和优化才能保证代码的稳定性。
本文尽量分享的是一些自动化办公中最常用的功能代码的使用方法,比如说打开文件、筛选区域,判断区域行数,动态选择区域、发送邮件等,以下为文章主要内容,后续会完善更新,还请多多收藏关注。
首先获取VBA代码执行文件的相对路径(一般是保存了宏代码的xlsm文件)
Path = ThisWorkbook.Path
打开文件
Workbooks.Open ("" & Path & "\" & "我的工作簿.xlsx")
该方法实际有两个参数:
FileName String 类型,必需。要打开的工作簿的文件名。
UpdateLinks Variant 类型,可选。指定文件中链接的更新方式。如果省略本参数,则提示用户选择链接的更新方式。否则,该参数的取值应为下表中的某个值。
UpdateLinks值含义:
0 不更新任何引用。
1 更新外部引用,但不更新远程引用。
2 更新远程引用,但不更新外部引用。
3 同时更新远程引用和外部引用。
但是有时候我们希望能打开模糊匹配的文件,可以借助通配符*,像下面这样。
Workbooks.Open ("" & Path & "\" & Dir("" & Path & "\" & "我的*.xls"))
有时候我们打开一个Excel文件 ,提示“此工作簿包含到一个或多个可能不安全的外部数据源的链接……”,问你是否更新,这个弹窗会阻断我们的VBA进程,我们可以在打开文件的时候设定不更新
Dim wb As Workbook
'UpdateLinks:=0 不更新链接
Set wb = Workbooks.Open(Filename:="" & Path & "\" & Dir("" & Path & "\" & "我的*.xls"), UpdateLinks:=0)
很多时候,我们要处理的数据需要先进行一个筛选,创建一个筛选的代码长这样:
ActiveSheet.Range("$A$1:$W$100" ).AutoFilter Field:=1, Criteria1:= _
">=10" Operator:=xlAnd, Criteria2:="<=100"
这段代码的含义是,筛选活动表的"A1:W100"这个区域," Field:=1"表示筛选条件位于所选区域的第一列。Criteria后面跟的是一系列条件。这种筛选语句可以有多条,则选取需要满足多条筛选语句。
如果判断普通区域(非筛选状态),没有隐藏行,可以用下面的语句简单判断最后一行数据行号:
思路是先取消可能存在的筛选,然后选择一个单元格(选择的单元格需保证到该列的最后一行之间不存在间断,否则会出错)
'清除筛选
ActiveSheet.AutoFilterMode = False
'计算需要填充行数
Range("A2").Select
'跳到该单元格所在列的最后一行
Selection.End(xlDown).Select
a = ActiveCell.Row()
b = CStr(a) '数字转文本类型,即为选取最后一行行号
更多的情况下,我们需要判断筛选后的第一行的行号才可以对该区域进行操作(一般是执行复制),可以采用以下代码:
n = Rows("2:" & Rows.Count).SpecialCells(12).Row
此句拆分一下,Rows(“2”&Rows.Count)选择从第2行开始到最后一行的区域,后面加上.specialCells(12)表示只选可见行,最后在加上区域的Row属性。返回可见区域第一行的行号。
有时候需要填充指定区域(很多时候是类似公式的下拉操作)
'选择填充开始位置
Range("U2:W2").Select
Application.CutCopyMode = False
'填充到最后一行
Selection.AutoFill Destination:=Range("U2:W100" )
'激活"我的工作簿.xlsx“窗口(前提是已经打开改文件)
Windows("我的工作表.xlsx").Activate
'关闭活动窗口的文件
ActiveWindow.Close
'选择指定工作表
Sheets("Sheet1").Select
'或者另一种方式,选“第1个“”sheet
Sheets(1).Select
有时我们需要判断一个工作簿里面的哪个子表才是我们需要的,我们可以遍历选择每个子表以此判断。
'判断子sheet是否为需要的
For i = 1 To Worksheets.Count
Sheets(i).Select
'写判断条件,满足了就退出循环不继续切换子表,否则一直看到最后一个子表
If Range("A1") = "日期_day" Then Exit For
Next
有时候,我们需要动态更改报表里面的日期,需要用到日期函数,以及对日期进行偏移(一周,一月等)。
下面有一个案例:
'今日日期
td = Date
'设置基础日期
basedate = CDate("2021-11-1")
Sheets("累计").Select
'在基础日期上偏移当前日期的天数
Range(Range("GD1").Offset(0, DateDiff("D", basedate, td) - 1), Range("GD1").Offset(0, DateDiff("D", basedate, td) - 1).Offset(72, 0)).Select
Selection.Copy
Range("GD1").Offset(0, DateDiff("D", basedate, td) - 1).Select
Date函数可以返回当前日期,而借助Datediff函数可以计算出偏移后的日期,最后再借助offset函数,即可实现对指定选区的偏移操作。
发送邮件模块可以这样写:
'发邮件模块
Sub SendEmail(To_Addr As String, Cc_Addr As String, Bcc_Addr As String, SubjectText As String, BodyText As String, AttachedObject As String)
Dim OutlookObj As Object
Dim OutlookNewMail As Object
'创建Outlook对象
Set OutlookObj = CreateObject("Outlook.Application")
Set OutlookNewMail = OutlookObj.CreateItem(olMailItem)
'错误异常处理
On Error GoTo SendEmail_Failed
With OutlookNewMail
.To = To_Addr '收件人地址
.cc = Cc_Addr '抄送人地址
.BCC = Bcc_Addr '密送人地址
.Subject = SubjectText '邮件主题
.htmlBody = BodyText '邮件内容
.Attachments.Add AttachedObject '粘贴附件
'.Send '若采用.Send方式发送邮件,则Outlook容易出现“有一个程序正试图以您的名义发送电子邮件”提示,比较招人讨厌。
'若坚持采用此种方式发送邮件,又不想Outlook出现讨厌的提示,则需对Outlook进行如下设置:
'"工具" -> "信任中心" -> "编程访问" -> 选择"从不向我发出可疑活动警告"
End With
'以下是采用通过激活Outlook,然后模拟按键方式进行邮件发送
SendEmail_Sending:
'显示发送邮件窗口
OutlookNewMail.display
'以下目的是留给系统充分的时间点击发送键
For j = 1 To 200
DoEvents
Next
'点击邮件发送
SendKeys "%s", Wait:=True
'遗憾的是,这里无法显示服务器发送状态,只能返回Excel发送的结果
MsgBox "邮件已发送!"
Exit Sub
SendEmail_Failed:
MsgBox "发送失败,原因为:" & Err.Description
Exit Sub
End Sub
'调用部分
'简单调用示例,调用中各参数分别为:"收件人","抄送人","密送人","主题","正文","附件"。
SendEmail "[email protected]", "", "", "数据表", "本月数据表,请查收!", "D:\Users\lindada\Desktop\我的工作表.xlsx"
以上邮件模块已经可以发送简单的文字邮件+附件了,但是我们日常工作中发的邮件一般是数据日报,不仅文字需要带一定的格式,邮件还会附带图片,这种需要将正文内容以HTML文档的格式编辑好放进正文里即可。
如下面一段HTML格式的正文:
<body style='font-family:微软雅黑;font-size:13px;'>
各位领导好,数据达成如下:
<br/>
1、整体情况,XXXXX;
<br/>
2、产品维度,XXXX;
<span style='color:red'>
达成较差的为:张三、李四、王五;
span>
<br/>
<img src='D:\Users\test\日报截图.jpg'>
body>
图文都有了,也有了格式设置,那么每次还需要将报表图片导出,就非常的麻烦,下面一段代码则可以将指定区域的内容提取为图表并导出:
a = ThisWorkbook.Path
'打开当前文件路径下的看板
Workbooks.Open ("" & a & "\" & "日报看板.xlsx")
选择看板窗口
Windows("日报看板.xlsx").Activate
'选择要发邮件的图表在的子表
Sheets("邮件").Select
'有时候会发现截出来的图片很大,可以模拟滚轮操作,将图片缩放到35%
ActiveWindow.Zoom = 35
'选择要导出为图片的区域
Range("B2:V79").Select
Selection.Copy
Selection.CopyPicture
With ActiveSheet.ChartObjects.Add(0, 0, Selection.Width, Selection.Height).Chart
.Parent.Select
.Paste
.Export "D:\test\日报看板.jpg", "JPG"
.Parent.Delete
End With
以上是本人办公自动化用到最多的结构,其余的常见用法,比如说跳转单元格的位置,复制,粘贴等均可以通过录制宏代码后进行稍加改进,本文暂时写到这里,后续有新的感想会更新,感谢各位!