把同一个文件夹里的几十个工作簿合并到一张表、按模板批量生成文件、打开文件时自动刷新、修改单元格时自动记录时间。工作簿和工作表操作的核心是明确对象:操作哪个文件、哪张表,不能依赖“当前激活”的是谁。
| 对象 | 含义 | 写法 |
|---|---|---|
ThisWorkbook |
代码所在的工作簿 | ThisWorkbook.Worksheets("汇总") |
ActiveWorkbook |
当前激活的工作簿 | 用户可能切换,慎用 |
Workbooks("报表.xlsx") |
按名称取已打开的工作簿 | 名称要包含扩展名 |
Workbooks.Open |
打开文件 | Set wb = Workbooks.Open(path) |
Workbooks.Add |
新建工作簿 | Set wb = Workbooks.Add |
Worksheets("Sheet1") |
按名称取工作表 | 不含图表工作表 |
Sheets(1) |
按索引取工作表 | 包含图表工作表 |
ThisWorkbook.Path |
当前文件所在目录 | 不含末尾分隔符 |
Sub OpenAndClose()
Dim wb As Workbook
Dim path As String
path = ThisWorkbook.Path & Application.PathSeparator & "数据.xlsx"
Set wb = Workbooks.Open(path, ReadOnly:=True)
Debug.Print wb.Worksheets(1).Range("A1").Value
wb.Close SaveChanges:=False
End Sub
保存:
wb.Save
wb.SaveAs Filename:=ThisWorkbook.Path & "\结果.xlsx", FileFormat:=xlOpenXMLWorkbook
wb.SaveAs Filename:=ThisWorkbook.Path & "\结果.xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled
wb.SaveCopyAs ThisWorkbook.Path & "\备份.xlsx"
SaveAs 会改变当前工作簿指向的文件;SaveCopyAs 只复制一份,不改变当前文件。.xlsm 才能保留宏;保存为 .xlsx 会丢失 VBA 项目。Replace 清理。Sub MergeWorkbooks()
Dim folderPath As String
Dim fileName As String
Dim wb As Workbook
Dim dest As Worksheet
Dim lastRow As Long
folderPath = ThisWorkbook.Path & Application.PathSeparator & "数据"
Set dest = ThisWorkbook.Worksheets("汇总")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
fileName = Dir(folderPath & Application.PathSeparator & "*.xlsx")
Do While fileName <> ""
Set wb = Workbooks.Open( _
folderPath & Application.PathSeparator & fileName, _
ReadOnly:=True)
lastRow = dest.Cells(dest.Rows.Count, "A").End(xlUp).Row
wb.Worksheets(1).Range("A2:D100").Copy _
Destination:=dest.Range("A" & lastRow + 1)
wb.Close SaveChanges:=False
fileName = Dir
Loop
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
示例里的 A2:D100 是固定范围;实际使用时应先求源表最后一行。Dir 循环第一次传路径,后续不传参数,直到返回空字符串。
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(1))
ws.Name = "临时"
ws.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
ws.Visible = xlSheetHidden ' 隐藏,用户可在菜单取消隐藏
ws.Visible = xlSheetVeryHidden ' 深度隐藏,只能通过 VBA 恢复
ws.Protect Password:="1234"
ws.Unprotect Password:="1234"
删除工作表:
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("临时").Delete
Application.DisplayAlerts = True
删除前确认表里没有需要保留的数据;删除工作表不能撤销。
事件代码必须写在对应的模块里:
Workbook_Open、Workbook_BeforeClose 写在 ThisWorkbook 模块;Worksheet_Change、Worksheet_SelectionChange 写在对应工作表的模块;' ThisWorkbook 模块
Private Sub Workbook_Open()
ThisWorkbook.Worksheets("汇总").Range("A1").Value = Now
End Sub
' Sheet1 模块
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A:A")) Is Nothing Then Exit Sub
Application.EnableEvents = False
On Error GoTo Cleanup
Target.Offset(0, 1).Value = Now
Cleanup:
Application.EnableEvents = True
End Sub
修改单元格会再次触发 Change,所以要先关闭事件,处理完再打开;出错时也要恢复,否则后续事件都不再触发。
ActiveWorkbook 指错文件:用户切到别的窗口后,ActiveWorkbook 就变了;固定用 ThisWorkbook 或明确的 Workbooks("名称")。DisplayAlerts = False 掩盖提示:关闭未保存的工作簿、覆盖同名文件时不再询问,可能丢数据;只在明确知道后果时临时关闭,并确保恢复。EnableEvents 没恢复:事件处理里出错后直接退出,EnableEvents 仍是 False,之后所有事件失效;用错误处理块恢复。\ / ? * [ ] : 会报错;改名后公式和代码引用也可能失效。Workbooks.Open 触发链接更新:文件里有外部链接时可能弹窗;用 UpdateLinks:=0 避免更新,或明确处理。.xlsx 丢宏、.csv 只保存当前表;按用途选择格式。Application.PathSeparator,不要硬编码 \;Mac 版 Excel 的路径分隔符不同。合上页面,先回答,再展开对照。
ThisWorkbook 和 ActiveWorkbook 有什么区别?EnableEvents = False?SaveAs 和 SaveCopyAs 有什么区别?ThisWorkbook 是代码所在的工作簿;ActiveWorkbook 是当前激活的工作簿,可能被用户切换。Change 事件,关闭事件可以避免递归;处理完必须恢复。SaveAs 改变当前工作簿指向的文件;SaveCopyAs 只复制一份,不改变当前文件。
小程序版
微信扫码,随时查命令