在VBA中,Sheets和Worksheets都是用来引用工作表的集合,但它们的范围不同。
你可以这样理解:Worksheets是Sheets的子集。
1、工作表的引用(访问)
前面讲 Range 对象时,VBA代码里面的 "Sheet1" ,就是引用 Worksheet 对象。但它不是通过工作表名去访问的,而是工程对象,如下图红框。右边括号里的 "Sheet1" 就是工作表名了。
除了工程对象,还可以通过 Worksheets 和 Sheets 索引(索引号、工作表名)。WorkSheets 集合包含所有的工作表,而 Sheets 集合不仅包含工作表集合 WorkSheets,还包含图表集合 Charts、宏表集合 Excel4MacroSheets 与 MS Excel 5.0 对话框集合 DialogSheets 等。
Sub WorksheetDemo() Dim ws As Worksheet Set ws = Sheet1 '工程对象 Set ws = Worksheets("Sheet1") 'Worksheets(工作表名) Set ws = Sheets("Sheet1") 'Sheets(工作表名) Set ws = Worksheets(1) 'Worksheets(索引号) Set ws = Sheets(1) 'Sheets(索引号) Set ws = ActiveSheet '活动的工作表 End Sub在确定工作簿里只有普通的工作表 Worksheet,可以放心使用 Sheets,担心出错就用 Worksheets。推荐用工作表名所有来指向工作表:①工程对象虽然可以明确指向,但在操作过程中,可能需要删除/新建工作表,这次是 "Sheet20",可能下次是 "Sheet18";②索引号不是谁先新建谁在前,它是根据工作表顺序。如下图,Worksheets(2) 访问的工作表是 "Sheet1",因为 "Sheet1" 在这个工作簿的第2位;
③活动的工作表是最不推荐的,可读性差。如果你想要通过录制宏达到自动化目的,建议把出现的 ActiveSheet 改成 Worksheets(工作表名) 。
2、选择 / 激活工作簿
不重要的方法,但偶尔可以结合工作表事件的 Activate 保护工作表不被查看,或者在输出工作簿时,激活指定的工作表方便查看。
有2种写法,Worksheet.Active 和 Worksheet.Select,后者如果工作表隐藏了,会报错,所以保守起见,要先判断是否被隐藏。
Sub SelectWorksheet() Sheets("Sheet2").Activate ActiveSheet.Range("A1").Formula = "=B1" '此时 ActiveSheet 指向 Sheet2 If Sheets("Sheet1").Visible = True Then '确认 Sheet1 没有隐藏 Sheets("Sheet1").Select ActiveSheet.Range("A1").Formula = "=B1" '此时 ActiveSheet 指向 Sheet1 End If End Sub3、遍历工作表
一个工作簿文件如果包含多个工作表,在不确定是否有想要的工作表时,可以通过遍历所有工作表查找符合条件的工作表名并返回。
Worksheet.Name返回工作表名。
Worksheets.Count返回工作表个数。
遍历工作表有2种方法,①遍历所有的工作簿对象Worksheets,返回单个工作表对象Worksheet;②通过索引号,逐个指向工作表对象Worksheet
Sub SearchWorksheet() '#### 案例:找到工作表名为 "raw" 和 包含 "规则" 的工作表 Dim myWs1 As Worksheet, myWs2 As Worksheet '---------------------- 遍历方法1 ---------------------- For Each ws In Worksheets '直接遍历对象所有的工作表,返回单个工作表对象 If ws.Name = "raw" Then 'Worksheet.Name 访问工作表名 Set myWs1 = ws ElseIf ws.Name Like "*规则*" Then Set myWs2 = ws End If Next ws '------------------------------------------------------- '---------------------- 遍历方法2 ---------------------- For idx = 1 To Worksheets.Count If Worksheets(idx).Name = "raw" Then '通过索引号 访问工作表 Set myWs1 = Worksheets(idx) ElseIf InStr(Worksheets(idx).Name, "规则") > 0 Then Set myWs2 = Worksheets(idx) End If Next idx '------------------------------------------------------- '#### 以上2种方法 2选1 '判断是否找到了指定工作表:raw If myWs1 Is Nothing Then flag1 = "没找到工作表raw" Else row1 = myWs1.UsedRange.Rows.Count col1 = myWs1.UsedRange.Columns.Count flag1 = "找到工作表raw,数据有 " & row1 & "行 x " & col1 & "列" End If '判断是否找到了指定工作表:规则 If myWs2 Is Nothing Then flag2 = "没找到命名包含""规则""的工作表" Else row2 = myWs2.UsedRange.Rows.Count col2 = myWs2.UsedRange.Columns.Count wsName = myWs2.Name flag2 = "找到命名包含""规则""的工作表,完整命名为""" & wsName & """,数据有 " & row2 & "行 x " & col2 & "列" End If MsgBox flag1 & vbCrLf & flag2 End SubvbCrlf 是字符串的换行符。运行结果示例图如下:
4、新建 / 删除工作表
1)新建工作表
语法:Worksheets.Add(Before, After, Count, Type),所有参数可选。
Before:指定工作表的对象,新建的工作表将置于此工作表之前。
After:指定工作表的对象,新建的工作表将置于此工作表之后。
Count:要新建的工作表数。 默认值为 1。
Type:新建的工作表类型。默认值为 xlWorksheet。其他还有 xlChart, xlExcel4MacroSheet, xlExcel4IntlMacroSheet。
Sub AddWorksheet() Worksheets.Add '不填参数,默认在最前面新建1个工作表 Worksheets.Add Before:=Worksheets("raw") '在<raw>工作表之前新建1个工作表 Worksheets.Add After:=Worksheets("测试规则"), Count:=2 '在<测试规则>工作表之前新建2个工作表 '在最末尾新建1个工作表并且命名 Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count)) ws.Name = "最后面的一个工作表" End Sub2)删除工作表
语法:Worksheet.Delete。正常删除工作表时,会弹窗提示用户确认,在VBA处理过程中,可以用 Application.DisplayAlerts 开启 / 关闭警报窗口,这样,程序运行过程中,用户就不用守着点击确认删除。
Sub DelWorksheet() Application.DisplayAlerts = False '关闭消息窗口 Worksheets("最后面的一个工作表").Delete '删除工作表 Application.DisplayAlerts = True '在末尾处 开启消息窗口 End Sub5、取消工作表的筛选
本来写前面完4点想开始Workbook的,突然想起还有这个常用的属性AutoFilterMode,又回来补上了。
写VBA不一定是给自己用,有时候取数时,表格做了筛选,这时候可能会有些数据拿不到,所以,每次取数前,对工作表取消筛选,真的很重要。代码也很简单,只要一行。
Sub CancelFilter() Worksheets("raw").AutoFilterMode = False End Sub其他方法如 保护、移动等等不做讲解,使用场景很少。