Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Application.OpenUndoTransaction "Create 6 tasks"
- Dim i As Integer
- For i = 1 To 6
- ActiveProject.Tasks.Add "UndoMe " & i
- Next
- Application.CloseUndoTransaction
- 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
- //Usage from ThisDocument VSTO Document level project
- public partial class ThisDocument
- {
- //Used to buffer writing text & formatting to document (to save undo stack)
- public static DocBuffer buffer;
- //Attached Template
- public static Word.Template template;
- private void ThisDocument_Startup(object sender, System.EventArgs e)
- {
- //Ignore changes to template (removes prompt to save changes to template)
- template = (Word.Template)this.Application.ActiveDocument.get_AttachedTemplate();
- template.Saved = true;
- //Document buffer
- buffer = new DocBuffer();
- //Start buffer
- ThisDocument.buffer.Start();
- //This becomes one "undo"
- Word.Selection curSel = Globals.ThisDocument.Application.Selection;
- curSel.TypeText(" ");
- curSel.TypeBackspace();
- curSel.Font.Bold = 1;
- curSel.TypeText("Hello, world!");
- curSel.Font.Bold = 0;
- curSel.TypeText(" ");
- //end buffer, print out text
- ThisDocument.buffer.End();
- }
- void Application_DocumentBeforeClose(Microsoft.Office.Interop.Word.Document Doc, ref bool Cancel)
- {
- buffer.Close();
- }
- private void ThisDocument_Shutdown(object sender, System.EventArgs e)
- {
- buffer.Close();
- }
- }
- public class DocBuffer
- {
- //Word API Objects
- Word._Document HiddenDoc;
- Word.Selection curSel;
- Word.Template template;
- //ref parameters
- object missing = System.Type.Missing;
- object FalseObj = false; //flip this for docbuffer troubleshooting
- object templateObj;
- //Is docbuffer running?
- public Boolean started{ get; private set; }
- //Open document on new object
- public DocBuffer()
- {
- //Clear out unused buffer bookmarks
- Word.Bookmarks bookmarks = Globals.ThisDocument.Application.ActiveDocument.Bookmarks;
- bookmarks.ShowHidden = true;
- foreach (Word.Bookmark mark in bookmarks)
- {
- if (mark.Name.Contains("_buf"))
- {
- mark.Delete();
- }
- }
- //Remove trail of undo's for clearing out the bookmarks
- Globals.ThisDocument.UndoClear();
- //Set up template
- template = ThisDocument.template;
- templateObj = template;
- //Open Blank document, then attach styles *and update
- HiddenDoc = Globals.ThisDocument.Application.Documents.Add(ref missing, ref missing, ref missing, ref FalseObj);
- HiddenDoc.set_AttachedTemplate(ref templateObj);
- HiddenDoc.UpdateStyles();
- //Tell hidden document it has been saved to remove rare prompt to save document
- HiddenDoc.Saved = true;
- //Make primary document active
- Globals.ThisDocument.Activate();
- }
- ~DocBuffer()
- {
- try
- {
- HiddenDoc.Close(ref FalseObj, ref missing, ref missing);
- }
- catch { }
- }
- public void Close()
- {
- try
- {
- HiddenDoc.Close(ref FalseObj, ref missing, ref missing);
- }
- catch { }
- }
- public void Start()
- {
- try
- {
- //Make hidden document active to receive selection
- HiddenDoc.Activate(); //results in a slight application focus loss
- }
- catch (System.Runtime.InteropServices.COMException ex)
- {
- if (ex.Message == "Object has been deleted.")
- {
- //Open Blank document, then attach styles *and update
- HiddenDoc = Globals.ThisDocument.Application.Documents.Add(ref missing, ref missing, ref missing, ref FalseObj);
- HiddenDoc.set_AttachedTemplate(ref templateObj);
- HiddenDoc.UpdateStyles();
- HiddenDoc.Activate();
- }
- else
- throw;
- }
- //Remove Continue Bookmark, if exists
- Word.Bookmarks hiddenDocBookmarks = Globals.ThisDocument.Application.ActiveDocument.Bookmarks;
- if (hiddenDocBookmarks.Exists("Continue"))
- {
- object deleteMarkObj = "Continue";
- Word.Bookmark deleteMark = hiddenDocBookmarks.get_Item(ref deleteMarkObj);
- deleteMark.Select();
- deleteMark.Delete();
- }
- //Tell hidden document it has been saved to remove rare prompt to save document
- HiddenDoc.Saved = true;
- //Keep track when started
- started = true;
- }
- //Used for non-modal dialogs to bring active document back up between text insertion
- public void Continue()
- {
- //Exit quietly if buffer hasn't started
- if (!started) return;
- //Verify hidden document is active
- if ((HiddenDoc as Word.Document) != Globals.ThisDocument.Application.ActiveDocument)
- {
- HiddenDoc.Activate();
- }
- //Hidden doc selection
- curSel = Globals.ThisDocument.Application.Selection;
- //Hidden doc range
- Word.Range bufDocRange;
- //Select entire doc, save range
- curSel.WholeStory();
- bufDocRange = curSel.Range;
- //Find end, put a bookmark there
- bufDocRange.SetRange(curSel.End, curSel.End);
- object bookmarkObj = bufDocRange;
- //Generate "Continue" hidden bookmark
- Word.Bookmark mark = Globals.ThisDocument.Application.ActiveDocument.Bookmarks.Add("Continue", ref bookmarkObj);
- mark.Select();
- //Tell hidden document it has been saved to remove rare prompt to save document
- HiddenDoc.Saved = true;
- //Make primary document active
- Globals.ThisDocument.Activate();
- }
- public void End()
- {
- //Exit quietly if buffer hasn't started
- if (!started) return;
- //Turn off buffer started flag
- started = false;
- //Verify hidden document is active
- if ((HiddenDoc as Word.Document) != Globals.ThisDocument.Application.ActiveDocument)
- {
- HiddenDoc.Activate();
- }
- //Remove Continue Bookmark, if exists
- Word.Bookmarks hiddenDocBookmarks = Globals.ThisDocument.Application.ActiveDocument.Bookmarks;
- hiddenDocBookmarks.ShowHidden = true;
- if (hiddenDocBookmarks.Exists("Continue"))
- {
- object deleteMarkObj = "Continue";
- Word.Bookmark deleteMark = hiddenDocBookmarks.get_Item(ref deleteMarkObj);
- deleteMark.Delete();
- }
- //Hidden doc selection
- curSel = Globals.ThisDocument.Application.Selection;
- //Hidden doc range
- Word.Range hiddenDocRange;
- Word.Range bufDocRange;
- //Select entire doc, save range
- curSel.WholeStory();
- bufDocRange = curSel.Range;
- //If cursor bookmark placed in, move there, else find end of text, put a bookmark there
- Boolean cursorFound = false;
- if (hiddenDocBookmarks.Exists("_cursor"))
- {
- object cursorBookmarkObj = "_cursor";
- Word.Bookmark cursorBookmark = hiddenDocBookmarks.get_Item(ref cursorBookmarkObj);
- bufDocRange.SetRange(cursorBookmark.Range.End, cursorBookmark.Range.End);
- cursorBookmark.Delete();
- cursorFound = true;
- }
- else
- {
- //The -2 is done because [range object].WordOpenXML likes to drop bookmarks at the end of the range
- bufDocRange.SetRange(curSel.End - 2, curSel.End - 2);
- }
- object bookmarkObj = bufDocRange;
- //Generate GUID for hidden bookmark
- System.Guid guid = System.Guid.NewGuid();
- String id = "_buf" + guid.ToString().Replace("-", string.Empty);
- Word.Bookmark mark = Globals.ThisDocument.Application.ActiveDocument.Bookmarks.Add(id, ref bookmarkObj);
- //Get OpenXML Text (Text with formatting)
- curSel.WholeStory();
- hiddenDocRange = curSel.Range;
- string XMLText = hiddenDocRange.WordOpenXML;
- //Clear out contents of buffer
- hiddenDocRange.Delete(ref missing, ref missing); //comment this for docbuffer troubleshooting
- //Tell hidden document it has been saved to remove rare prompt to save document
- HiddenDoc.Saved = true;
- //Make primary document active
- Globals.ThisDocument.Activate();
- //Get selection from new active document
- curSel = Globals.ThisDocument.Application.Selection;
- //insert buffered formatted text into main document
- curSel.InsertXML(XMLText, ref missing);
- //Place cursor at bookmark+1 (this is done due to WordOpenXML ignoring bookmarks at the end of the selection)
- Word.Bookmarks bookmarks = Globals.ThisDocument.Application.ActiveDocument.Bookmarks;
- bookmarks.ShowHidden = true;
- object stringObj = id;
- Word.Bookmark get_mark = bookmarks.get_Item(ref stringObj);
- bufDocRange = get_mark.Range;
- if (cursorFound) //Canned language actively placed cursor
- bufDocRange.SetRange(get_mark.Range.End, get_mark.Range.End);
- else //default cursor at the end of text
- bufDocRange.SetRange(get_mark.Range.End + 1, get_mark.Range.End + 1);
- bufDocRange.Select();
- }
Add Comment
Please, Sign In to add comment