跳到主要内容

如何避免在 Excel VBA 中使用 Select

你或许知道在 Excel VBA 中使用 .Select 、.Activate 是一个坏习惯,但你知道该如何避免使用它吗?

为什么要避免使用 .Select

应避免使用 .Select.ActivateSelectionActivecellActivesheetActiveworkbook 等的两个主要原因:

如何避免 .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")

同样的,以上所有示例指向的是活动工作簿。除非您只想使用 ActiveWorkbookThisWorkbook,否则最好也将 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

将单元格区域作为变量传递给您的 SubFunction

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 ' 将新值写入工作表

评论

您的电子邮件地址不会显示出来。*号为必填项。