UtterAccess.com
X   Site Message
(Message will auto close in 2 seconds)

Welcome to UtterAccess! Please ( Login   or   Register )

Custom Search
 
   Reply to this topicStart new topic
> Accessing Content Of Contentcontrols Programmatically, Office 2013    
 
   
MadPiet
post May 14 2019, 01:07 AM
Post#1



Posts: 3,041
Joined: 27-February 09



Well, 2016+

If I have a document built using Bookmarks, it's easy enough to map between those and columns in a table in Access. But what if the document has Content Controls? It looks like Content Controls have a subscript to differentiate them, so how do you know how to map them to a column in a table?

With bookmarks, I could do name each bookmark so it corresponded to say a column in a table, and then mapping was something like

docWord.Bookmarks(rsBkmk.Fields(1).Name)

or
rs.Fields("Salary") = CCur(docWord.Bookmarks("Salary").Text)

and then I could loop through the bookmarks and write their values somewhere.

If Content Controls don't have individual names, how do you map them if you don't know in what order they appear?

It's a theoretical question now, but a job I looked at was trying to process a hundred thousand contracts saved as Word documents. (Or are the poor guys who got the job going to have to read each file manually? That's just plain crazy, in my opinion... hence my question.)

Thanks,

Pieter
Go to the top of the page
 
DanielPineault
post May 14 2019, 07:19 AM
Post#2


UtterAccess VIP
Posts: 6,570
Joined: 30-June 11



Content Controls are a pain programmatically. Hopefully the following might help (just quick and dirty utilities I created a couple years back and aren't properly error handled, ...)

Enumerate the title of each CC in the specified document
CODE
Function EnumerateCCTitles(sDocFile As String)
    Dim oApp                  As Object
    Dim oDoc                  As Object
    Dim oTBx                  As Object
    Dim CC                    As Object
    Dim strTemp               As String
    Dim i                     As Long
    Const msoTextBox = 17

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo 0

    Set oDoc = oApp.Documents.Open(sDocFile)
    oApp.Visible = True
    For Each oTBx In oDoc.Shapes
        If oTBx.Type = msoTextBox Then
            For Each CC In oTBx.TextFrame.TextRange.ContentControls
                Debug.Print CC.Title
            Next
        End If
    Next oTBx
End Function

Do note that you'd think that you could do something like
CODE
For Each CCtrl In oDoc.ContentControls

but it only works if the CCs are part of the 'main story', otherwise it won't list them, that's why I had to create the above!


To extract a value, you can use
CODE
CC.Range.Text

So you could do
CODE
Function EnumerateCCTitles(sDocFile As String)
    Dim oApp                  As Object
    Dim oDoc                  As Object
    Dim oTBx                  As Object
    Dim CC                    As Object
    Dim strTemp               As String
    Dim i                     As Long
    Const msoTextBox = 17

    '     Set oDoc = ActiveDocument
    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo 0

    Set oDoc = oApp.Documents.Open(sDocFile)
    oApp.Visible = True
    For Each oTBx In oDoc.Shapes
        If oTBx.Type = msoTextBox Then
            For Each CC In oTBx.TextFrame.TextRange.ContentControls
                Debug.Print CC.Title, CC.Range.Text
            Next
        End If
    Next oTBx
End Function


But things don't end there.

If the CC is a checkbox then instead of .Range.Text you need to use .Checked

--------------------
Daniel Pineault (2010-2018 Microsoft MVP)
Professional Help: http://www.cardaconsultants.com
Free MS Access Code, Tips, Tricks and Samples: http://www.devhut.net

* Design should never say "Look at me". It should always say "Look at this". -- David Craib
* A user interface is like a joke, if you have to explain it, it's not that good! -- Martin LeBlanc


All code samples, demonstration databases, links,... are provided 'AS IS' and are to be used at your own risk! Take the necessary steps to check, validate ...(you are responsible for your choices and actions)
Go to the top of the page
 
ADezii
post May 14 2019, 07:24 AM
Post#3



Posts: 2,297
Joined: 4-February 07
From: USA, Florida, Delray Beach


  1. To the best of my knowledge, you can uniquely identify Context Controls via an Index into the ContentControls Collection, as in:
    CODE
    ActiveDocument.ContentControls(1)
  2. Each Content Control also has a Unique ID Property.

This post has been edited by ADezii: May 14 2019, 07:25 AM
Go to the top of the page
 
DanielPineault
post May 14 2019, 08:13 AM
Post#4


UtterAccess VIP
Posts: 6,570
Joined: 30-June 11



Just combining ADezii's comments
CODE
Function EnumerateCCTitles(sDocFile As String)
    Dim oApp                  As Object
    Dim oDoc                  As Object
    Dim oTBx                  As Object
    Dim CC                    As Object
    Dim strTemp               As String
    Dim i                     As Long
    Const msoTextBox = 17

    On Error Resume Next
    Set oApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then    'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If
    On Error GoTo 0

    Set oDoc = oApp.Documents.Open(sDocFile)
    oApp.Visible = True
    Debug.Print "Index No", "Id", "Title", "Text"
    For Each oTBx In oDoc.Shapes
        If oTBx.Type = msoTextBox Then
            For Each CC In oTBx.TextFrame.TextRange.ContentControls
                i = i + 1
                Debug.Print i, CC.ID, CC.Title, CC.Range.Text
            Next
        End If
    Next oTBx
End Function


So once you identify the CC Id (assuming the documents are standardized!), then you can more easily bind to them for data extraction and simply use (assuming the id = 3772645804 in the example below)
CODE
ActiveDocument.ContentControls(3772645804).Title

Or in the case of the above
CODE
oDoc.ContentControls(3772645804).Title

CODE
oDoc.ContentControls(3772645804).Range.Text

CODE
oDoc.ContentControls(3772645804).Checked

--------------------
Daniel Pineault (2010-2018 Microsoft MVP)
Professional Help: http://www.cardaconsultants.com
Free MS Access Code, Tips, Tricks and Samples: http://www.devhut.net

* Design should never say "Look at me". It should always say "Look at this". -- David Craib
* A user interface is like a joke, if you have to explain it, it's not that good! -- Martin LeBlanc


All code samples, demonstration databases, links,... are provided 'AS IS' and are to be used at your own risk! Take the necessary steps to check, validate ...(you are responsible for your choices and actions)
Go to the top of the page
 
ADezii
post May 14 2019, 10:23 AM
Post#5



Posts: 2,297
Joined: 4-February 07
From: USA, Florida, Delray Beach


To further complicate matters, a ContextControl exposes a Type Property which can uniquely identify what Type of Control it is:
Attached File(s)
Attached File  Type.JPG ( 89.33K )Number of downloads: 2
 
Go to the top of the page
 


Custom Search


RSSSearch   Top   Lo-Fi    19th May 2019 - 10:05 AM