Share via

SetPlaceholderText Method fails if using Late Binding; but, succeeds if using Early Binding

Anonymous
2018-09-13T21:56:42+00:00

Hi,

Thanks for taking the time to look at this. After spending the better part of a day on it, its time for me to call the calvary. 

I'm working with a procedure that resets a Content Control to its placeholder text with the following code:

Public Function DepopulatedCc(ByVal PopulatedCc As Object) As Object  ' Word.ContentControl

#If LateBinding Then

  Dim oWdApp As Object

  Dim oWdCc As Object

#Else

  Dim oWdApp As Word.Application ' Requires a reference:  Microsoft Word 14.0 Object Library

  Dim oWdCc As Word.ContentControl ' Requires a reference:  Microsoft Word 14.0 Object Library

#End If

  On Error Resume Next

  Set oWdApp = GetObject(, "Word.Application")

  If Err Then

    ' Word is not running.

    GoTo SingleExit

  End If

  On Error GoTo 0

  Dim bLockContents As Boolean

  Dim bLockContentControl As Boolean

  Dim sPlaceHolderText As String

  Set oWdCc = PopulatedCc

  With oWdCc

    ' Grab the existing property values to be restored later.

    bLockContents = .LockContents

    bLockContentControl = .LockContentControl

    ' We need the Content Control and its Contents to be changeable.

    .LockContents = False

    .LockContentControl = False

    Select Case .Type

      Case wdContentControlText

        sPlaceHolderText = .PlaceholderText

        .Range.Text = vbNullString

        .SetPlaceholderText , , sPlaceHolderText ' Error here: Run-time error '13', Type mismatch 

      Case wdContentControlRichText

        sPlaceHolderText = .PlaceholderText

        .Range.Text = vbNullString

        .SetPlaceholderText , , sPlaceHolderText

      Case wdContentControlComboBox

        sPlaceHolderText = .DropdownListEntries(1).Text

        .DropdownListEntries(1).Select ' Don't know if this is working yet

        .SetPlaceholderText , , sPlaceHolderText

      Case wdContentControlDropdownList

        sPlaceHolderText = .DropdownListEntries(1).Text

        .DropdownListEntries(1).Select

        .SetPlaceholderText , , sPlaceHolderText

      Case wdContentControlBuildingBlockGallery

        MsgBox "This is a Building Block Gallery Content Control. " & vbCrLf _

          & "The Application cannot reset this type of control (yet)."

      Case wdContentControlDate

        MsgBox "This is a Date Content Control. " & vbCrLf _

          & "The Application cannot reset this type of control (yet)."

      Case wdContentControlGroup

        MsgBox "This is a Content Control Group. " & vbCrLf _

          & "The Application cannot reset this type of control (yet)." 

      Case wdContentControlCheckBox

        .Checked = False

    End Select

    ' Restore the properties to their original values.

    .LockContents = bLockContents

    .LockContentControl = bLockContentControl

  End With

  Set DepopulatedCc = oWdCc

SingleExit:

  Set oWdCc = Nothing

  Set oWdApp = Nothing

End Function

The code that calls this function assembles a collection of Content Controls in a document or the selected portion of a document and then runs through that collection to remove applied content and redisplay the PlaceholderText.

If LateBinding = True, I'm getting "Run-time error '13' -- Type mismatch" error at the statement indicated. 

When the error is occurring I've used the Intermediate Window to diagnose the conditions as follows:

Debug.Print TypeName(oWdCc)

ContentControl

Debug.Print TypeName(PopulatedCc) 

ContentControl

Debug.Print TypeName(wdContentControlText)

Long

Debug.Print wdContentControlText

 1 

Debug.Print  TypeName(sPlaceHolderText) 

String

Debug.Print sPlaceHolderText 

DocumentAuthorPrincipal

If LateBinding = False, the code does not produce and error, and the results in the Intermediate Window are exactly the same as those produced with LateBinding = True. The results in the Intermediate Window are exactly what I intended for them to be and seem to be as required for the SetPlaceholderText method. So I'm suspecting ignorance on my part or a blunder to which I am blind.

