Macro to Modify Content Control Properties for Directory of Documents - vba

I have over 300 documents with a table coverpage, within one of the cells is a content control box with incorrect properties (the title and the tag are both named wrong). I can so far create a macro to fix the properties but only after I click into the cell by opening each document one by one. Is there a way to run a macro that can find this content control box in a table and amend the properties and save?

To search for a Content Control with a certain Title and/or Tag in a document and then change the Title or Tag, you'd use code something like this ...
Dim cc As ContentControl
For Each cc In ActiveDocument.ContentControls
If cc.Range.Information(wdWithInTable) Then
If cc.Tag = "InErrorTag" And cc.Title = "InErrorTitle" Then
'then correct the Tag and Title
cc.Tag = "CorrectedTag"
cc.Title = "CorrectedTitle"
End If
End If
Next
To then perform this replacement in a batch process of updating multiple documents you need additional code.
There is a Wiki article Batch Editing MS Word Documents that provides cross platform (Windows and Mac) VBA code for that purpose. You can merge the article's code with the Content Control replacement code above to accomplish you task.

Related

MS Word: Trying to dynamically update a text field when I change pictures

I create scannable QR codes cards in word for users to report problems. Each time I change the QRCode image, I have to change the Caption under the image to match it to the computer we are labeling. Typing this caption takes time, as 9 cards fit on a single page and each has to be updated when we insert/change the image. I'm trying to figure out how to dynamically change the caption each time I change the picture. I am adding an image as an example below. ANY Help would be appreciated.
enter image description here
I have tried looking at VB to set a label and reference the image filename (which us created with the computer name) and just remove the extension, but I can't figure out how to set the properties for the object and dynamically link them. I have little VB.Net scripting and haven't used it in almost 10 years.
Assumning you need a solution for manual data entry into your 9 cards/labels (even though a mailmerge would work better for bulk card/label creation), if you configure each of them with:
a DISPLAYBARCODE field where your image shows the QR code; and
a text content control where your image shows the serial #,
the following ContentControlOnExit macro, placed in the 'ThisDocument' code module of your document or its template will automatically update the QR code in each label/card to match the serial # whenever its content control is exited.
Private Sub Document_ContentControlOnExit(ByVal CCtrl As ContentControl, Cancel As Boolean)
With CCtrl.Range.Cells(1).Range
.Fields(1).Code.Text = "DISPLAYBARCODE " & CCtrl.Range.Text & " QR \q 3"
.Fields.Update
End With
End Sub

Search text file and put matching results in listbox

I have a VB.NET project in which there is a form where there is a TextBox control, a ListBox control and an external text file that contains a list of outlook folder paths for client emails.
Essentially, the user enters into the text box the name of a client and/or their unique reference number, presses the search button (yes - I know I could make the results appear as they type, I want a button!) and it comes up with the matching results for the company name or serial number that are in the text file and puts them in the list box, with the full path of the outlook email folder.
For example:
If I put into the textbox: "06967759-274D-40B2-A3EB-D7F9E73727D7"
It would put the following result into the listbox:
"EIS Admin\Contacts{06967759-274D-40B2-A3EB-D7F9E73727D7}"
And the user can then go to that folder and find the email(s).
I have gone through several revisions both of my own code and code pasted from online with people having the same issue, only to have Visual Studio throw no errors, run the code and have no luck, with it doing nothing but clearing the list box, and not showing matching results of any kind.
I understand this may be a repeat question but I am extremely confused, can't get anything to work and need some help regarding my issue.
Here is the current code (from online - not mine):
lbx_OFL_Results.Items.Clear()
Dim i As Integer
For i = 0 To lbx_OFL_Results.Items.Count - 1
If i > lbx_OFL_Results.Items.Count - 1 Then Exit For
If Not lbx_OFL_Results.Items(i).Contains(tbx_FindText.Text) Then
lbx_OFL_Results.Items.Remove(lbx_OFL_Results.Items(i))
i -= 1
End If
Next
The list box is called "lbx_OFL_Results"
The textbox is called "tbx_FindText"
I start by clearing the list box of all items (when the form loads, it fills the list box will all lines of the text file, so I need to clear it).
Form Load Event Code:
Dim lines1() As String = IO.File.ReadAllLines("C:\ProgramData\WPSECHELPER\.data\Outlook Folder Wizard\outlookfolders.txt")
lbx_OFL_Results.Items.AddRange(lines1)
For the rest of the code it seems to be doing some form of a 'sort search' then removing any excess results.
If anyone can suggest edits to my code, or new code then that would be sublime.
Thanks.
Thanks to #Jimi for the answer.
Code:
listbox.Items.Clear()
listbox.BeginUpdate()
For i as Integer = 0 To lines1().Length - 1
If lines1(i).Contains(searchbox.Text) Then
listbox.Items.Add(lines1(i))
End If
Next
listbox.EndUpdate()
I have another question which solves how to make this search non case-sensitive. It can be found here.

