I am trying to create a code that need to change a custom document property in a word document. This custom document property is the information that must be inserted in the document but sometimes need to be changed as requested. So far I have created the code for inserting the custom document property, it works fine, see below.
Sub AddCustomDocProperty()
Selection.Fields.Add _
Range:=Selection.Range, _
Type:=wdFieldEmpty, _
Text:="DOCPROPERTY ""ProjectName"" ", _
PreserveFormatting:=False
End Sub
The custom document property is named as ProjectName which will be linked with a specific field where the user will input the project name, e.g. New Screwdriver
Let's say the custom document property shows New Screwdriver and I need to change to New Screwdriver 2021.
How can I write a code that change the docproperty based on the new input given in Project name field?
I tried to find something in the forum but I did not find anything.
Thanks in advance.
A user can't easily change the value of such a field by simply typing. Whatever additional text they type will fall outside the field. Then it's difficult for you to retrieve with VBA. Consider using a content control, formfield, or even a bookmarked table cell for their input instead.
But to answer your question, this will update a custom document property:
Sub SetProp()
ActiveDocument.CustomDocumentProperties("ProjectName").value = "New Screwdriver 2021"
End Sub
Related
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)
Hopefully an easy one.
I've got a Word document littered with Checkboxes. Is there any way to access these checkboxes as a collection I can loop through and check/set properties such as ID and Value?
For reference, I've already tried the ActiveDocument.ContentControls collection; it's empty.
I've also tried ActiveDocument.Fields. This actually contains the same number of checkboxes as there are on the page, but I can't cast it to a Checkbox to access the properties I need.
One final question, is it possible to dynamically assign an event handler to the click?
Thank you in advance
The collection of all ActiveX fields embedded in your document (let's say its name is ThisDocument) is the collection ThisDocument.Fields. The items of this collection are objects of class Field.
To query the value of the objects in this collection, you'd use something along the lines of:
ThisDocument.Fields.Item(1).OLEFormat.Object.Value
To add code to the event handlers, just right-click on the ActiveX control, and then select "View Code" from the context menu. You'll get the Click event handler:
Private Sub CheckBox1_Click()
' empty if event handler not set, VBA code otherwise '
End Sub
To insert code dynamically, you need to manipulate the Code Module directly, and add the event handlers line by line. This might be tricky but, basically, you'd do something like:
ThisDocument _
.VBProject _
.VBComponents(ThisDocument.CodeName) _
.CodeModule _
.InsertLines(<<Line>>, <<String>>)
where <<Line>> is where you want to insert (number), and <<String>> is the text that you want to insert. Be careful not to insert in the middle of an existing Sub, Function or custom type definition (obviously).
I know how to use variables in Word 2010 using VBA. However, they are all reset when the document in closed and reopened.
How do I store a variable permanently in a Word document?
This can be used:
Sub Test()
ActiveDocument.Variables.Add Name:="PermanentVar", Value:=100
'ActiveDocument.Variables("PermanentVar").Delete
End Sub
Check if it is retained:
Private Sub Document_Open()
Msgbox ActiveDocument.Variables("PermanentVar")
End Sub
Ref MS kb Link
Ref SO link
Use a custom document property instead. These are stored on the Word document permanently, and can be edited and retrieved using VBA.
To create a custom property, go to File > Properties > Advanced Properties (this will be in a slightly different place in older version of Word but will still be there somewhere...).
Go to the Custom tab from the advanced properties, and fill in the name of your custom document property, the field type (you can select text, date, number or a Yes/No flag, which should cover off most options), and a starting value - you have you include a starting value or the Add button will be greyed out. Click Add.
You now have a custom property in your document, and you can use VBA to manipulate and reference it.
To change the value of your property, use the following code:
Application.ActiveDocument.CustomDocumentProperties.Item(1).Value = "Your new value..."
Item(1) is set because this is reference the first custom document property in your document. If you have more than one custom property, you'll need to change the number to reference the correct property, or write some VBA that will reference the property by name.
To pass the property to a variable, use the following code:
strYourVariable = Application.ActiveDocument.CustomDocumentProperties.Item(1).Value
I have a custom content control in Microsoft Word from a third party I am trying to resize the width and height of. Normal content control selection via VBA is not working because this control has no Title or Tag. However, if I manually select the object and resize it programmatically using "Selection.ShapeRange.Height = x" or ShapeRange.Width it does work. So to do it all programmatically I need to determine the name of the "selection" without having to manually select it.
Is there a way to "inspect" the complete reference to the currently selected object in word, so we can then get a starting point to work with it in VBA?
It's hard to know what type of object your dealing with. I tested this by inserting a blank ActiveX image control, selecting it and then running the macro. The code has two methods but one is commented out.
Sub FindName()
MsgBox (Selection.Fields.Item(1).OLEFormat.ClassType)
'MsgBox (Selection.InlineShapes.Item(1).OLEFormat.ClassType)
MsgBox (Selection.InlineShapes.Item(1).Field.Index)
MsgBox (Selection.InlineShapes.Item(1).AlternativeText)
'Show current name
MsgBox (Selection.Fields.Item(1).OLEFormat.Object.Name)
'Set new name
Selection.Fields.Item(1).OLEFormat.Object.Name = "Image5"
'Re-display name to show that it changed
MsgBox (Selection.Fields.Item(1).OLEFormat.Object.Name)
End Sub
The result was this:
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