我听说过很多关于在Excel VBA中使用. select的可以理解的厌恶,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是Select函数,我的代码将更具可重用性。然而,我不确定如果不使用选择如何引用事物(如ActiveCell等)。
我找到了这篇关于范围的文章和这个关于不使用select的好处的例子,但我找不到任何关于如何使用的东西。
我听说过很多关于在Excel VBA中使用. select的可以理解的厌恶,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是Select函数,我的代码将更具可重用性。然而,我不确定如果不使用选择如何引用事物(如ActiveCell等)。
我找到了这篇关于范围的文章和这个关于不使用select的好处的例子,但我找不到任何关于如何使用的东西。
当前回答
两个主要原因,为什么.Select, .Activate, Selection, Activecell, Activesheet, Activeworkbook等应该避免
它会降低代码的速度。 它通常是运行时错误的主要原因。
我们如何避免它?
1)直接与相关对象一起工作
考虑下面的代码
Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"
这段代码也可以写成
With Sheets("Sheet1").Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
2)如果需要,声明你的变量。上面相同的代码可以写成
Dim ws as worksheet
Set ws = Sheets("Sheet1")
With ws.Range("A1")
.Value = "Blah"
.NumberFormat = "@"
End With
这是一个很好的答案,但我在这个话题上忽略了我们真正需要Activate的时候。每个人都说它不好,但没有人解释在什么情况下使用它是有意义的。
无法避免使用. activate /. select的情况。(将添加更多的链接,当我遇到他们)
当您希望将工作表显示给用户以便用户可以看到它时。 例如工作宏从表单控件运行时返回错误,强制使用.Activate 当通常的Text To Columns / .Formula = .Formula方法不起作用时,您可能不得不求助于.Select
其他回答
在我看来,.select的使用来自于像我这样的人,他们通过记录宏然后修改代码开始学习VBA,而没有意识到.select和后续的选择只是一个不必要的中间人。
.select可以避免,就像许多人已经发布的那样,通过直接使用已经存在的对象,这允许各种间接引用,如以复杂的方式计算I和j,然后编辑cell(I,j)等。
否则,.select本身并没有什么隐含的错误,你可以很容易地找到它的用途,例如,我有一个电子表格,我用日期填充,激活宏,对它做一些魔法,并在一个单独的表格上以可接受的格式导出它,然而,这需要一些最终手动(不可预知的)输入到相邻的单元格。这时,使用.select可以节省额外的鼠标移动和点击。
我要给出简短的答案,因为其他人都给出了长答案。
当您记录宏并重用它们时,您将得到.select和.activate。当你选择一个单元格或工作表时,它会使它激活。从那时起,当你使用像Range这样的非限定引用时。值他们只是使用活动单元格和表。如果您没有观察代码放置的位置或用户单击工作簿,这也会产生问题。
因此,您可以通过直接引用单元格来消除这些问题。这是:
'create and set a range
Dim Rng As Excel.Range
Set Rng = Workbooks("Book1").Worksheets("Sheet1").Range("A1")
'OR
Set Rng = Workbooks(1).Worksheets(1).Cells(1, 1)
或者你可以
'Just deal with the cell directly rather than creating a range
'I want to put the string "Hello" in Range A1 of sheet 1
Workbooks("Book1").Worksheets("Sheet1").Range("A1").value = "Hello"
'OR
Workbooks(1).Worksheets(1).Cells(1, 1).value = "Hello"
这些方法有多种组合,但对于像我这样没有耐心的人来说,这将是尽可能简短地表达的总体思想。
使用. parent特性,这个例子展示了如何只设置一个myRng引用就可以动态访问整个环境,而不需要任何. select、. activate、. activecell、. activeworkbook、. activesheet等等。(没有任何通用的. child特性。)
Sub ShowParents()
Dim myRng As Range
Set myRng = ActiveCell
Debug.Print myRng.Address ' An address of the selected cell
Debug.Print myRng.Parent.name ' The name of sheet, where MyRng is in
Debug.Print myRng.Parent.Parent.name ' The name of workbook, where MyRng is in
Debug.Print myRng.Parent.Parent.Parent.name ' The name of application, where MyRng is in
' You may use this feature to set reference to these objects
Dim mySh As Worksheet
Dim myWbk As Workbook
Dim myApp As Application
Set mySh = myRng.Parent
Set myWbk = myRng.Parent.Parent
Set myApp = myRng.Parent.Parent.Parent
Debug.Print mySh.name, mySh.Cells(10, 1).Value
Debug.Print myWbk.name, myWbk.Sheets.Count
Debug.Print myApp.name, myApp.Workbooks.Count
' You may use dynamically addressing
With myRng
.Copy
' Pastes in D1 on sheet 2 in the same workbook, where the copied cell is
.Parent.Parent.Sheets(2).Range("D1").PasteSpecial xlValues
' Or myWbk.Sheets(2).Range("D1").PasteSpecial xlValues
' We may dynamically call active application too
.Parent.Parent.Parent.CutCopyMode = False
' Or myApp.CutCopyMode = False
End With
End Sub
始终声明工作簿,工作表和单元格/范围。
例如:
Thisworkbook.Worksheets("fred").cells(1,1)
Workbooks("bob").Worksheets("fred").cells(1,1)
因为终端用户总是只会点击按钮,一旦焦点从代码想要使用的工作簿上移开,事情就会完全出错。
永远不要使用工作簿的索引。
Workbooks(1).Worksheets("fred").cells(1,1)
当用户运行您的代码时,您不知道还会打开哪些工作簿。
如何避免复制粘贴?
让我们面对现实吧:这个在记录宏时经常出现:
Range("X1").Select
Selection.Copy
Range("Y9").Select
Selection.Paste
而这个人唯一想要的是:
Range("Y9").Value = Range("X1").Value
因此,与其在VBA宏中使用复制粘贴,我建议使用以下简单的方法:
Destination_Range.Value = Source_Range.Value