Fire Subroutine when user leaves a date field ContentControl Word VBA

Edit: I've updated the post with more info.
I have a Content Control inside a header in Word in which I have a date time picker. I'm trying to fire the _ContentControlOnExit event when the user leaves the focus (blurs) of the picker.
Let's suppose I've manually created a Content Control and I've assigned it a Date Picker. I've also tagged it with the value date.
I want that each time the date is changed, I perform a subroutine that will insert a text value to another ContentControl tagged tide-level. I tried the code below with no success.
Please, note that the date ContentControl is inside a header in the Word Document.
Private Sub ActiveDocment_ContentControlOnExit(ByVal ContentControl As ContentControl, Cancel As Boolean)
If (ContentControl.Type = wdContentControlDate) Then
MsgBox "Let's do it! Write the tide levels"
dateObj = ActiveDocument.SelectContentControlsByTag("tide-level")
dateObj.Range.Text = "wwwoohooo Tide Levels!"
Cancel = True
End If
End Sub
I remember reading somewhere that whenever you have content in the header, it seems things get problematic...
Any ideas?
P.S:
Currently using Word 365 - VBA
Based on the name of the procedure in the question - ActiveDocment_ContentControlOnExit - it appears the event handler was not generated automatically by Word and that it is therefore not in the ThisDocument class module of the document that contains the content controls. The name of the event handler (generated by the VBA editor) is usually Document_ContentControlOnExit.
The content control event handlers must be in ThisDocument. Theoretically, they could be typed manually, but Word doesn't always recognize manually typed event handlers. So it's better to use the VBA Editor's automatic "stub" generation to get the structures:
Open the ThisDocument module for the document that contains the content control.
In the code page window, at the top left, select "Document" from the drop-down.
from the top-right select the event to be inserted.
At this point, the VBA editor will create the "stub" for you - all that's needed is the code to be executed.
Note about the content control being in the header: This event does fire as long as focus when exiting remains in the header. If, however, the user double-clicks in the document body in order to exit the header the event doesn't fire. (At least, not in my tests.) If this is a problem you may want to put this field in the body of the document with a second, linked content control in the header to reflect the selection. Doing this is a bit complex (requires a Custom XML Part in the document to manage the linked information), but the version of Word you're using should have a tool for setting it up.
the macro name should be:
Docment_ContentControlOnExit
NOT:
ActiveDocment_ContentControlOnExit

Explanation of vba code in a word document having .docm extension

