我注意到Project 2007具有允许可以撤消的操作放在单个堆栈项中的功能,或"撤消事务".例如:
Application.OpenUndoTransaction "Create 6 tasks" Dim i As Integer For i = 1 To 6 ActiveProject.Tasks.Add "UndoMe " & i Next Application.CloseUndoTransaction
这意味着用户可以在单个撤消操作中撤消所有操作,而不是6次.
这在Word和/或Excel中实现会很棒,因为我在VSTO中做了一些可以同时进行多项更改的东西,如果用户必须多次点击撤消,这对用户来说会有点烦人.他们犯了一个错误.虽然这些特定功能似乎不存在,但是有人知道是否/如何以某种方式完成这项工作?
您可以通过覆盖VBA中的撤消和重做命令例程来模拟Word中的事务行为(我不认为仅使用VSTO可以覆盖内置Word命令).通过添加书签来标记交易的开始,通过删除书签来标记结束.
在调用undo时,我们检查是否存在事务标记书签并重复撤消,直到标记消失.重做工作方式相同.此机制支持对文档内容执行的所有修改的事务性撤消/重做.但是,要允许撤消/重做对文档属性的修改,需要使用SetCustomProp宏实现特殊机制.不应直接设置文档属性,只能通过此宏设置.
更新:我忘了清楚地提到这种方法仅适用于键盘快捷键和菜单命令,单击工具栏按钮仍然会执行单步撤消.因此,我们决定用自定义按钮替换工具栏按钮.代码已经使用了很长一段时间使用Word 2003(它没有使用Word 2007进行测试,所以要做好准备应对惊喜;)
Option Explicit ' string constants for Undo mechanism Public Const BM_IN_MACRO As String = "_InMacro_" Public Const BM_DOC_PROP_CHANGE As String = "_DocPropChange_" Public Const BM_DOC_PROP_NAME As String = "_DocPropName_" Public Const BM_DOC_PROP_OLD_VALUE As String = "_DocPropOldValue_" Public Const BM_DOC_PROP_NEW_VALUE As String = "_DocPropNewValue_" '----------------------------------------------------------------------------------- ' Procedure : EditUndo ' Purpose : Atomic undo of macros ' Note: This macro only catches the menu command and the keyboard shortcut, ' not the toolbar command '----------------------------------------------------------------------------------- Public Sub EditUndo() ' Catches Ctrl-Z 'On Error Resume Next Dim bRefresh As Boolean bRefresh = Application.ScreenUpdating Application.ScreenUpdating = False Do If ActiveDocument.Bookmarks.Exists(BM_DOC_PROP_CHANGE) Then Dim strPropName As String Dim strOldValue As String strPropName = ActiveDocument.Bookmarks(BM_DOC_PROP_NAME).Range.Text strOldValue = ActiveDocument.Bookmarks(BM_DOC_PROP_OLD_VALUE).Range.Text ActiveDocument.CustomDocumentProperties(strPropName).Value = strOldValue End If Loop While (ActiveDocument.Undo = True) _ And ActiveDocument.Bookmarks.Exists(BM_IN_MACRO) Application.ScreenUpdating = bRefresh End Sub '----------------------------------------------------------------------------------- ' Procedure : EditRedo ' Purpose : Atomic redo of macros ' Note: This macro only catches the menu command and the keyboard shortcut, ' not the toolbar command '----------------------------------------------------------------------------------- Public Sub EditRedo() ' Catches Ctrl-Y Dim bRefresh As Boolean bRefresh = Application.ScreenUpdating Application.ScreenUpdating = False Do If ActiveDocument.Bookmarks.Exists(BM_DOC_PROP_CHANGE) Then Dim strPropName As String Dim strNewValue As String strPropName = ActiveDocument.Bookmarks(BM_DOC_PROP_NAME).Range.Text strNewValue = ActiveDocument.Bookmarks(BM_DOC_PROP_NEW_VALUE).Range.Text ActiveDocument.CustomDocumentProperties(strPropName).Value = strNewValue End If Loop While (ActiveDocument.Redo = True) _ And ActiveDocument.Bookmarks.Exists(BM_IN_MACRO) Application.ScreenUpdating = bRefresh End Sub '----------------------------------------------------------------------------------- ' Procedure : SetCustomProp ' Purpose : Sets a custom document property '----------------------------------------------------------------------------------- Public Function SetCustomProp(oDoc As Document, strName As String, strValue As String) Dim strOldValue As String On Error GoTo existsAlready strOldValue = "" oDoc.CustomDocumentProperties.Add _ Name:=strName, LinkToContent:=False, Value:=Trim(strValue), _ Type:=msoPropertyTypeString GoTo exitHere existsAlready: strOldValue = oDoc.CustomDocumentProperties(strName).Value oDoc.CustomDocumentProperties(strName).Value = strValue exitHere: ' support undo / redo of changes to the document properties 'On Error Resume Next Dim bCalledWithoutUndoSupport As Boolean If Not ActiveDocument.Bookmarks.Exists(BM_IN_MACRO) Then ActiveDocument.Range.Bookmarks.Add BM_IN_MACRO, ActiveDocument.Range bCalledWithoutUndoSupport = True End If Dim oRange As Range Set oRange = ActiveDocument.Range oRange.Collapse wdCollapseEnd oRange.Text = " " oRange.Bookmarks.Add "DocPropDummy_", oRange oRange.Collapse wdCollapseEnd oRange.Text = strName oRange.Bookmarks.Add BM_DOC_PROP_NAME, oRange oRange.Collapse wdCollapseEnd oRange.Text = strOldValue oRange.Bookmarks.Add BM_DOC_PROP_OLD_VALUE, oRange oRange.Collapse wdCollapseEnd oRange.Text = strValue oRange.Bookmarks.Add BM_DOC_PROP_NEW_VALUE, oRange oRange.Bookmarks.Add BM_DOC_PROP_CHANGE ActiveDocument.Bookmarks(BM_DOC_PROP_CHANGE).Delete Set oRange = ActiveDocument.Bookmarks(BM_DOC_PROP_NEW_VALUE).Range ActiveDocument.Bookmarks(BM_DOC_PROP_NEW_VALUE).Delete If Len(oRange.Text) > 0 Then oRange.Delete Set oRange = ActiveDocument.Bookmarks(BM_DOC_PROP_OLD_VALUE).Range ActiveDocument.Bookmarks(BM_DOC_PROP_OLD_VALUE).Delete If Len(oRange.Text) > 0 Then oRange.Delete Set oRange = ActiveDocument.Bookmarks(BM_DOC_PROP_NAME).Range ActiveDocument.Bookmarks(BM_DOC_PROP_NAME).Delete If Len(oRange.Text) > 0 Then oRange.Delete Set oRange = ActiveDocument.Bookmarks("DocPropDummy_").Range ActiveDocument.Bookmarks("DocPropDummy_").Delete If Len(oRange.Text) > 0 Then oRange.Delete If bCalledWithoutUndoSupport And ActiveDocument.Bookmarks.Exists(BM_IN_MACRO) Then ActiveDocument.Bookmarks(BM_IN_MACRO).Delete End If End Function '----------------------------------------------------------------------------------- ' Procedure : SampleUsage ' Purpose : Demonstrates a transaction '----------------------------------------------------------------------------------- Private Sub SampleUsage() On Error Resume Next ' mark begin of transaction ActiveDocument.Range.Bookmarks.Add BM_IN_MACRO Selection.Text = "Hello World" ' do other stuff ' mark end of transaction ActiveDocument.Bookmarks(BM_IN_MACRO).Delete End Sub