了解VBA中With关键字的确切操作 - 意外行为

时间:2014-07-09 11:24:02

标签: vba excel-vba excel

为了重构和优化某些vba代码,我开始使用with替换一系列重复引用单个对象的语句。

起初我以为

Object.operation1()
Object.operation2()

相当于

With Object
    .operation1()
    .operation2()
End With

并且差别在于第二个解决方案只是更快,因为我们只引用了一次对象。

然后我遇到了以下情况:

我有一张逐行填充的工作表,使用.End(xlDown)查找最后一个空闲行,并且Offset(params)感谢访问单元格:

案例1

Sheets("Sheet1").Range("A1").End(xlDown).Offset(1, 0) = aValue
Sheets("Sheet1").Range("A1").End(xlDown).Offset(0, 1) = anOtherValue

结果

 XXX           XXX           XXX             <- Old line
 aValue        anOtherValue                  <- New line

等同于

案例2

With Sheets("Sheet1").Range("A1").End(xlDown)
    .Offset(1, 0) = aValue
    .Offset(0, 1) = anOtherValue
End With

结果

 XXX           anOtherValue  XXX
 aValue        

相当于

案例3

With Sheets("Sheet1").Range("A1").End(xlDown)
    .Offset(1, 0) = aValue
    .Offset(1, 1) = anOtherValue
End With

结果

 XXX           XXX           XXX
 aValue        anOtherValue

注意:通过&#34;等效&#34;我的意思是&#34;结果相同&#34;

我想,在With设置值后,工作表就会更新,这就是为什么第二种情况第二种Offset()认为没有新的单元格中已填充单元格(这就是为什么anOtherValue不在右边单元格中的原因,因为当调用Offset(0,1)时应该包含aValue的单元格是空的)。 希望这很清楚......

所以(最后)我的问题是:

有谁知道With确切如何工作/行为?因为我没有在网上找到任何清晰的描述。我知道它只引用了一次该对象,但这是否意味着它在此过程中没有对该对象进行更新?

1 个答案:

答案 0 :(得分:2)

With只是获取并保存对指定对象的引用。该参考文献没有改变。 (你可以把它想象成一个隐含的变量)

由于显而易见的原因,您的end(xlDown)代码第二次没有引用相同的范围,因此它不等同于您的With块。

假设您已选择A1,并运行此代码:

Sub foo()
    With ActiveCell
        ActiveCell.Offset(1).Select
        MsgBox .Address
    End With
End Sub

即使活动单元格现在为A2,您也会在消息中获得A1,因为这是With行运行时的活动单元格。

同样,如果你选择A1并运行它:

Sub bar()
    With ActiveCell
        ActiveCell.Cut ActiveCell.Offset(1)
        MsgBox .Address
    End With
End Sub

即使活动单元格仍为A1,您也会在消息中看到A2,因为With块引用的单元格已被移动。请注意,如果您复制它而不是剪切,则消息将显示A1,因为该单元格未被移动。