I've used MZ-Tools to Clean the code and rebooted the machine. Just to be sure to be sure and I get the same results. 

I've included a compiler instruction at the beginning of the module to facilitate switching between Early and Late Binding as follows:

       #Const LateBinding = False

The code does work with Early Binding; but does not work with Late Binding. I confirmed that the values for the variables I thought would be important by including a Stop before the error-prone statement and repeating the diagnostic Debug.Print statements described above and got the same results.

Additionally, you may need to know that I have another module containing the following:

#If LateBinding Then

Public Enum WdContentControlType

  wdContentControlRichText = 0             ' Word.WdContentControlType

  wdContentControlText = 1                 ' Word.WdContentControlType

  wdContentControlPicture = 2              ' Word.WdContentControlType

  wdContentControlComboBox = 3             ' Word.WdContentControlType

  wdContentControlDropdownList = 4         ' Word.WdContentControlType

  wdContentControlBuildingBlockGallery = 5 ' Word.WdContentControlType

  wdContentControlDate = 6                 ' Word.WdContentControlType

  wdContentControlGroup = 7                ' Word.WdContentControlType

  wdContentControlCheckBox = 8             ' Word.WdContentControlType

End Enum

#End If

I'd like to use Late Binding when distributing the code to users on various versions of Word 2007+ and because I include the same modules in my Personal.xlsb and Excel add-ins. I hope that this saves me a lot of code management trouble for my applications that control Word from Excel or control Excel from Word; but, there are times when I wonder it it is a good strategy. I will say that I've been learning a lot to make it work and it has been working for me -- at least most of the time.

So, wassup doc?

Bruce

Microsoft 365 and Office | Word | For home | Windows

Locked Question. This question was migrated from the Microsoft Support Community. You can vote on whether it's helpful, but you can't add comments or replies or follow the question.

0 comments No comments

Answer accepted by question author

Anonymous
2018-09-15T22:28:19+00:00

I found a thread started by Alfred Tetzlaf here. That indicated that there may be something about needing to specify all the parameters (BuildingBlock, Range, and Text). In my code, I was unsuccessfully attempting to do this as:

.SetPlaceholderText , , sPlaceHolderText

Based on the clues by Alfred Tetzlaf  I tried some permutations and made some progress. Here is what I learned: 

The following two statements work when Early Binding but fail with Error 13 - Type mismatch when Late Binding:

.SetPlaceholderText Text:=sPlaceHolderText 

.SetPlaceholderText , , sPlaceHolderText  

' The following two statements work when Early or Late Binding.

.SetPlaceholderText BuildingBLock:=Nothing, Range:=Nothing, Text:=sPlaceHolderText 

.SetPlaceholderText Nothing, Nothing, sPlaceHolderText

It appears that it is critical to explicitly provide the BuildingBLock and Range parameters as Nothing. It is not clear to me why these findings are true; but several tests have convinced me they are. 

This seems to be a bug; but, at least the workaround achieves the functional result of being able to use the SetPlaceholderText method with either Early or Late Binding using the same code.

Was this answer helpful?

0 comments No comments

12 additional answers

