Gav*_*vin 6 .net excel vba vsto ms-word
我注意到Project 2007具有允许可以撤消的操作放在单个堆栈项中的功能,或"撤消事务".例如:
Application.OpenUndoTransaction "Create 6 tasks"
Dim i As Integer
For i = 1 To 6
ActiveProject.Tasks.Add "UndoMe " & i
Next
Application.CloseUndoTransaction
Run Code Online (Sandbox Code Playgroud)
这意味着用户可以在单个撤消操作中撤消所有操作,而不是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
Run Code Online (Sandbox Code Playgroud)