Issue with UndoRecord.StartCustomRecord in VSTO add-in: Undo stack breaks after bullet/numbering

Kasun Bamunuarachchi 0 Reputation points
2025-08-28T11:24:36.35+00:00

I am using UndoRecord.StartCustomRecord in Microsoft.Office.Interop.Word to create custom undo records in my VSTO add-in. However, I’ve encountered some unexpected behavior that makes the Word undo stack unusable.

(I put the same question on Stackoverflow as well and got no answer, so posting the question here too.)

Here’s what I did:

  • From a button click, I performed a Find and Replace operation and applied styles using the set_Style() method.
  • These actions were wrapped inside UndoRecord.StartCustomRecord and UndoRecord.EndCustomRecord.

Issue: When I try to perform these custom actions after adding bullets or numbering, my custom undo record does not appear in the Undo stack as expected. Instead:

  • The “Replace All” operation gets unfolded (treated as a separate undo steps rather than a single custom action).
  • I can no longer undo actions that occurred before my custom action execution.

This essentially breaks the Undo stack.

Code snippet I used:Here’s what I did:

  • From a button click, I performed a Find and Replace operation and applied styles using the set_Style() method.
  • These actions were wrapped inside UndoRecord.StartCustomRecord and UndoRecord.EndCustomRecord.

Issue: When I try to perform these custom actions after adding bullets or numbering, my custom undo record does not appear in the Undo stack as expected. Instead:

  • The “Replace All” operation gets unfolded (treated as a separate undo steps rather than a single custom action).
  • I can no longer undo actions that occurred before my custom action execution.

This essentially breaks the Undo stack.

Code snippet I used:

Word.Range currentRange = Globals.ThisAddIn.Application.Selection.Range;

var application = Globals.ThisAddIn.Application;
var document = application.ActiveDocument;

this.undoRecord = application.UndoRecord;

this.undoRecord.StartCustomRecord("MyRecord");
string replacementText = "";

Word.Find find = currentRange.Find;
find.ClearFormatting();
find.Replacement.ClearFormatting();
find.Text = "^p"; // Paragraph break
find.Replacement.Text = replacementText;
find.Forward = true;
find.Wrap = Word.WdFindWrap.wdFindStop;
find.Format = false;
find.MatchCase = false;
find.MatchWholeWord = false;
find.MatchWildcards = false;
find.Execute(Replace: Word.WdReplace.wdReplaceAll);

foreach (Word.Paragraph paragraph in document.Paragraphs)
{
    paragraph.Range.set_Style(Microsoft.Office.Interop.Word.WdBuiltinStyle.wdStyleEmphasis);
}

this.undoRecord.EndCustomRecord();

I made a sample project in GitHub to recreate this issue. You can build the GitHub sample and try to recreate the issue. Following are the recreation steps.

  • Add some paragraphs to the document
  • Add a number or bullet from Numbering menu.
  • Click on the top button in my VSTO plugin.
  • Custom undo action doesn't reflect properly in Undo stack
  • If the same actions were done to a document without bullets or numbering, undo stack will be unharmed and will work properly.

Am I using UndoRecord.StartCustomRecord incorrectly, or is this a limitation/bug in Word’s undo stack? How should I correctly implement custom undo records in this scenario?

Developer technologies | C#
0 comments No comments
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.