你或许知道在 Excel VBA 中使用 .Select
、.Activate
是一个坏习惯,但你知道该如何避免使用它吗?
为什么要避免使用 .Select
应避免使用 .Select
, .Activate
, Selection
, Activecell
, Activesheet
, Activeworkbook
等的两个主要原因:
- 它会减慢你的代码运行速度。学习加速 Excel VBA 代码的方法。
- 它通常是运行时错误的主要原因。
如何避免 .Select 的示例
使用 Dim
定义变量
Dim rng as Range
使用 Set
将变量设置为所需单元格区域。引用单个单元格区域的方法有很多种,例如:
Set rng = Range("A1")
Set rng = Cells(1, 1)
Set rng = Range("NamedRange")
或多个单元格区域:
Set rng = Range("A1:B10")
Set rng = Range("A1", "B10")
Set rng = Range(Cells(1, 1), Cells(10, 2))
Set rng = Range("AnotherNamedRange")
Set rng = Range("A1").Resize(10, 2)
您还可以使用快捷记号(A1 引用样式或命名区域使用方括号([]
)括起来),但这效率较低,通常应在生产代码中避免使用。
Set rng = [A1]
Set rng = [A1:B10]
以上所有示例均指的是活动工作表上的单元格。除非您只想使用活动工作表,否则最好也将 Worksheet
定义成变量:
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
Set rng = ws.Cells(1, 1)
With ws
Set rng = .Range(.Cells(1, 1), .Cells(2, 10))
End With
如果您确实想使用 ActiveSheet
,为清楚起见最好明确说明。但是要小心,因为某些 Worksheet
方法会更改活动工作表。
Set rng = ActiveSheet.Range("A1")
同样的,以上所有示例指向的是活动工作簿。除非您只想使用 ActiveWorkbook
或 ThisWorkbook
,否则最好也将 Workbook
定义成变量。
Dim wb As Workbook
Set wb = Application.Workbooks("Book1")
Set rng = wb.Worksheets("Sheet1").Range("A1")
如果您确实想使用 ActiveWorkbook
,为清楚起见最好明确说明。但是要小心,因为许多 WorkBook
方法会更改活动工作簿。
Set rng = ActiveWorkbook.Worksheets("Sheet1").Range("A1")
您还可以使用 ThisWorkbook
对象来引用包含运行代码的工作簿:
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1")
比如一段常见的代码是打开一个工作簿,获取一些数据然后再次关闭。
这是不好的代码:
Sub foo()
Dim v As Variant
Workbooks("Book1.xlsx").Sheets(1).Range("A1").Clear
Workbooks.Open ("C:\Path\To\SomeClosedBook.xlsx")
v = ActiveWorkbook.Sheets(1).Range("A1").Value
Workbooks("SomeAlreadyOpenBook.xlsx").Activate
ActiveWorkbook.Sheets("SomeSheet").Range("A1").Value = v
Workbooks(2).Activate
ActiveWorkbook.Close
End Sub
这是好的代码:
Sub foo()
Dim v As Variant
Dim wb1 As Workbook
Dim wb2 As Workbook
Set wb1 = Workbooks("SomeAlreadyOpenBook.xlsx")
Set wb2 = Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")
v = wb2.Sheets("SomeSheet").Range("A1").Value
wb1.Sheets("SomeOtherSheet").Range("A1").Value = v
wb2.Close
End Sub
将单元格区域作为变量传递给您的 Sub
或 Function
:
Sub ClearRange(r As Range)
r.ClearContents
'....
End Sub
Sub MyMacro()
Dim rng As Range
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:B10")
ClearRange rng
End Sub
直接使用相关对象:
比如下列这段代码:
Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"
也可以使用 With 语句写成:
With Sheets("Sheet1").Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
如果需要,请定义您的变量。上面的代码可以写成:
Dim ws As Worksheet
Set ws = Sheets("Sheet1")
With ws.Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
您还可以在方法(例如Find
和 Copy
)中应用变量:
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10")
Set rng2 = ThisWorkbook.Worksheets("SomeSheet").Range("B1:B10")
rng1.Copy rng2
如果要遍历单元格区域,通常最好(更快)先将单元格区域值复制到变体数组再遍历它:
Dim dat As Variant
Dim rng As Range
Dim i As Long
Set rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10000")
dat = rng.Value ' dat 现在是数组 (1 到 10000, 1 到 1)
For i = LBound(dat, 1) To UBound(dat, 1)
dat(i, 1) = dat(i, 1) * 10 ' 或者你需要执行的任何操作将新值放回工作表
Next
rng.Value = dat ' 将新值写入工作表