本文翻译自:How to avoid using Select in Excel VBA

I've heard much about the understandable abhorrence of using .Select in Excel VBA, but am unsure of how to avoid using it. 我已经听说了很多有关在Excel VBA中使用.Select的可理解的.Select ,但是不确定如何避免使用它。 I am finding that my code would be more re-usable if I were able to use variables instead of Select functions. 我发现如果我能够使用变量而不是Select函数,那么我的代码将更可重用。 However, I am not sure how to refer to things (like the ActiveCell etc.) if not using Select . 但是,如果不使用Select ,我不确定如何引用事物(例如ActiveCell等)。

I have found this article on ranges and this example on the benefits of not using select but can't find anything on how ? 我在范围上找到了这篇文章,在 这个示例中找到了不使用select的好处,但是找不到如何做的事情?


#1楼

参考:https://stackoom.com/question/ixGV/如何避免在Excel-VBA中使用选择


#2楼

Please note that in the following I'm comparing the Select approach (the one that the OP wants to avoid), with the Range approach (and this is the answer to the question). 请注意,下面我将比较Select方法(OP希望避免的一种方法)和Range方法(这是问题的答案)。 So don't stop reading when you see the first Select. 因此,当您看到第一个“选择”时不要停止阅读。

It really depends on what you are trying to do. 这实际上取决于您要执行的操作。 Anyway a simple example could be useful. 无论如何,一个简单的例子可能会有用。 Let's suppose that you want to set the value of the active cell to "foo". 假设您要将活动单元格的值设置为“ foo”。 Using ActiveCell you would write something like this: 使用ActiveCell可以编写如下代码:

Sub Macro1()ActiveCell.Value = "foo"
End Sub

If you want to use it for a cell that is not the active one, for instance for "B2", you should select it first, like this: 如果要将其用于非活动单元格,例如“ B2”,则应首先选择它,如下所示:

Sub Macro2()Range("B2").SelectMacro1
End Sub

Using Ranges you can write a more generic macro that can be used to set the value of any cell you want to whatever you want: 使用范围,您可以编写一个更通用的宏,该宏可用于将所需的任何单元格的值设置为所需的任何值:

Sub SetValue(cellAddress As String, aVal As Variant)Range(cellAddress).Value = aVal
End Sub

Then you can rewrite Macro2 as: 然后,您可以将Macro2重写为:

Sub Macro2()SetCellValue "B2", "foo"
End Sub

And Macro1 as: 和Macro1为:

Sub Macro1()SetValue ActiveCell.Address, "foo"
End Sub

Hope this helps to clear things up a little bit. 希望这有助于清除一些问题。


#3楼

Some examples of how to avoid select 如何避免选择的一些例子

Use Dim 'd variables 使用Dim变量

Dim rng as Range

Set the variable to the required range. Set变量设置为所需范围。 There are many ways to refer to a single-cell range 有很多方法可以引用单细胞范围

Set rng = Range("A1")
Set rng = Cells(1,1)
Set rng = Range("NamedRange")

or a multi-cell range 或多单元格范围

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)

You can use the shortcut to the Evaluate method, but this is less efficient and should generally be avoided in production code. 可以使用Evaluate方法的快捷方式,但这效率较低,通常应在生产代码中避免。

Set rng = [A1]
Set rng = [A1:B10]

All the above examples refer to cells on the active sheet . 以上所有示例均涉及活动工作表上的单元格。 Unless you specifically want to work only with the active sheet, it is better to Dim a Worksheet variable too 除非您特别想只使用活动工作表,否则最好也将Worksheet变量变暗。

Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
Set rng = ws.Cells(1,1)
With wsSet rng = .Range(.Cells(1,1), .Cells(2,10))
End With

If you do want to work with the ActiveSheet , for clarity it's best to be explicit. 如果您确实想使用ActiveSheet ,为清楚起见,最好是明确的。 But take care, as some Worksheet methods change the active sheet. 但是要小心,因为某些Worksheet方法会更改活动工作表。

Set rng = ActiveSheet.Range("A1")

Again, this refers to the active workbook . 同样,这是指活动工作簿 Unless you specifically want to work only with the ActiveWorkbook or ThisWorkbook , it is better to Dim a Workbook variable too. 除非您特别想只使用ActiveWorkbookThisWorkbook ,否则也最好对Workbook变量进行调暗。

