Search code examples
c#ms-wordvstooffice-interopword-2013

Word interop add-in - changing Window View properties do not affect Revision markup style


Using an application level add-in, I'm performing some operations on document open that require revisions (tracked changes) to be rendered inline and not hidden, so that they are contained within the Range of the document. After consulting the documentation, I thought that all I had to do was change the the view properties of the active window: MarkupMode claims to do what I want.

But this property seems to be completely disconnected from how revisions display in the document! To test this, I tried toggling the mode manually in a document, and looking at MarkupMode, and checking it immediately afterwards in an onSelectionChange event handler. I went ahead and tracked a bunch of properties of ActiveWindow.View, for good measure. To my surprise and chagrin, when I looked at the locals with changes rendered inline:

before

before values

... and compared the values to those with changes hidden:

after

after values

Nothing changed! What gives? Am I not looking at the right property/properties to ensure that changes are rendered inline? Is Microsoft completely incapable of writing meaningful documentation? I'll point out that I tried to make the property change in code as well, to see if the rendering of revisions would change, with no success. I would appreciate any feedback.

Edit: Simple code to duplicate issue:

private void ThisAddIn_Startup(object sender, EventArgs e)
{
    Application.WindowSelectionChange += application_WindowSelectionChange;
}

private void application_WindowSelectionChange(Selection sel)
{
    var testDoc = sel.Document;

    var test = new
    {
        testDoc.ActiveWindow.View,
        testDoc.ActiveWindow.View.ShowRevisionsAndComments,
        testDoc.ActiveWindow.View.ShowInsertionsAndDeletions,
        testDoc.ActiveWindow.View.MarkupMode,
        testDoc.ActiveWindow.View.RevisionsMode
    };
}

Edit 2: Beyond this contrived example, I need to have control over the markup style of Revisions because I am searching for text on DocumentOpen that may include text that is present as Revision objects. More specifically, I am attempting to do the following, using the above text (with text "powerful way to help you prove " deleted in a revision):

private void ThisAddIn_Startup(object sender, EventArgs e)
{
    Application.DocumentOpen += application_DocumentOpen;
}

private void application_DocumentOpen(Document doc)
{
    // expected text, as taken from screengrab example above. Includes
    //  text removed in a revision
    string expectedText = "Video provides a powerful way to help you prove your point.";

    // make sure that we're in print view
    if (doc.ActiveWindow.View.Type != WdViewType.wdPrintView)
    {
        doc.ActiveWindow.View.Type = WdViewType.wdPrintView;
    }

    // attempt to ensure that document revisions are marked up inline. Does not accomplish anything
    doc.ActiveWindow.View.MarkupMode = WdRevisionsMode.wdInLineRevisions;        
    // attempt to locate text. Will fail if revisions are not marked up inline (deletion is not part of document content range otherwise)
    var locatedRange = doc.Content.OccurrenceOfText(expectedText);
}

// extension method to locate text inside a range. Searching entire Content in this example
private static Range OccurrenceOfText(this Range rng, string text)
{
    rng.Find.Forward = true;
    rng.Find.Format = false;

    rng.Find.Execute(text);

    if (!rng.Find.Found)
    {
        throw new Exception("Unable to locate text! Are Revisions marked up inline?");
    }

    // return brand new range containing located content
    return rng.Document.Range(rng.Start, rng.End);
}

Edit 3: As Cindy made clear, my problem was that I was using the wrong property: I needed to use the View.RevisionsFilter.Markup property to make the change. Additionally, an issue that I hadn't diagnosed is that depending on the View properties, it is entirely possible that the Range returned from a search performed as I do returns a Text property that is different than the text that was searched with. This can happen if Revision objects are present inside the Range.


Solution

  • It works for me. What I did:

    1. Created a test document. Used =rand() ->Press Enter to put some text in the document. Copied in the phrase, changing "powerful" to "useful".
    2. Turned on track changes and made some changes, including selecting "useful" and typing "powerful".
    3. Made sure the changes were displaying in balloons and the "Original" view of the mark-up was being shown.
    4. Saved and closed the document.
    5. Put a break-point on the line that calls OccurrenceOfText, then F5 to start the add-in in debug mode.
    6. Opened the saved document. The Open event fired. I checked the values of the View.Markup and View.RevisionsView - they had changed to inline and "Final". Stepped through the rest of the code and it executed correctly (found the occurrence).

    I needed to modify your code slightly since I don't have your "wrapper". I also changed the way OccurrenceOfText returns the Range: no need to do it in the complicated manner you use...

    I note that you do not appear to set View.RevisionsView - perhaps this is why you're not seeing the result you expect?

     private void Application_DocumentOpen(Microsoft.Office.Interop.Word.Document doc)
      {
                //Test revisions
        // expected text, as taken from screengrab example above. Includes
        //  text removed in a revision
        string expectedText = "Video provides a powerful way to help you prove your point.";
    
        // make sure that we're in print view
        if (doc.ActiveWindow.View.Type != Word.WdViewType.wdPrintView)
        {
            doc.ActiveWindow.View.Type = Word.WdViewType.wdPrintView;
        }
    
        // attempt to ensure that document revisions are marked up inline. Does not accomplish anything
        Word.View vw = doc.ActiveWindow.View;
        vw.MarkupMode = Word.WdRevisionsMode.wdInLineRevisions;
        vw.RevisionsView = Word.WdRevisionsView.wdRevisionsViewFinal;      
        // attempt to locate text. Will fail if revisions are not marked up inline (deletion is not part of document content range otherwise)
        var locatedRange = OccurrenceOfText(doc.Content, expectedText);
    }
    
    // extension method to locate text inside a range. Searching entire Content in this example
    private static Word.Range OccurrenceOfText(Word.Range rng, string text)
    {
        rng.Find.Forward = true;
        rng.Find.Format = false;
    
        rng.Find.Execute(text);
    
        if (!rng.Find.Found)
        {
            throw new Exception("Unable to locate text! Are Revisions marked up inline?");
        }
    
        // return brand new range containing located content
        return rng;  //.Document.Range(rng.Start, rng.End);
     }