Reputation: 282
A little more detail:
I have a loop which goes through all the files that need changing which works fine. However, whatever I seem to do, any new controls that I create appear at the beginning of the document and not in the correct place (there is a control with a code for the document before it).
Ideas? As an aside is there any logical reason why changing the control names doesn't work?
Current code:
Sub FieldChanger()
Dim docCur As Document
Dim strCurPath As String
Dim strCurFile As String
Dim rngTitle As Range
Dim strTitle As String
Dim ccName As ContentControl
strCurPath = "C:\Users\User\Desktop\BGS\Final\"
strCurFile = Dir(strCurPath & "*.docx")
Do While strCurrentFile <> ""
Set docCur = Application.Documents.Open(strCurPath & strCurFile)
With docCur.ContentControls
.Item(1).LockContents = False //Unlock outer content control
Set rngTitle = .Item(3).Range
strTitle = rngTitle.Text
rngTitle = rngTitle.Move(wdCharacter, 1)
ccName = rngTitle.ContentControls.Add(wdContentControlRichText) //This line throws a 4198 error
ccName.Title = "ccName"
ccName.Tag = "ccName"
ccName.Range = strTitle
ccName.LockContentControl = True
.Item(3).LockContentControl = False
.Item(3).Delete
.Item(1).LockContents = True //Lock outer content control
End With
docCur.Save
docCur.Close
strCurFile = Dir
Loop
End Sub
Upvotes: 1
Views: 5859
Reputation:
As an aside is there any logical reason why changing the control names doesn't work?
The Content Control (CC) name is just a name. Renaming the CC from "Title" doesn't change where Word gets the content from. Nor would naming a CC as "Title" cause Word to put the document's title string in the CC. If you create an empty document, insert the Title document property (as a CC) and look at the value of
activedocument.ContentControls(1).XMLMapping.XPath
you will probably see the value
/ns1:coreProperties[1]/ns0:title[1]
This is what tells Word that it needs to put the value of the Title builtin document property in the CC, and where to go to get it. You can link your own plain text CCs to builtin properties using the same mechanism, or you can link them to nodes in "Custom XML parts" of your own. But they don't have to be linked to anything.
As for the code, how about something more like this (NB, I have also changed "strCurrentFile" to strCurFile). I wondered whether you really need to re-insert the CC value as a new CC (i.e. why not just remove the CC and leave its existing value there) but have assumed that you need the CC there.
NB, as a general rule in VBA you need to use the Set keyword when setting the value of objects such as range variables and CCs. In theory you should also set objects to Nothing (e.g. Set rngTitle = Nothing) when you have finished with them. I haven't added that stuff here. In VB.NET you don't need to do either of those things.
Dim docCur As Document
Dim strCurPath As String
Dim strCurFile As String
Dim rngTitle As Range
Dim strTitle As String
Dim ccName As ContentControl
strCurPath = "C:\a\test\"
strCurFile = Dir(strCurPath & "*.docx")
Do While strCurFile <> ""
Set docCur = Application.Documents.Open(strCurPath & strCurFile)
With docCur.ContentControls
.Item(1).LockContents = False 'Unlock outer content control
Set rngTitle = .Item(3).Range
strTitle = rngTitle.Text
' we need the following line to ensure that deleting the range
' does not remove the CC prematurely
.Item(3).Temporary = False
rngTitle.Delete
rngTitle.Collapse wdCollapseStart
' Delete the control here instead of later
.Item(3).LockContentControl = False
.Item(3).Delete
Set ccName = rngTitle.ContentControls.Add(wdContentControlRichText)
ccName.Title = "ccName"
ccName.Tag = "ccName"
ccName.Range = strTitle
ccName.LockContentControl = True
.Item(1).LockContents = True 'Lock outer content control
End With
docCur.Save
docCur.Close
strCurFile = Dir
Loop
Comment consolidation...
There are addins that may help, e.g. the databinding toolkit at cctw.codeplex.com (not checked that link recently)
Upvotes: 3