Dim wb As Workbook
Set wb = Application.Workbooks("Book1")
Set rng = wb.Worksheets("Sheet1").Range("A1")

If you do want to work with the ActiveWorkbook , for clarity it's best to be explicit. 如果您确实想使用ActiveWorkbook ,为清楚起见,最好是明确的。 But take care, as many WorkBook methods change the active book. 但是请注意,因为许多WorkBook方法都会更改活动书本。

Set rng = ActiveWorkbook.Worksheets("Sheet1").Range("A1")

You can also use the ThisWorkbook object to refer to the book containing the running code. 您还可以使用ThisWorkbook对象来引用包含运行代码的书。

Set rng = ThisWorkbook.Worksheets("Sheet1").Range("A1")

A common (bad) piece of code is to open a book, get some data then close again 常见的(不好的)代码是打开一本书,获取一些数据然后再次关闭

This is bad: 这不好:

Sub foo()Dim v as VariantWorkbooks("Book1.xlsx").Sheets(1).Range("A1").ClearWorkbooks.Open("C:\Path\To\SomeClosedBook.xlsx")v = ActiveWorkbook.Sheets(1).Range("A1").ValueWorkbooks("SomeAlreadyOpenBook.xlsx").ActivateActiveWorkbook.Sheets("SomeSheet").Range("A1").Value = vWorkbooks(2).ActivateActiveWorkbook.Close()
End Sub

And would be better like: 最好是这样的:

Sub foo()Dim v as VariantDim wb1 as WorkbookDim  wb2 as WorkbookSet wb1 = Workbooks("SomeAlreadyOpenBook.xlsx")Set wb2 = Workbooks.Open("C:\Path\To\SomeClosedBook.xlsx")v = wb2.Sheets("SomeSheet").Range("A1").Valuewb1.Sheets("SomeOtherSheet").Range("A1").Value = vwb2.Close()
End Sub

Pass ranges to your Sub s and Function s as Range variables 将范围作为范围变量传递给SubFunction

Sub ClearRange(r as Range)r.ClearContents'....
End SubSub MyMacro()Dim rng as RangeSet rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:B10")ClearRange rng
End Sub

You should also apply Methods (such as Find and Copy ) to variables 您还应该将方法(例如FindCopy )应用于变量

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

If you are looping over a range of cells it is often better (faster) to copy the range values to a variant array first and loop over that 如果要遍历某个单元格的范围,通常最好(更快)先将范围值复制到一个变量数组,然后遍历该单元格

Dim dat As Variant
Dim rng As Range
Dim i As LongSet rng = ThisWorkbook.Worksheets("SomeSheet").Range("A1:A10000")
dat = rng.Value  ' dat is now array (1 to 10000, 1 to 1)
for i = LBound(dat, 1) to UBound(dat, 1)dat(i,1) = dat(i,1) * 10 'or whatever operation you need to perform
next
rng.Value = dat ' put new values back on sheet

This is a small taster for what's possible. 这是一个可能的小尝试者。


#4楼

Two Main reasons why .Select / .Activate / Selection / Activecell / Activesheet / Activeworkbook etc... should be avoided 为什么主要有两个原因.Select / .Activate / Selection / Activecell / Activesheet / Activeworkbook等...应避免

  1. It slows down your code. 它会减慢您的代码速度。
  2. It is usually the main cause of runtime errors. 它通常是运行时错误的主要原因。

How do we avoid it? 我们如何避免呢?

1) Directly work with the relevant objects 1)直接处理相关对象

Consider this code 考虑这段代码

Sheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "Blah"
Selection.NumberFormat = "@"

This code can also be written as 该代码也可以写成

With Sheets("Sheet1").Range("A1").Value = "Blah".NumberFormat = "@"
End With

2) If required declare your variables. 2)如果需要,声明您的变量。 The same code above can be written as 上面的相同代码可以写成

Dim ws as worksheetSet ws = Sheets("Sheet1")With ws.Range("A1").Value = "Blah".NumberFormat = "@"
End With

#5楼

I'm going to give the short answer since everyone else gave the long one. 我要给出简短的答案,因为其他所有人都给出了很长的答案。

