我听说过很多关于在Excel VBA中使用. select的可以理解的厌恶,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是Select函数,我的代码将更具可重用性。然而,我不确定如果不使用选择如何引用事物(如ActiveCell等)。
我找到了这篇关于范围的文章和这个关于不使用select的好处的例子,但我找不到任何关于如何使用的东西。
我听说过很多关于在Excel VBA中使用. select的可以理解的厌恶,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是Select函数,我的代码将更具可重用性。然而,我不确定如果不使用选择如何引用事物(如ActiveCell等)。
我找到了这篇关于范围的文章和这个关于不使用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"
这些方法有多种组合,但对于像我这样没有耐心的人来说,这将是尽可能简短地表达的总体思想。
其他回答
“…我发现,如果我能够使用变量而不是选择函数,我的代码将更加可重用。”
虽然我想不出更多孤立的情况,在这些情况下. 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程序员可能推断的任何误解。)
从不使用选择或活动表的主要原因是,大多数人在运行宏时至少会打开另外几个工作簿(有时是几十个),如果他们在宏运行时从工作表中单击离开,并单击他们已经打开的其他工作簿,那么“活动表”会发生变化,而不满足“选择”命令的目标工作簿也会发生变化。
在最好的情况下,你的宏会崩溃,在最坏的情况下,你可能会在错误的工作簿中写入值或更改单元格,而无法“撤消”它们。
我有一个我遵循的简单的黄金法则:为工作簿对象和工作表对象添加名为“wb”和“ws”的变量,并始终使用它们来引用我的宏书。如果我需要引用多本书或多张表格,我会添加更多变量。
例如,
Dim wb as Workbook
Dim ws as Worksheet
Set wb = ThisWorkBook
Set ws = wb.sheets("Output")
“Set wb = ThisWorkbook”命令绝对是关键。“ThisWorkbook”是Excel中的一个特殊值,它意味着您的VBA代码当前正在运行的工作簿。一个非常有用的快捷方式来设置你的工作簿变量。
当你在你的Sub顶部做了这些之后,使用它们再简单不过了,只要在你使用“Selection”的地方使用它们:
因此,要将“Output”中的单元格“A1”的值更改为“Hello”,而不是:
Sheets("Output").Activate
ActiveSheet.Range("A1").Select
Selection.Value = "Hello"
我们现在可以这样做:
ws.Range("A1").Value = "Hello"
如果用户使用多个电子表格,它不仅更可靠,而且不太可能崩溃;它也更短,更快,更容易写。
作为额外的奖励,如果你总是将变量命名为“wb”和“ws”,你可以将代码从一本书复制粘贴到另一本书,通常只需要进行最小的更改就可以工作。
如何避免复制粘贴?
让我们面对现实吧:这个在记录宏时经常出现:
Range("X1").Select
Selection.Copy
Range("Y9").Select
Selection.Paste
而这个人唯一想要的是:
Range("Y9").Value = Range("X1").Value
因此,与其在VBA宏中使用复制粘贴,我建议使用以下简单的方法:
Destination_Range.Value = Source_Range.Value
请注意,在下面我将比较Select方法(OP想要避免的方法)和Range方法(这是问题的答案)。所以当你看到第一个选择时不要停止阅读。
这真的取决于你想要做什么。总之,举个简单的例子会很有用。让我们假设您想要将活动单元格的值设置为“foo”。使用ActiveCell,你可以这样写:
Sub Macro1()
ActiveCell.Value = "foo"
End Sub
如果你想将它用于一个非活动单元格,例如“B2”,你应该首先选择它,如下所示:
Sub Macro2()
Range("B2").Select
Macro1
End Sub
使用Ranges,你可以编写一个更通用的宏,可以用来设置任何你想要的单元格的值:
Sub SetValue(cellAddress As String, aVal As Variant)
Range(cellAddress).Value = aVal
End Sub
然后你可以重写Macro2为:
Sub Macro2()
SetCellValue "B2", "foo"
End Sub
而Macro1为:
Sub Macro1()
SetValue ActiveCell.Address, "foo"
End Sub
我要给出简短的答案,因为其他人都给出了长答案。
当您记录宏并重用它们时,您将得到.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"
这些方法有多种组合,但对于像我这样没有耐心的人来说,这将是尽可能简短地表达的总体思想。