Writing from Excel, to Word Activex Text box

Viewed 325

I have an Excel application which collects information via a form based interface. This is used to;

  1. Fill values in the workbook
  2. A procedure opens a Word document (template essentially) and names the file according to rules, based on some of the input data. (Okay to this point)
  3. The idea then, is to transfer collected information (from the Excel app driving this process) to the same Word document opened and named. Specifically, I intend to populate a number of uniquely named ActiveX textboxes with document.

    *** This is where I fail miserably.

I have enabled the "Microsoft Word 16.0 Object Library" under references in the MSExcel VBA environment.

Given that I know the name/title of the content control (ActiveX textbox is a 'content control' isn't it?). The code below is a simplified example, if it works for the example I should be able to sort out the broader document:

Sub trial()
Dim Word As Word.Application
Dim wdDoc As Word.Document
On error resume next
Set Word = New Word.Application
Set wdDoc = Word.Documents.Open("G:\CAPS Management Tool\Customer.docm")
Word.Application.Visible = True
Dim cc As Object
Set cc = ActiveDocument.SelectContentControlsByTitle(txt_PersonName) 'txt_PersonName is the control name
cc.Range.Text = "SUCCESS"  'Run-time error 438
                           'Object does not support property or method
Set cc = ActiveDocument.SelectContentControlsByTitle(txt_Address) 'txt_Address is the control name
cc.Range.Text = "SUCCESS"  'Run-time error 438
                           'Object does not support property or method
End Sub

Anybody able to assist? There are a lot of text boxes in the Word document I wish to plug in to.

Thanks in advance.

2 Answers

OK, so I kept digging (I don't like accepting defeat) and found that my entire premise was wrong! ActiveX controls in Word are considered "InlineShapes" not "ContentControls". But the results I was reading in the internet searches had me confused (didn't claim to be the sharpest tool in the shed).

Once I realised this, some more digging provided the answer (see below).

So, first to list the 3 controls in my document (and their index) with the following Sub

Sub ListActiveXControls()
Dim i As Integer
i = 1
Do Until i > ActiveDocument.InlineShapes.Count
Debug.Print ActiveDocument.InlineShapes(i).OLEFormat.Object.Name & "    Control Index = " & i
i = i + 1
Loop
End Sub

Now moving to EXCEL, I used the following:

Sub trial()
Dim Word As Word.Application
Dim wdDoc As Word.Document
Set Word = New Word.Application
Set wdDoc = Word.Documents.Open("G:\CAPS Management Tool\Customer.docm")
Word.Application.Visible = True
debug.print "ActiveDocument Name is : " & ActiveDocument.Name 
' Result = Nothing
' Allowing the code to continue without the pause caused the operation to fail
Application.Wait (Now + TimeValue("0:00:10")) ' See text below, would not work without pause
wdDoc.Activate
' Begin set ActiveX control values. In this instance,
' The first line corresponds to 'Textbox1'
ActiveDocument.InlineShapes(1).OLEFormat.Object.Text = "Success"
' The second line corresponds to 'Textbox2'
ActiveDocument.InlineShapes(2).OLEFormat.Object.Text = "Success"
' The third line corresponds to 'ChkBox1'
ActiveDocument.InlineShapes(3).OLEFormat.Object.Value = True
End Sub

For some reason, without the 'Wait' command, the operation fails. Stepping through, if there is no pause, the ActiveDocument seems to be null, no idea why. It occurs with a document with 2 ActiveX controls or 165 ActiveX controls and the wait required seems to be 10 secs on my PC. Incidentally, setting almost 150 control values was only seconds, once the wait period was completed.

If anyone knows why the 'Wait' is seemingly required, I'd be interested to know!

Here are a few tips to help you work this out.

  1. Don't use On Error Resume Next unless you really need it. And then when you do use it, re-enable error catching with On Error Goto 0 as quickly as possible. Otherwise you'll miss many errors in your code and it will be hard to tell what's happening.
  2. Don't use the name Word as a variable name. It is reserved for the Word.Application and will only confuse the compiler (and you).
  3. The control titles are text strings, so you must enclose them in double-quotes.
  4. I've thrown in a bonus Sub that gives you a quick method to either open a new Word application instance or attach to an existing application instance. You'll find that (especially during debugging) there will be dozens of Word exe's opened and running.

The example code below also breaks the assignment of your "SUCCESS" value to the control into a separate Sub. It's in this short Sub that using On Error Resume Next is appropriate -- and isolated from the rest of the logic -- limiting its scope.

Option Explicit

Sub trial()
    Dim wdApp As Word.Application
    Dim wdDoc As Word.Document
    Set wdApp = AttachToMSWordApplication
    Set wdDoc = wdApp.Documents.Open("C:\Temp\Customer.docm")
    wdApp.Application.Visible = True
    TextToControl wdDoc, "txt_PersonName", "SUCCESS"
    TextToControl wdDoc, "txt_Address", "SUCCESS"
End Sub

Private Sub TextToControl(ByRef doc As Word.Document, _
                          ByVal title As String, _
                          ByVal value As String)
    Dim cc As ContentControl
    On Error Resume Next
    Set cc = doc.SelectContentControlsByTitle(title).Item(1)
    If Not cc Is Nothing Then
        cc.Range.Text = value
    Else
        Debug.Print "ERROR: could not find control titled '" & title & "'"
        '--- you could also raise an error here to be handled by the caller
    End If
End Sub

Public Function AttachToMSWordApplication() As Word.Application
    '--- finds an existing and running instance of MS Word, or starts
    '    the application if one is not already running
    Dim msApp As Word.Application
    On Error Resume Next
    Set msApp = GetObject(, "Word.Application")
    If Err > 0 Then
        '--- we have to start one
        '    an exception will be raised if the application is not installed
        Set msApp = CreateObject("Word.Application")
    End If
    Set AttachToMSWordApplication = msApp
End Function
Related