You'll get .select and .activate whenever you record macros and reuse them. 每当记录宏并重用它们时,您都会获得.select和.activate。 When you .select a cell or sheet it just makes it active. 当您选择一个单元格或工作表时,只会使其处于活动状态。 From that point on whenever you use unqualified references like Range.Value they just use the active cell and sheet. 从那时起,每当您使用不合格的引用(如Range.Value它们仅使用活动单元格和工作表。 This can also be problematic if you don't watch where your code is placed or a user clicks on the workbook. 如果您不注意代码的放置位置或用户单击工作簿,这也会造成问题。

So, you can eliminate these issues by directly referencing your cells. 因此,您可以通过直接引用单元格来消除这些问题。 Which goes: 哪去了:

'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)

Or you could 或者你可以

'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"

There are various combinations of these methods, but that would be the general idea expressed as shortly as possible for impatient people like me. 这些方法有各种各样的组合,但是对于像我这样不耐烦的人,这将是尽可能短的表达的总体思路。


#6楼

One small point of emphasis I'll add to all the excellent answers given above: 我将在上面给出的所有出色答案中添加一点重点:

Probably the biggest thing you can do to avoid using Select is to as much as possible, use named ranges (combined with meaningful variable names) in your VBA code . 要避免使用Select,最大的可能就是尽可能在VBA代码中使用命名范围(结合有意义的变量名称)This point was mentioned above, but glossed over a bit; 上面已经提到了这一点,但略有掩饰。 however, it deserves special attention. 但是,它值得特别注意。

Here are a couple additional reasons to make liberal use of named ranges though I am sure I could think of more. 尽管我确信我可以想到更多的原因,但还有另外两个原因可以自由使用命名范围。

Named ranges make your code easier to read and understand. 命名范围使您的代码更易于阅读和理解。

Example: 例:

Dim Months As Range
Dim MonthlySales As RangeSet Months = Range("Months")
'e.g, "Months" might be a named range referring to A1:A12Set MonthlySales = Range("MonthlySales")
'e.g, "Monthly Sales" might be a named range referring to B1:B12Dim Month As Range
For Each Month in MonthsDebug.Print MonthlySales(Month.Row)
Next Month

It is pretty obvious what the named ranges Months and MonthlySales contain, and what the procedure is doing. 很明显, MonthsMonthlySales的命名范围包含什么,以及该过程在做什么。

Why is this important? 为什么这很重要? Partially because it is easier for other people to understand it, but even if you are the only person who will ever see or use your code, you should still use named ranges and good variable names because YOU WILL FORGET what you meant to do with it a year later, and you will waste 30 minutes just figuring out what your code is doing. 部分原因是因为它使其他人更容易理解它,但是即使您是唯一会看到或使用您的代码的人,您仍应使用命名范围和良好的变量名,因为您将忘记使用它的意图一年后, 您将花费 30分钟来弄清楚您的代码在做什么。

Named ranges ensure that your macros do not break when (not if!) the configuration of the spreadsheet changes. 命名范围可确保您的宏在电子表格配置更改时(如果没有!)不会中断。

Consider, if the above example had been written like this: 考虑一下,如果上面的示例是这样写的:

Dim rng1 As Range
Dim rng2 As RangeSet rng1 = Range("A1:A12")
Set rng2 = Range("B1:B12")Dim rng3 As Range
For Each rng3 in rng1 Debug.Print rng2(rng3.Row)
Next rng3

This code will work just fine at first - that is until you or a future user decides "gee wiz, I think I'm going to add a new column with the year in Column A !", or put an expenses column between the months and sales columns, or add a header to each column. 这段代码起初会很好用-直到您或将来的用户决定“老兄,我想我要在A列中添加年份的新列!”,或在月份之间插入费用列和销售列,或为每个列添加标题。 Now, your code is broken. 现在,您的代码已损坏。 And because you used terrible variable names, it will take you a lot more time to figure out how to fix it than it should take. 而且由于使用了可怕的变量名,因此花了更多的时间弄清楚如何解决它,而不是应该花费的时间。

If you had used named ranges to begin with, the Months and Sales columns could be moved around all you like, and your code will continue working just fine. 如果您使用命名范围作为开头,则可以根据需要随意移动“ Months和“ Sales列,并且代码将继续正常运行。

