Resting Anchor

The Anchorage

Personal website of Gregory K. Maxey, Commander USN (Retired)

Content Controls – Don't Print Placeholder Text
(A Microsoft Word Help & Tip page by Gregory K. Maxey)

DISCLAIMER/TERMS OF USE

The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.

If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!

Click to donate British Pound Sterling                   Click to donate US dollars                   Click to donate EU euros

This Microsoft Word Tips & Microsoft Word Help page provides a couple of solutions to the frequently asked question, "How do I prevent the placeholder text (PHT) in uncompleted content controls from printing?"  The solutions provided are a result of collaborative effort with MVP Jay Freedman.

The problem can occur often.  You prepare a form and send it out for completion.  Users complete part of the form and leave some of the content controls uncompleted.   When the form is returned and printed the PHT in the uncompleted content controls are printed.  This results in an unsightly finished form.

don't print cc placeholder text
Representation of a printed document with bubble added for emphasis

Unfortunately there isn't a simple solution.  There is no option in Word to exclude printing content control PHT, and without an intensive form validation process, you can't make the user fill out each field.

Each of the automated solutions provided require VBA which means the template and form documents must be macro enabled (i.e., .dotm and .docm extensions).

Method I - Detect Events/Intercept Commands/Modify PHT Style

The first method employs the application event "DocumentBeforePrint," repurposed Print commands and a temporary modification of the document's Placeholder text style.

Placeholder text, like most text in Word, is defined by a style.  If you temporarily set the Placeholder text style font property .Hidden to true, set the application options .PrintHiddenText property to false and print the document the PHT text will not be printed. This can of course be done manually if you have a willing group of form users, but an automated process requires a VBA solution.

Site Note Icon Notes:
     1. The Normal project is project associated with the Normal template.  It is global and always loaded.

     2.  The method is developed for Word 2010, but includes all necessary code for Word 2013 and 2007 users.  Some elements (e.g., the class module) is not required for Word 2007.

VBA Script:
Option Explicit
Private WithEvents m_oWordApp As Word.Application
Private Sub Class_Initialize()
 Set m_oWordApp = Word.Application
lbl_Exit:
  Exit Sub
End Sub

Private Sub m_oWordApp_DocumentBeforePrint(ByVal oDoc As Document, Cancel As Boolean)
Dim bOption As Boolean
  If Not p_bQuickPrint Then
    If Not p_bInPreviewPrintEditMode Then
      'Store current user option setting
      bOption = Options.PrintHiddenText
      'Turn off printing hidden text
      Options.PrintHiddenText = False
      'Modify the placeholder text style
      ActiveDocument.Styles("Placeholder Text").Font.Hidden = True
    End If
    'Execute the print command
    CommandBars.ExecuteMso "PrintPreviewAndPrint"
    'Pause to allow printer to spool document. Then undo style modification
    Application.OnTime Now + TimeValue("00:00:05"), "RestorePlaceholders"
    'Restore user option
    Options.PrintHiddenText = bOption
    'Return to document
    CommandBars.ExecuteMso "PrintPreviewAndPrint"
  End If
lbl_Exit:
  Exit Sub
End Sub
VBA Script:
Option Explicit
Public p_bInPreviewPrintEditMode As Boolean
Public p_bQuickPrint As Boolean
Private session_clsPrint As clsPrint
Private bOption as Boolean

Sub AutoExec()
 'Initialize variable and class (Word 2010/2013 only) when Word starts
 p_bQuickPrint = False
 p_bInPreviewPrintEditMode = False
 If Application.Version > 12.0 Then
   Set session_clsPrint = New clsPrint
 End If
lbl_Exit:
  Exit Sub
End Sub

Sub RestorePlaceholders()
   'Delayed call from class Word 2010/2013 only
   ActiveDocument.Styles("Placeholder Text").Font.Hidden = False
lbl_Exit:
  Exit Sub
End Sub

Sub FilePrint()
  'Intercepts the Word 2007 Menu>Print>Print command
  bOption = Options.PrintHiddenText
  Options.PrintHiddenText = False
  ActiveDocument.Styles("Placeholder Text").Font.Hidden = True
  Dialogs(wdDialogFilePrint).Show
  ActiveDocument.Styles("Placeholder Text").Font.Hidden = False
  Options.PrintHiddenText = bOption
End Sub

