在VBA中引用Excel单元格

时间:2017-10-16 16:10:35

标签: vba

我的主要问题是分配变量并在VBA中操作它。

我知道这段代码有效,但我不确定这是否是在VBA中分配变量的正确方法,就像我对currentcell = Cells(i,1).Value

一样
Sub C()
Dim i As Integer
For i = 1 To 4
currentcell = Cells(i, 1).Value
MsgBox currentcell
Next i
End Sub

1 个答案:

答案 0 :(得分:1)

宏录制器和许多教程不会告诉你的是,这些调用隐含地引用了ActiveSheet,这显然隐含在ActiveWorkbook中。当你需要处理的只是一个单独的工作表时,它可能很好,但实际情况是从来没有这种情况,用ActiveSheet隐式引用编写的代码非常脆弱,容易出错,而且底层导致过多的Stack Overflow问题被标记为

  • Cells
  • Range
  • Name
  • Rows
  • Columns

每当您使用其中任何一个时,您都会针对某个全局范围的Property Get访问者进行调用,该访问者“方便地”为您提取ActiveSheet引用:

  

Rubberduck toolbar showing "Excel._Global.Cells (property get accessor:Range)"

     

Rubberduck工具栏的屏幕截图,显示所选代码的声明网站。 免责声明:我管理开源VBIDE加载项目。

所以是的,这个“有效”,但你想要的是取而代之的是显式的 Worksheet对象引用。有许多方法来获取Worksheet对象引用,但最好的方法是不关心工作表的来源,并将其作为参数:

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 ThisWorkbook.Worksheets("Period" & n)

或者其他什么。有很多方法,每种都有自己的陷阱 - 通常你会看到这样的东西:

DoSomething Sheets("Sheet1") 'where "Sheet1" is in ThisWorkbook

Sheets隐式引用ActiveWorkbook 之外,ThisWorkbook 可能是Sheets Chart集合可能会返回Worksheet 1}}对象,不是"Sheet1"。此外,如果ThisWorkbook位于CodeName(包含正在运行的代码的工作簿)中,则按名称引用工作表意味着只要用户重命名该工作表的选项卡,代码就会中断。

引用编译/设计时存在的工作表的最强大方法是CodeName。在 Project Explorer (Ctrl + R)中选择工作表,然后打开 Properties 工具窗口(F4),并通过更改{{(Name)来设置它。 1}}属性到你需要的任何东西:VBA用这个名称定义一个全局范围的全局对象变量,所以你可以调用它MyAwesomeReport然后在代码中引用它:

DoSomething MyAwesomeReport

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

您的代码(无论该代码片段多么小)还有其他问题,特别是它使用未声明的变量,这意味着您没有使用Option Explicit,这是另一件事情,最终会在后端咬你并且在Stack Overflow中遇到一个令人尴尬的问题,归结为一个错字 - 因为在每个模块的顶部都没有指定Option Explicit,VBA会很乐意编译一个拼写错误,使你的代码行为异常,而不是简单地编译。这些错误很难找到,而且它们很容易被阻止:

  

使用。选项。明确。总是