如何避免在Excel VBA中使用选择相关推荐

  1. Excel VBA中的等价(Eqv)和蕴含(Imp)

    在一般的编程语言中,逻辑运算只有四个 - Not - And - Or - Xor 但在Excel VBA中,还有 - Eqv 逻辑等价 - Imp 逻辑蕴含 他们的真值表如下 现给逻辑等价Eqv和逻 ...

  2. EXCEL VBA 中关于斗牛的算法

    EXCEL VBA 中关于斗牛的算法 初学EXCEL VBA,只能用最简单的穷举法来算斗牛了.具体规则是,5个数字,任意3个数字相加为10的倍数,其他两个数字相加,大于10则减去10,小于10则为牛几 ...

  3. excel自动筛选_在Excel 2007中按选择自动筛选

    excel自动筛选 在Excel 2007中按选择自动筛选 (AutoFilter by Selection in Excel 2007) A couple of weeks ago I descri ...

  4. 在Excel VBA中使用字典

    序言 VBA的基础数据类型里面并没有字典类型,但字典其实在很多应用场景中都很有用,那么如何在VBA中使用字典,本文就用几个例子和大家交流探讨一下. 场景1 某个医院每天都会从不同的制造商那里进三种材料 ...

  5. shell if多个条件判断_萌新关于Excel VBA中IF条件判断语句的一点心得体会

    作者:金人瑞 <Excel VBA175例无理论纯实战教程>学员 最近正在学习郑广学老师的VBA 175例教程,这是一篇新手向的文章,也是一个新手的总结,高手可以批评文章中的不足之处,也可 ...

  6. 如何在 Excel VBA 中插入行

    在本文中,我将解释如何使用VBA(Visual Basic for Applications)在Excel中插入行.VBA 是一种编程语言,适用于在Excel和其他Office程序中工作的人员,因此可 ...

  7. 在Excel VBA中写SQL,是一种什么体验

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  8. Excel VBA中判断word文件是否打开,未打开则打开该文件

    需求与场景 在Excel的VBA中,打开Word文件是比较容易的,但判断某个word文件是否已经打开,则有些小坑需要注意. 因为工作需求,要把Excel中的数据写入到指定的word文件里(用链接的方式 ...

  9. EXCEL VBA中变量的作用域 工程级变量使用注意小点

    ** 标题过程级,模块级,工程级变量** 一张图说明具体的区别 作用域不同,存放位置,声明的方式不同 举例1 结果只显示工程级,模块级,模块级变量,过程级变量只能在过程里引用 举例2 新建模块2,复制 ...

最新文章

  1. 简单粗暴的多对象目标跟踪神器 – DeepSort
  2. TCP三次握手及tcpdump抓包
  3. java字符串的替换replace、replaceAll、replaceFirst的区别
  4. php图文消息带代码详细注释,微信发送图文消息代码整理
  5. Windows ThinPC 最终版已 RTM
  6. VTK:PolyData之CellLocatorVisualization
  7. 如何提升你的代码能力?
  8. 每日一题(35)—— heap与stack的差别
  9. jq之$(“p.test“)
  10. 【MyBatis框架】高级映射-一对多查询
  11. iis服务器文件上传大小限制,windows服务器中iis限制文件大小方法
  12. 使用h5py操作hdf5文件
  13. ServerSideIncludeModule不是可识别的本机模块
  14. 《相关性准则——大数据时代的高效能之道》一一2.3 数字信息
  15. 【TDA4系列】通过MCU域的R5F1_0启动全部核心MAIN域核心(R5F DSP A73)
  16. Android 自定义View 三板斧之三——重写View来实现全新控件
  17. 花样机模板电脑CAD免费打板转格式软件PS300B使用步骤教程:日本兄弟牌Brother花样机通用CAD画图打板.dxf文件转.emb文件
  18. 医院招聘护士 计算机证,医院招聘护士的自我介绍
  19. log4j2.xsml配置文件详细
  20. History of Object Recognition (物体识别)

热门文章

  1. POS机系统 秘钥体系
  2. vc6.0 记录一些常见问题的解决方案
  3. 算法----- 在排序数组中查找元素的第一个和最后一个位置
  4. 您的手机上未安装应用程序 android 点击快捷方式提示未安装程序的解决
  5. Android之横向滑动的广告(网格控件)
  6. Swift 字典转数组
  7. (0075)iOS开发之cocoapods使用OpenSSL报target has libraries with conflicting names: libcrypto.a and libssl.a
  8. ftp 信息服务器日常维护,Web Ftp Mail服务器的日常管理与维护
  9. uniapp定义全局变量方法
  10. Mac 配置flutter