我听说过很多关于在Excel VBA中使用. select的可以理解的厌恶,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是Select函数,我的代码将更具可重用性。然而,我不确定如果不使用选择如何引用事物(如ActiveCell等)。

我找到了这篇关于范围的文章和这个关于不使用select的好处的例子,但我找不到任何关于如何使用的东西。


当前回答

“…我发现,如果我能够使用变量而不是选择函数,我的代码将更加可重用。”

虽然我想不出更多孤立的情况,在这些情况下. select将是比直接引用单元格更好的选择,但我要为Selection辩护,并指出它不应该因为应该避免. select的原因而被抛弃。

There are times when having short, time-saving macro sub routines assigned to hot-key combinations available with the tap of a couple of keys saves a lot of time. Being able to select a group of cells to enact the operational code on works wonders when dealing with pocketed data that does not conform to a worksheet-wide data format. Much in the same way that you might select a group of cells and apply a format change, selecting a group of cells to run special macro code against can be a major time saver.

基于选择的子框架示例:

Public Sub Run_on_Selected()
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Selected_Visible()
    'this is better for selected ranges on filtered data or containing hidden rows/columns
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL.SpecialCells(xlCellTypeVisible)
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Discontiguous_Area()
    'this is better for selected ranges of discontiguous areas
    Dim ara As Range, rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each ara In rSEL.Areas
        Debug.Print ara.Address(0, 0)
        'cell group operational code here
        For Each rng In ara.Areas
            Debug.Print rng.Address(0, 0)
            'cell-by-cell operational code here
        Next rng
    Next ara
    Set rSEL = Nothing
End Sub

要处理的实际代码可以是从单行到多个模块的任何内容。我曾使用此方法在包含外部工作簿文件名的不规则单元格上启动长时间运行的例程。

简而言之,不要因为Selection与. select和ActiveCell的密切关联而放弃它。作为工作表属性,它还有许多其他用途。

(是的,我知道这个问题是关于. select,而不是Selection,但我想消除新手VBA程序员可能推断的任何误解。)

其他回答

使用. 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

“…我发现,如果我能够使用变量而不是选择函数,我的代码将更加可重用。”

虽然我想不出更多孤立的情况,在这些情况下. select将是比直接引用单元格更好的选择,但我要为Selection辩护,并指出它不应该因为应该避免. select的原因而被抛弃。

There are times when having short, time-saving macro sub routines assigned to hot-key combinations available with the tap of a couple of keys saves a lot of time. Being able to select a group of cells to enact the operational code on works wonders when dealing with pocketed data that does not conform to a worksheet-wide data format. Much in the same way that you might select a group of cells and apply a format change, selecting a group of cells to run special macro code against can be a major time saver.

基于选择的子框架示例:

Public Sub Run_on_Selected()
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Selected_Visible()
    'this is better for selected ranges on filtered data or containing hidden rows/columns
    Dim rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each rng In rSEL.SpecialCells(xlCellTypeVisible)
        Debug.Print rng.Address(0, 0)
        'cell-by-cell operational code here
    Next rng
    Set rSEL = Nothing
End Sub

Public Sub Run_on_Discontiguous_Area()
    'this is better for selected ranges of discontiguous areas
    Dim ara As Range, rng As Range, rSEL As Range
    Set rSEL = Selection    'store the current selection in case it changes
    For Each ara In rSEL.Areas
        Debug.Print ara.Address(0, 0)
        'cell group operational code here
        For Each rng In ara.Areas
            Debug.Print rng.Address(0, 0)
            'cell-by-cell operational code here
        Next rng
    Next ara
    Set rSEL = Nothing
End Sub

要处理的实际代码可以是从单行到多个模块的任何内容。我曾使用此方法在包含外部工作簿文件名的不规则单元格上启动长时间运行的例程。

简而言之,不要因为Selection与. select和ActiveCell的密切关联而放弃它。作为工作表属性,它还有许多其他用途。

(是的,我知道这个问题是关于. select,而不是Selection,但我想消除新手VBA程序员可能推断的任何误解。)

我注意到这些答案都没有提到. offset属性。这也可以用来避免在操作某些单元格时使用Select操作,特别是在引用选定的单元格时(正如OP中使用ActiveCell提到的那样)。

这里有几个例子:

我还假定ActiveCell是J4。

ActiveCell。Offset(2,0).Value = 12

这将从activecell(即J6)往下两行更改单元格的值为12 A -2会把值12放在J2上面两行

ActiveCell.Offset(0, 1)。ActiveCell.Offset副本(2)

这将把右边一列的单元格(k4)复制到活动单元格(L4)两列的单元格。 注意,offset参数中0可能被省略 因此:activecell。offset(,2)和activecell。offset(0,2)是一样的 类似于前面的例子,-1是左边的一列(i4)

这并不是说这些选项比上面的选项更好,但它肯定比使用select要好。注意,在工作表中应该避免使用EXCEL函数偏移量,因为它是一个易失函数。