none
How to conditionally prevent or revert style changes RRS feed

  • Question

  • We are making use of both plain text content controls and rich text ones. When the plain text ones are created, a pre-defined style (chosen by other factors) is applied around the content control. I need to either prevent the user from changing that style or revert it back any time they do change it.

    I can disable the style-related functions on the ribbon when the current selection is on those controls, but that isn't sufficient to handle paste operations that keep or merge formatting, nor changing the style via an already open StylesPane. I thought I had found several commands to repurpose that might help, but none of them are triggered by the actions I tried.

    Is there a solution for me?

    Wednesday, September 17, 2014 2:40 PM

Answers

  • The Document Protection route seems to be better for our needs and I'm going that way.

    But to wrap up this thread, the approach is mostly usable:

    1. ContentControlOnExit provides an easy way to catch and revert most unwanted changes.  (Thank you, macropod.)  I found 3 ways Word can apply a new style to the text in a plain text content control, and there may be others, so it is easier to always revert the style than to discern when it actually needs to be reverted.
    2. There are a bundle of other ways the user can change the style of the text in the content control (paste, Format Painter, etc.  Also see the post "Disable button under Paste Options: in Office 2013").  BeforeSave is executed when saving and during document close (even when not saving under conditions identified in the post "Why do we get different 'Save before exit' dialogs?"), and is a place where any previously missed unwanted changes can be reverted.  Again, it's easier to always revert the style than to discern if it actually needs to be reverted.
    3. The SelectionChanged event can be used to recognize when the selection wraps the content control and nothing else so the Ribbon elements can then be appropriately disabled.
    4. The Apply Styles taskpane can be hidden to stop it from changing things.  (See the related post, "How to temporarily hide the Apply Styles taskpane," (which this website won't let me add a link to!) for how to do that. Other style-related taskpanes are easier to manage.)

    • Marked as answer by JohnWhitmire Monday, September 22, 2014 2:22 PM
    • Edited by JohnWhitmire Monday, September 22, 2014 2:30 PM refine answer
    Monday, September 22, 2014 2:22 PM

All replies

  • Hi John,

    Did you have any code for this case?

    If so, would you mind sharing the steps how to reproduce your case?

    If you made changes in Word manually, I would move this thread to Technet Word forum for more effective responses.

    Regards,

    George.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, September 18, 2014 7:42 AM
    Moderator
  • You could use a pair of ContentControlOnEnter and ContentControlOnExit macros to re-apply your Style to content control's range. For example:

    Dim Stl As String

    Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
    Stl = ContentControl.Range.Style.NameLocal
    End Sub

    Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
    With ContentControl.Range
      .Font.Reset
      .ParagraphFormat.Reset
      .Style = Stl
    End With
    End Sub


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Thursday, September 18, 2014 8:24 AM
  • Although I would prefer the "prevent" approach over the "revert" approach, this works for all but two cases I've found so far.

    1. User saves the document without exiting the content control. I can handle this in the BeforeSave event.
    2. User selects the content control paragraph from the margin and changes the style via the ApplyStyles taskpane. The selection is already outside the content control, extending from one position before to one position after. I don't see a solution for that.

    [As an aside on 2, when the TaskPaneFormatting taskpane ("Styles") is showing, I can hide it by setting its Visible property if I don't want the user using it (and restore it otherwise). The same is true for the StyleInspector taskpane. But when the TaskPaneApplyStyles taskpane ("Apply Styles") is showing, I can't change the value of its Visible property to false (although I can change it to true?!). How do I stop them from using that path?]


    • Edited by JohnWhitmire Thursday, September 18, 2014 8:06 PM
    Thursday, September 18, 2014 3:51 PM
  • You could handle both of those cases with the following macros:

    Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
      Call CCtrlReformat(ContentControl)
    End Sub

    Sub AutoClose()
    Application.ScreenUpdating = False
    Dim CCtrl As ContentControl, bSvd As Boolean
    With ActiveDocument
      bSvd = .Saved
      For Each CCtrl In .ContentControls
        Call CCtrlReformat(CCtrl)
      Next
      If .Saved = False And bSvd = True Then .Save
    End With
    Application.ScreenUpdating = True
    End Sub

    Sub CCtrlReformat(CCtrl As ContentControl)
    With CCtrl
      If .ShowingPlaceholderText = False Then
        If .DefaultTextStyle <> "" Then
          If .Range.Style <> .DefaultTextStyle Then
            .Range.Font.Reset
            .Range.ParagraphFormat.Reset
            .Range.Style = .DefaultTextStyle
          End If
        End If
      Else
        .Range.Text = ""
      End If
    End With
    End Sub

    Note that, with these macros, you don't need the ContentControlOnEnter macro.


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Thursday, September 18, 2014 10:38 PM
  • If I follow this correctly, it's using the same basic approach for ContentControlOnExit and adding a catch-all when the document closes that runs through the content controls and patches up what escaped the other event handler. I assume that AutoClose is the equivalent of the C# BeforeSave event, and if so, I had already implemented this approach (with virtually the same architecture) in some of my prototyping.  It doesn't really "handle" case 2; it just recovers from it, potentially very long after it occurred (which is clearly sub-optimal).

    So... from these two suggestions, it's looking like prevention is not possible and nearly-immediate recovery is not possible in every case. The other fork in my research is looking at Document Protection as a possible means of accomplishing this, although I'm not fond of reassessing and adjusting the protection settings on every selection change. Is that a viable approach?

    Also, is there an answer for my puzzle about TaskPaneApplyStyles?

    Friday, September 19, 2014 12:02 PM
  • Except for the last-selected content control, the updates occur on exit. It really doesn't matter whether the user has changed the formatting from outside the content control beforehand. Of course, if the user changes the formatting after exiting the content control, or fails to exit the last content control, a ContentControlOnExit macro can't catch that.

    AutoClose isn't the equivalent of a BeforeSave event. It's closer to a BeforeClose event. VBA too can access a document's BeforeSave event, via a DocumentBeforeSave macro - and the BeforeClose event via a DocumentBeforeClose macro. I wasn't aware before that you're using events, so I provided a different route to the same end, but you could do the same via a DocumentBeforeSave macro or a DocumentBeforeClose macro. These event macros require Class instantiation and the implementation of a Class module. See: http://word.mvps.org/FAQs/MacrosVBA/AppClassEvents.htm.

    If you're going to go down the event route, though, you could use a WindowSelectionChange macro to trap any user selections that span or fall within a content control. That would enable you to resolve any format changes on the fly.


    Cheers
    Paul Edstein
    [MS MVP - Word]

    Friday, September 19, 2014 12:51 PM
  • The Document Protection route seems to be better for our needs and I'm going that way.

    But to wrap up this thread, the approach is mostly usable:

    1. ContentControlOnExit provides an easy way to catch and revert most unwanted changes.  (Thank you, macropod.)  I found 3 ways Word can apply a new style to the text in a plain text content control, and there may be others, so it is easier to always revert the style than to discern when it actually needs to be reverted.
    2. There are a bundle of other ways the user can change the style of the text in the content control (paste, Format Painter, etc.  Also see the post "Disable button under Paste Options: in Office 2013").  BeforeSave is executed when saving and during document close (even when not saving under conditions identified in the post "Why do we get different 'Save before exit' dialogs?"), and is a place where any previously missed unwanted changes can be reverted.  Again, it's easier to always revert the style than to discern if it actually needs to be reverted.
    3. The SelectionChanged event can be used to recognize when the selection wraps the content control and nothing else so the Ribbon elements can then be appropriately disabled.
    4. The Apply Styles taskpane can be hidden to stop it from changing things.  (See the related post, "How to temporarily hide the Apply Styles taskpane," (which this website won't let me add a link to!) for how to do that. Other style-related taskpanes are easier to manage.)

    • Marked as answer by JohnWhitmire Monday, September 22, 2014 2:22 PM
    • Edited by JohnWhitmire Monday, September 22, 2014 2:30 PM refine answer
    Monday, September 22, 2014 2:22 PM
  • And now the plot thickens. There are times when applying the style through ContentControl.Range.set_Style that the font color of the placeholder text gets changed. I can do this manually, too, by applying, say, Heading 2 to the control twice.  How do I revert that back to the normal placeholder text color without changing the color of the text later typed into the control?
    Monday, October 6, 2014 7:07 PM