I have a Microsoft Word document with .docm format. A first glance it does not contain any macros (as when clicking the following on the ribbon; View -> Macros -> View macros pops up a window having an empty list).
But when enabling the Developer ribbon tab, and clicking the Visual Basic icon there, and then selecting the Document and ContentControlonEnter from the dropdowns in the VB window the following code appears:
Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
Dim i As Long, j As Long
With ActiveDocument
If ContentControl.Title = "Classification" Then
ContentControl.DropdownListEntries.Clear
For i = 1 To .ContentControls.Count
If Left(.ContentControls(i).Title, 5) = "Level" Then
j = j + 1
ContentControl.DropdownListEntries.Add Text:=j & " - " & .ContentControls(i).Range.Text
End If
Next
End If
End With
End Sub
Selecting the other options in the dropdowns give only "blank" code (that is they contain only function declarations followed by theEnd keyword).
My question is what is the code meant to do?
*
Details:
The Word document in question contains hyperlinks to parts of the same document and a couple of links to Word files and Excel files of the same folder. It also contains lots of content control boxes, which I'm guessing is the focus of the code (as the code contains the ContentControl keyword)
Content controls can trigger macros when the user enters and exits them. Microsoft made the design decision that all content controls should trigger the same "events" - Document_ContentControlOnEnter / Document_ContentControlOnExit - and that the code in the event needs to check which content control was entered / exited.
Content controls are considered as part of the Document because the Document can trigger events. That's why they're in (and MUST be in) the ThisDocument class module.
(Note: View Macros can only show you PUBLIC SUB procedures with no arguments that are located in "normal" code modules. Any Private Sub, any Function, anything that takes a parameter and anything in a class module will not appear in that list. So you can't use that list to determine whether a document contains any code.)
The If ContentControl.Title = "Classification" Then checks which content control was entered. (Note: it usually makes more sense to use Select Case rather than If, especially when the event needs to distinguis between multiple content controls.) What's inside the If only executes if it was a content control with the Title "Classification". (Note that more than one content control can have the same Title, so more than one content control could run the code.)
If another content control is entered, the event is still fired, but nothing happens (in this case).
Catalin Pop correctly explained that the code is, in essence, "resetting" the drop down list.
Legacy Form fields use a similar pattern - macros can fire when the user enters/exits an form field. But the design for that was you had to create a Public Sub and assign that to the form field in the Properties.
I think the logic here is quite simple.
Basically the code searches for a content control named Classification within the entire document.
After it finds it, it clears all of its drowdown entries - like a reset.
After the cleaning part it again searches through the entire document for all content control that start with word "Level" and it collect the text for those controls and their order in appearance.
With this info collected it then fills the dropdown optios for the classification control above. (e.g. 1 Level X, 2 Level Y.. - based on what it finds in the document for controls starting with Level in their name)

Building Word fields

Apart from just inserting and parsing text into a blank Word field, is there any way to programmatically build user-defined fields and field codes into my own templates with VBA? Furthermore, is there a way to make these fields show up in the list of available fields?
I recently developed a solution that used Word's MACROBUTTON and ADDIN field types.
I found MACROBUTTON useful because the third whitespace-delimited entry inside the field (programmatically field.code.text) is displayed within Word. This allows my users to watch fields as they move around. { MACROBUTTON NoMacro * } would display an "*" in Word, e.g. And it would do nothing when the user double-clicked on it, because I have purposefully not defined a macro named "NoMacro".
The ADDIN field does not display (except when display field codes is turned on) and stores a hidden string in its field.data property. Using this field I could have a hidden field the contents of which could not be seen or modified by users (excepting that if they turn on "show field codes" they can see that it is an ADDIN field (but they cannot see/edit the "data" property), and that they can delete this field just like any other field.)
I found these pages useful:
Using MacroButton fields
Using Addin Fields
What had you in mind? It is possible to add custom document properties either manually or with VBA. These are the accessible as fields under DOCPROPERTY:
{ DOCPROPERTY "Test" \* MERGEFORMAT }
You can use a macro to ensure that the custom property is added to documents:
Sub AutoNew()
Dim objCustomProperties As DocumentProperties
Set objCustomProperties = ActiveDocument.CustomDocumentProperties
objCustomProperties.Add Name:="Test", _
Type:=msoPropertyTypeString, Value:="Blah", _
LinkToContent:=False
End Sub
Further Information
Automacros: http://msdn.microsoft.com/en-us/library/aa263747(office.10).aspx
Understanding Custom Document Properties in Microsoft Office Word 2003: http://msdn.microsoft.com/en-us/library/aa537154.aspx