在退出子程序之前,我应该重新启用.CutCopyMode吗?

10
为优化我的代码,我关闭了几个应用程序对象成员属性;其中一个特别的是.CutCopyMode属性
Sub MyProcedure()
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
        .CutCopyMode = False
    End With

    ' lots of code here

在我的子程序完成之前,我应该将.CutCopyMode重新打开(例如设置为True)吗?

    ' lots of code here

    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .CutCopyMode = True     '<~~ ???
    End With
End Sub

1
@pnuts - 除了[excel-2010]是我衡量所有贡献的事实标准之外,我希望避免与我没有直接测试过的xl2007 Office剪贴板行为直接关联。 - user4039065
@Jeeped 我看到了很多 Application.Calculation = xlCalculationManual-Application.Calculation = xlCalculationAutomatic 的使用,这有用吗?如果我添加公式,是否需要设置事件来触发这些公式? - MGP
1
关闭计算可以避免重复计算循环,从而提高效率。当然,这取决于具体的公式。即使是非易失性公式,如果使用了整列引用并且这些引用中的值在循环中被改变,例如更改C4的值,其他地方的=SUM(C:C)也会重新计算。下一次循环时,C5获得新值,又会触发另一个计算循环,以此类推。 - user4039065
1个回答

19
简短回答是,Application.CutCopyMode = True 要么什么也不做,要么就是与你想的相反。如果当前的 .CutCopyMode 状态为 False,则将其设置为 True 不会打开“跳舞边框”,如果当前状态为 xlCopy 或 xlCut(XlCutCopyMode 枚举常量),将 .CutCopyMode 设置为 True 将有效地关闭它。此外,您不能将 .CutCopyMode 设置为 xlCopy 或 xlCut。

长话短说,理解 Application.CutCopyMode 属性 的目的以及官方文档错误地暗示可以将其重新打开是开始的地方。

当您在工作表上手动剪切(Ctrl+X)或复制(Ctrl+C)一个或多个单元格时,单元格将获得一个“跳跃边框”¹,表示操作的来源。此时,.CutCopyMode为非零值(xlCopy或xlCut),并且后续粘贴操作与Office剪贴板和Windows剪贴板之间存在关系,因为它们保留源内容。
如果选择剪切(又称移动)单元格,则在将单元格粘贴(Ctrl+V)到新位置后,.CutCopyMode变为false,并且您会失去源周围的“跳跃边框”。这是因为源单元格中没有剩余内容。内容仍然可以从Office剪贴板中访问,但已从Windows剪贴板中删除。
如果选择复制单元格,则可以将单元格粘贴到其他位置,而“跳跃边框”仍然存在。.CutCopyMode属性保持非零值(例如xlCopy)。您可以移动到另一个位置并粘贴相同的内容;.CutCopyMode保持非零值,并且原始内容周围的“跳跃边框”以及与Office剪贴板和Windows剪贴板之间的关系仍然存在。
如果你在运行包含 Application.CutCopyMode = False 的 VBA 代码时,跳动的边框将会消失,并且任何粘贴操作与 Office 剪贴板之间的连接都将被消除。这是启动 VBA 子过程时所需的良好状态,以便代码中的任何潜在复制/粘贴操作都不会与 .CutCopyMode 状态发生冲突。但是,只有在特殊情况下才需要这样做(请参见下一段)。
某些 Excel 操作足以打破此 Office 剪贴板连接并强制 .CutCopyMode 为 False。其中之一是手动启动宏子过程,因此在代码开头包含 Application.CutCopyMode = False 的受益有限。然而,如果你的代码已经启动了 Range.Copy 操作,并且已经完成了使用复制内容的 Worksheet.Paste methodRange.PasteSpecial method 操作,则在代码中运行可能是明智的。
检查和报告.CutCopyMode的当前状态可以使用一些工作表事件宏代码完成。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Select Case Application.CutCopyMode
        Case True
            Debug.Print "CutCopyMode is ON"
        Case xlCopy
            Debug.Print "CutCopyMode is in Copy mode"
        Case xlCut
            Debug.Print "CutCopyMode is in Cut mode"
        Case False
            Debug.Print "CutCopyMode is OFF"
        Case Else
            Debug.Print "???"
    End Select
End Sub

在 VBE 的立即窗口报告的结果将是复制模式、剪切模式或关闭。Application.CutCopyMode 永远不会直接报告其状态为 True²。

虽然您可以使用 Application.CutCopyMode = False 来改变操作环境,但我从未能够通过将属性设置为 True 来打开 .CutCopyMode。没有错误被抛出,官方文档明确指出将属性设置为 True 会 "启动剪切或复制模式并显示移动边框",但我发现唯一恢复“蚂蚁行进”的方法是启动另一个复制操作。

因此,在所有意图和目的上,编写 Application.CutCopyMode = True 不会造成任何伤害。然而,编写 Application.CutCopyMode = False 可以通过释放剪贴板存储来实现一些好处。

如果有人可以通过操作 Application.CutCopyMode 属性 来重新启动“蚂蚁行进”,我非常希望能看到一个例子。


"The 'dancing border' is also known colloquially as 'marching ants.'
While a boolean value of True or False is a distinct type, for all intents and purposes False equals zero and anything that is not False is True. If resolving boolean to number, a VBA False is 0 and True is always equal to (-1) but if resolving the reverse number to boolean any non-zero number is considered True and a zero is considered False."

我不知道我等了这么久才得到这个问题/解释。写得太棒了!双大拇指 - BruceWayne
2
我认为这只是一份文档错误。虽然可能读取任何可能的状态{-1、0、1、2},但只能将{0}写入该属性。在写入属性时,任何数值都会被强制转换为零。这似乎是合理的,因为每当蚂蚁关闭时,OCB就已经被清除了。再次使昆虫动画化将使用户界面处于模棱两可的状态,表明可以粘贴,但实际上不行,因为OCB是空白的。这种设计是有道理的,但文档却没有解释清楚。 - Excel Hero
你手头时间太多了 =P 我很好奇。这样优化能带来多少效果?需要复制/粘贴多少次才能反映出明显的差异? - findwindow
@findwindow - 说实话,这个问答是为了回应最近在问题中发布的一些代码段中看到的Application.CutCopyMode = True而进行的。我很少在VBA中使用Range.Copy方法,更喜欢直接传递值。 - user4039065
哈哈,我确实想知道你为什么在复制/粘贴,但是后来你撒谎了。你写道 为了优化我的代码... 标记一下 =P - findwindow
为什么在C#中的interop.Excel有值(1和2)?在VBA中,true和false的值在哪里?它们是否指的是同一件事? - liang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接