Sub FilePrintDefault()
  'Intercepts the Word 2007/2010/2013 Quick Print commands
  'Prevent triggering a duplicate print in the class modules (Word 2010/2013)
  p_bQuickPrint = True
  If Not p_bInPreviewPrintEditMode Then
    bOption = Options.PrintHiddenText
    Options.PrintHiddenText = False
    ActiveDocument.Styles("Placeholder Text").Font.Hidden = True
    ActiveDocument.PrintOut Background:=False
    ActiveDocument.Styles("Placeholder Text").Font.Hidden = False
    Options.PrintHiddenText = bOption
  Else
    ActiveDocument.PrintOut Background:=False
  End If
  p_bQuickPrint = False
lbl_Exit:
  Exit Sub
End Sub

Sub PrintPreviewEditMode()
  'Intercepts the Word 2010 Print Preview/2013 Edit Mode
  If p_bInPreviewPrintEditMode Then
    'User likely was in PPEM then used PPPM but didn't print. PHT already modified
    ActiveDocument.PrintPreview
  Else
    p_bInPreviewPrintEditMode = True
    bOption = Options.PrintHiddenText
    Options.PrintHiddenText = False
    ActiveDocument.Styles("Placeholder Text").Font.Hidden = True
    ActiveDocument.PrintPreview
    Options.PrintHiddenText = bOption
  End If
lbl_Exit:
  Exit Sub
End Sub

Sub FilePrintPreview()
  'Intercepts the Word 2007 Print Preview command
  bOption = Options.PrintHiddenText
  Options.PrintHiddenText = False
  ActiveDocument.Styles("Placeholder Text").Font.Hidden = True
  ActiveDocument.PrintPreview
  Options.PrintHiddenText = bOption
lbl_Exit:
  Exit Sub
End Sub

Sub ClosePreview()
  ActiveDocument.Styles("Placeholder Text").Font.Hidden = False
  p_bInPreviewPrintEditMode = False
  On Error GoTo lbl_Exit
  ActiveDocument.ClosePrintPreview
lbl_Exit:
  Exit Sub
End Sub

Site Note IconNote:  You have to close and restart Word in order fo the AutoExec macro to initialize the clsPrint class.

The following is an explanation of how the process more or less works:

Site Note IconNotes:
1. If you often print large forms, you may want to increase the delay. This delay is needed because changing the Hidden attribute immediately (at the end of the DocumentBeforePrint routine) would happen before the PrintPreviewAndPrint command has time to spool the content to the printer queue.
2. Due to a plethora of complications associated the inability to intercept the PrintPreviewAndPrint command, the PHT will still appear visible in the backstage preview pane when you select the File tab in Word 2010/2013, but that visible PHT IS NOT printed.
3. If you really want to see what the document will look like with PHT suppressed then add  the PrintPreviewAndEdit control to your QAT.  In Print Preview and Edit mode, the PHT is suppressed. 
4. If while in the Print Preview and Edit mode you select the Print Preview and Print control the backstage view and preview appears with the PHT suppressed.
5. If you print (i.e, select the "Print" command) the PHT is suppressed in the printed document and then restored after the short delay.
6. However, if you don't print and return to the document by clicking one of the other tabs on the ribbon then the PHT will not be restored and remain formatted as hidden text.
7. In this situation,  you can restore PHT by immediately switching to Print Preview and Edit mode then closing the mode.

Method II - Detect Events/Intercept Commands/Modify PHT Object

The second method, similar to the first, employs the application event "DocumentBeforePrint," repurposed Print commands and a temporary alteration of the PHT object itself.

Placeholder text, is a bit peculiar.  While it appears to be text, a content control's .PlaceholderText property is actually a Building Block object with a value.  For a more in depth discussion see:  5 Curiosities about Placeholders in Word Content Controls (for developers).  If we temporarily set the .PlaceholderText property to a zero width space (i.e., ChrW(8203), before printing and restore then original PHT after printing the results will be similar to method I.  The code is a bit more complicated and the only advantage is we don't tinker with user options or restrict printing of hidden text in general.

The jury is still deliberating if there is any real advantage over either method, but I use method II in my Content Control Tools Add-In. So here it is:

Site Note Icon Note:  If you have already created the modules using method I then simply delete the existing content in the modules.  Do not attempt to use both methods simultaneously.

VBA Script:
Option Explicit
Private WithEvents m_oWordApp As Word.Application

