避免使用 SELECT 或 ACTIVATE

这是非常罕见的,你永远要使用 SelectActivate 在你的代码,但一些 Excel 的方法需要做的工作表或工作簿被激活之前预期他们会工作。

如果你刚刚开始学习 VBA,通常会建议你使用宏录制器录制你的动作,然后查看代码。例如,我记录了在 Sheet2 上输入单元格 D3 中的值所采取的操作,宏代码如下所示:

Option Explicit
Sub Macro1()
'
' Macro1 Macro
'

'
    Sheets("Sheet2").Select
    Range("D3").Select
    ActiveCell.FormulaR1C1 = "3.1415"   '(see **note below)
    Range("D4").Select
End Sub

但请记住,宏录制器会为你的(用户)操作创建一行代码。这包括单击工作表选项卡以选择 Sheet2(Sheets("Sheet2").Select),在输入值(Range("D3").Select)之前单击单元格 D3,然后使用 Enter 键(有效地选择当前所选单元格下方的单元格:Range("D4").Select)。

这里使用 .Select 有很多问题:

  • **并不总是指定工作表。**如果在录制时不切换工作表,则会发生这种情况,这意味着代码将为不同的活动工作表生成不同的结果。
  • **.Select() 很慢。**即使 Application.ScreenUpdating 设置为 False,这也是一个不必要的处理操作。
  • **.Select() 是不守规矩的。**如果 Application.ScreenUpdating 留给 True,Excel 实际上会选择单元格,工作表,表格……无论你正在使用什么。这对眼睛来说很紧张,看起来真的很不愉快。
  • **.Select() 将触发听众。**这已经有点先进,但除非解决,否则会触发像 Worksheet_SelectionChange() 这样的功能。

当你在 VBA 中编码时,不再需要所有键入操作(即 Select 语句)。你的代码可以简化为单个语句,以将值放入单元格中:

'--- GOOD
ActiveWorkbook.Sheets("Sheet2").Range("D3").Value = 3.1415

'--- BETTER
Dim myWB      As Workbook
Dim myWS      As Worksheet
Dim myCell    As Range

Set myWB = ThisWorkbook             '*** see NOTE2
Set myWS = myWB.Sheets("Sheet2")
Set myCell = myWS.Range("D3")

myCell.Value = 3.1415

(上面的更好示例显示使用中间变量来分隔单元格引用的不同部分 .GOOD 示例将始终正常工作,但在更长的代码模块中可能非常麻烦,如果其中一个引用输入错误则更难以调试。 )

**注意:宏录制器会对你输入的数据类型做出许多假设,在这种情况下输入字符串值作为创建值的公式。你的代码不必执行此操作,只需将数值直接分配给单元格,如上所示。

**注意 2:建议的做法是将本地工作簿变量设置为 ThisWorkbook 而不是 ActiveWorkbook(除非你明确需要它)。原因是你的宏通常需要/使用 VBA 代码所源自的任何工作簿中的资源,并且不会在该工作簿之外查看 - 除非你明确指示你的代码与其他工作簿一起使用。当你在 Excel 中打开多个工作簿时,ActiveWorkbook 的焦点可能与你在 VBA 编辑器中查看的工作簿不同。因此,当你真正引用另一个工作簿时,你认为你正在执行一个工作簿。ThisWorkbook 指的是包含正在执行的代码的工作簿。