Sort by: Most helpful
  1. Anonymous
    2018-09-15T01:29:12+00:00

    Thanks Jay and Rich,

    I've been down the route of just setting  .Range.Text = vbNullString in earlier versions of this code. At that time, the placeholder text would occasionally display as "....." (i.e. 5 spaces). That problem would not exist when a Content Control was created initially and used for a while; but, would appear from time-to-time for reasons I was not able to detect (and I tried all sorts of closely controlled trials). When it did occur the only solution was to recreate the Content Control and hope for the best. It would work for a while and then the "....." would start showing up again. Setting the PlaceholderText property directly has been a way to at least assure that I know I've done my part to set it and it is a whale of a lot faster than recreating all the Content Controls from scratch yet AGAIN.

    My motivation for getting this straightened out is that some of my documents include over 2000 Content Controls that are programmatically populated and depopulated. That means the "....." problem would leave users in a really confusing place. Fortunately, I developed some procedures to do the heavy lifting; but, they take a while to execute. My strategy was to use the Depopulate function to effectively reset the Placeholder Text within the scope of routine operations. That way users would have a simple remedy when the "....." problem resurfaces again.  

    If we users don't have the opportunity to use the SetPlaceholderText method, it becomes pretty hard to programmatically create or adjust Content Controls and reliably use the Placeholder Text to display as intended and serve its purpose to communicate to the user that a Content Control is there and what its intent is. It also begs the question; why does the SetPlaceholderText method exist if it does not work correctly. I suspect you'll advocate using Early Binding; but, I've got some reasons for trying to avoid that as expressed earlier and I'm not giving up on that just yet. I'm also very familiar with and heavily use the tools generously provided by Greg Maxey and Graham Mayor. 

    I guess I can try just using the vbNullString approach again and perhaps include an error handler. But I suspect that the error handler would just need to avoid setting the placeholder text and I'd be right back to living with the need to rebuild Content Controls when the  "....." problem surfaces or be limited to Early Binding.

    Based on the information I get from the Immediate Window, I can't see what it is that I'm doing wrong. From that perspective it really seems to be a bug that warrants fixing by Microsoft. There is a pretty large revenue stream coming from Office and a lot of users spend a lot of time working with it productively. I'd like to think there is an economic (if not moral) argument for fixing this.

    Was this answer helpful?

    0 comments No comments
  2. Jay Freedman 207.7K Reputation points Volunteer Moderator
    2018-09-15T00:01:05+00:00

    For at least the Text, RichText, Date, and ComboBox content controls, simply setting .Range.Text = vbNullString is enough to redisplay the PlaceHolderText. The Picture control and the Dropdown List control require special handling, and the Building Block and Repeating Section controls misbehave badly.

    The following code clears all the content controls I'm able to handle and restores them to the placeholder text.

    Sub x()

        Dim CC As ContentControl

        For Each CC In ActiveDocument.ContentControls

            Select Case CC.Type

                Case wdContentControlCheckBox

                    CC.Checked = False

                Case wdContentControlPicture

                    CC.Range.Select

                    Selection.InlineShapes(1).Delete

                    Selection.MoveRight wdCharacter, 1

                Case wdContentControlDropdownList

                    CC.DropdownListEntries(1).Select

                Case wdContentControlBuildingBlockGallery, _

                        wdContentControlRepeatingSection

                    ' do nothing

                Case Else

                    CC.Range.Text = vbNullString

            End Select

        Next CC

    End Sub

    Was this answer helpful?

    0 comments No comments
  3. Anonymous
    2018-09-14T13:20:10+00:00

    Not really. The whole idea is to develop an add-in that works without requiring the user to set a bunch of references or have special versions for various unique situations.

    I've seen enough comments in various posts that indicate Word Content Controls can be a little wonky with respect to PlaceholderText to suspect that the solution might be a bit convoluted. That would be OK because I'd be paying the price of a solution one time and reaping the benefits of having a deployable solution that is not dependent on a compilation solution. I'm not too familiar with the compiled solution idea; but,  I suspect it would need to be applied at every test during development, every deployment, and every update of deployed add-ins. Consequently, the path of least resistance is much less attractive to me than a comprehensive solution that requires work to find and develop once.

    If this is a known problem in Word, I'd appreciate someone from Microsoft or some other authority admitting that is the case so I can stop beating my head against this specific wall. There are plenty of walls around; so, I don't particularly need this one to keep the skin on my forehead from healing.

    Was this answer helpful?

    0 comments No comments
  4. Anonymous
    2018-09-14T12:51:15+00:00

    I think I feel your pain... if you exclusively use early binding and deploy the solution from a source compiled using the appropriate Office 2007 application ... would that development process work for you? It might be the path of least resistance. :-)

    Was this answer helpful?

    0 comments No comments