Private Sub Class_Initialize()
  Set m_oWordApp = Word.Application
End Sub

Private Sub m_oWordApp_DocumentBeforePrint(ByVal Doc As Document, Cancel As Boolean)
  If Not p_bQuickPrint Then
   If Not p_bInPreviewPrintEditMode Then
     'Call procedures in the standard module to alter placeholder text
     modPrint.DimensionArray
     modPrint.Processor 2
   End If
   'Execute the print command
   CommandBars.ExecuteMso "PrintPreviewAndPrint"
   'Pause to allow printer to spool document. Then call procedure to restore placeholder
   DoEvents
   Application.OnTime Now + TimeValue("00:00:05"), "modPrint.RestorePHT" 
   'Toggle back to document
   CommandBars.ExecuteMso "PrintPreviewAndPrint"
  End If
lbl_Exit:
  Exit Sub
End Sub
VBA Script:
Option Explicit
Public p_bInPreviewPrintEditMode As Boolean
Public p_bQuickPrint As Boolean
Private session_clsPrint As clsPrint
Private oRngStory As Word.Range
Private lngValidator As Long
Private oCC As ContentControl
Private oShp As Shape
Private arrPHT() As String
Private i As Long
Public Type CCCollection
  Count As Long
  bContainsCCs As Boolean
End Type
Private m_bModifiedCCs As Boolean

Sub AutoExec()
 'Initialize variables and class when Word starts
 p_bQuickPrint = False
 p_bInPreviewPrintEditMode = False
 If Application.Version > 12# Then
   Set session_clsPrint = New clsPrint
 End If
lbl_Exit:
  Exit Sub
End Sub

Sub DimensionArray()
  'Count CCs in document
  i = Processor(1).Count
  ReDim arrPHT(i)
lbl_Exit:
  Exit Sub
End Sub

Sub RestorePHT()
  'Called from clsPrint
  modPrint.Processor 3
lbl_Exit:
  Exit Sub
End Sub

Sub FilePrint()
  'Intercepts the Word 2007 Menu>Print>Print command
  'Call procedures alter placeholder text
  DimensionArray
  Processor 2
  Dialogs(wdDialogFilePrint).Show
  'Call procedures to restore placeholder text
  Processor 3
lbl_Exit:
  Exit Sub
End Sub

Sub FilePrintDefault()
  'Intercepts the Word 2007/2010/2013 Quick Print commands
  p_bQuickPrint = True
  If Not p_bInPreviewPrintEditMode Then
    'Call procedures alter placeholder text
    DimensionArray
    Processor 2
    'Print the document
    ActiveDocument.PrintOut
    'Call procedures to restore placeholder text
    Processor 3
  Else
    ActiveDocument.PrintOut
  End If
  p_bQuickPrint = False
lbl_Exit:
  Exit Sub
End Sub

Sub PrintPreviewEditMode()
  'Intercepts the Wor 2010 PrintPreviewEditMode command
  If p_bInPreviewPrintEditMode Then
    'User likely was in PPEM then used PPPM but didn't print
    ActiveDocument.PrintPreview
  Else
    p_bInPreviewPrintEditMode = True
    m_bModifiedCCs = False
    DimensionArray
    If Processor(2).bContainsCCs = True Then
      m_bModifiedCCs = True
    End If
    ActiveDocument.PrintPreview
  End If
  If m_bModifiedCCs Then Application.StatusBar = "CC PHT modified"
lbl_Exit:
  Exit Sub
End Sub

Sub FilePrintPreview()
  'Intercepts the Word 2007 PrintPreview command
  m_bModifiedCCs = False
  DimensionArray
  If Processor(2).bContainsCCs = True Then
    m_bModifiedCCs = True
  End If
  ActiveDocument.PrintPreview
  If m_bModifiedCCs Then Application.StatusBar = "CC PHT modified"
lbl_Exit:
  Exit Sub
End Sub

Sub ClosePreview()
  p_bInPreviewPrintEditMode = False
  Processor 3
  On Error GoTo lbl_Exit
  ActiveDocument.ClosePrintPreview
lbl_Exit:
  On Error GoTo 0
  Exit Sub
End Sub

