在VBA中引用Excel单元格

在VBA中引用Excel单元格,vba,Vba,我的主要问题是分配一个变量,并在VBA中对其进行操作 我知道这段代码可以工作,但我不确定这是否是在VBA中分配变量的正确方法,就像我在currentcell=Cells(I,1).Value中所做的那样 宏记录器和许多教程不会告诉您的是,这些调用隐式地引用了ActiveSheet,这显然隐式地存在于ActiveWorkbook中。当您需要处理的只是一张工作表时,这可能没什么问题,但现实情况是,情况并非如此,使用ActiveSheet的隐式引用编写的代码极其脆弱,容易出现错误,而且太多堆栈溢出问题

我的主要问题是分配一个变量,并在VBA中对其进行操作

我知道这段代码可以工作,但我不确定这是否是在VBA中分配变量的正确方法,就像我在currentcell=Cells(I,1).Value中所做的那样


宏记录器和许多教程不会告诉您的是,这些调用隐式地引用了
ActiveSheet
,这显然隐式地存在于
ActiveWorkbook
中。当您需要处理的只是一张工作表时,这可能没什么问题,但现实情况是,情况并非如此,使用
ActiveSheet
的隐式引用编写的代码极其脆弱,容易出现错误,而且太多堆栈溢出问题背后的根本原因是:

  • 单元格
  • 范围
  • Name
无论何时使用其中任何一个,您都在对某个全局作用域
属性Get
访问器进行调用,该访问器“方便地”为您获取
ActiveSheet
引用:

的工具栏截图,显示所选代码的声明站点免责声明:我管理那个开源VBIDE加载项项目

是的,这个“有效”,但您需要的是使用显式的
工作表
对象引用。获取
工作表
对象引用的方法有很多,但最好的方法是不关心工作表来自何处,并将其作为参数:

Sub DoSomething(ByVal ws As Worksheet)
    Dim currentCell As Variant
    Dim i As Integer
    For i = 1 To 4
        currentcell = ws.Cells(i, 1).Value
        'in-cell error values can't be converted to a string:
        If Not IsError(currentCell) Then MsgBox currentcell
    Next i
End Sub
这负责准确地知道在过程之外使用什么工作表,并将其交给调用代码,代码可以如下所示:

DoSomething Sheet1 'uses the sheet's CodeName property
DoSomething Sheets("Sheet1") 'where "Sheet1" is in ThisWorkbook
或者这个:

DoSomething ThisWorkbook.Worksheets("Period" & n)
或者别的什么。有很多种方法,每种方法都有自己的局限性——通常你会看到这样的情况:

DoSomething Sheet1 'uses the sheet's CodeName property
DoSomething Sheets("Sheet1") 'where "Sheet1" is in ThisWorkbook
除了
工作表
隐式引用
活动工作簿
,它可能是也可能不是
此工作簿
,并且
工作表
集合可以返回一个
图表
对象,该对象不是
工作表
。此外,如果
“Sheet1”
位于
此工作簿中(包含正在运行的代码的工作簿),则按名称引用工作表意味着一旦用户重命名该工作表的选项卡,代码就会中断

引用编译/设计时存在的工作表的最可靠的方法是通过其
代码名
。在项目资源管理器中选择工作表(Ctrl+R),然后打开“属性”工具窗口(F4),并通过将
(名称)
属性更改为所需的任何属性来设置其
(名称)
):VBA根据该名称定义全局范围全局对象变量,因此,您可以将其称为
MyAwesomeReport
,然后在代码中引用它:

DoSomething MyAwesomeReport
如果用户更改工作表的“名称”,则该代码不会中断


您的代码(无论代码片段多么小)还有其他问题,特别是它使用了未声明的变量,这意味着您没有使用
选项Explicit
,这是另一件事,它最终会咬到你的屁股,并带来一个尴尬的问题,归结为一个打字错误——因为如果没有在每个模块的顶部指定
Option Explicit
,VBA会很高兴地编译一个打字错误,使你的代码行为异常,而不是简单地不编译。这些漏洞很难找到,而且很容易预防:

使用。选项明确的总是


也许你可以先试试谷歌。这个太宽了。堆栈溢出不是为了复制几乎所有教程中的材质而设计的。话虽如此,当您在学习VBA时遇到特定困难时,堆栈溢出是一个很好的资源。如果你有很好的编程背景,你会发现VBA很容易学习。在短短的几个小时内,您应该能够学习一个可用的子集。请查看我的编辑,John,谢谢。@johncleman除了很多VBA教程外,其他很多教程都是糟糕的学习材料,教的东西都是错误的。所有的东西都放在一个地方,现在都不见了。我更希望看到像这样的主动、渴望学习“最佳实践”的问题,而不是另一个重复的问题,问他们为什么在代码中使用非限定的隐式
ActiveSheet
引用出现运行时错误1004,因为这是他们从在线教程中复制/粘贴的内容,或改编自宏录制器代码。@newacc2240请参阅类似这样的“教程”,它可以在不声明或使用单个对象变量的情况下,从工作表中获取工作簿引用、获取工作表引用和访问范围,并将所有内容放在一条指令中,这正是为什么人们首先要编写糟糕的VBA代码,即在相同的行中对同一对象进行30次解引用。偶尔出现一个过于宽泛的问题,当它生成这样的答案时,这并不是一件坏事+1.