Function Processor(ByRef lngAction As Long) As CCCollection
  Dim oCount As Long
  i = 0
  lngValidator = ActiveDocument.Sections(1).Headers(1).Range.StoryType
  For Each oRngStory In ActiveDocument.StoryRanges
    'Iterate through all linked stories
    Select Case oRngStory.StoryType
      Case 1 To 11
        Do
          For Each oCC In oRngStory.ContentControls
            Select Case lngAction
              Case 1
                oCount = oCount + 1
              Case 2
                oCount = oCount + 1
                'Store placeholder text
                arrPHT(i) = oCC.PlaceholderText
                'Set temporary placeholder text
                oCC.SetPlaceholderText , , ChrW(8203)
                i = i + 1
              Case 3
               If oCC.ShowingPlaceholderText Then
                 'Restore stored placeholder text
                 oCC.SetPlaceholderText , , arrPHT(i)
               End If
               i = i + 1
            End Select
          Next oCC
          Select Case oRngStory.StoryType
            Case 6, 7, 8, 9, 10, 11
              If oRngStory.ShapeRange.Count > 0 Then
                For Each oShp In oRngStory.ShapeRange
                  On Error GoTo Err_HasText
                  If oShp.TextFrame.HasText Then
                    For Each oCC In oShp.TextFrame.TextRange.ContentControls
                      Select Case lngAction
                        Case 1
                          oCount = oCount + 1
                        Case 2
                          'Store placeholder text
                          arrPHT(i) = oCC.PlaceholderText
                          'Set temporary placeholder text
                          oCC.SetPlaceholderText , , ChrW(8203)
                          i = i + 1
                        Case 3
                          If oCC.ShowingPlaceholderText Then
                           'Restore stored placeholder text
                           oCC.SetPlaceholderText , , arrPHT(i)
                          End If
                         i = i + 1
                      End Select
                    Next oCC
                  End If
                  On Error GoTo 0
Err_HasText_ReEntry:
                Next oShp
              End If
            Case Else
            'Do Nothing
          End Select
          'Get next linked story (if any)
          Set oRngStory = oRngStory.NextStoryRange
        Loop Until oRngStory Is Nothing
      Case Else
    End Select
  Next oRngStory
  Processor.Count = oCount
  If oCount > 0 Then
    Processor.bContainsCCs = True
  End If
  Exit Function
Err_HasText:
  Resume Err_HasText_ReEntry
End Function

The process and procedures are similar to Method I, instead of changing the PHT style, it:

Method III - Document Content Control Events/Custom Placeholder Text

Method III employs an individual document template, the Document_ContentControlOnEnter & Document_ContentControlOnExit events and custom PHT applied dynamically as the user completes the form.

cc do not print pht 2
Design Mode view

cc do not print pht 3
cc do not print pht
VBE code pane
VBA Script:
Option Explicit
Private Sub Document_New()
  ActiveDocument.SelectContentControlsByTitle("Name").Item(1).Range.Select
lbl_Exit:
  Exit Sub
End Sub

Private Sub Document_Open()
  ActiveDocument.SelectContentControlsByTitle("Name").Item(1).Range.Select
lbl_Exit:
  Exit Sub
End Sub

Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
Select Case ContentControl.Title
  Case "Name"
    ContentControl.SetPlaceholderText , , "Click and enter your name here."
  Case "Address"
    ContentControl.SetPlaceholderText , , "Click and enter your address here."
  Case "Phone Number"
    ContentControl.SetPlaceholderText , , "Click and enter your phone number here."
End Select
lbl_Exit:
  Exit Sub
End Sub

Private Sub Document_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
  If ContentControl.ShowingPlaceholderText = True Then
    ContentControl.SetPlaceholderText , , " "
  End If
lbl_Exit:
  Exit Sub
End Sub

Unlike the previous methods, this method has no relationship with the application print processes.  It simply uses the built-in document events to dynamically apply or remove a visible placeholder text as the user navigates the form. 

Site Note IconNote:  This method is the least robust since it is possible that a user enters a CC displaying the visible placeholder text and then prints the document without first exiting the CC.  You, or your users, must be sure to physically "exit" any uncompleted document CC.

Conclusion

If properly applied each of the three methods will result in a more appealing printed form.

cc do not print pht 5

That's it! I hope you have found this tips page useful and informative.

Share

DISCLAIMER/TERMS OF USE

The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.

If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!

Click to donate British Pound Sterling                   Click to donate US dollars                   Click to donate EU euros

Search my site or the web using Google Search Engine

Google Search Logo