Search code examples
ms-wordtags

How to add readable tags in MS Word document?


So, there is this service called 'vphrase' that reads a word document for tags and replaces it with data from database. Suppose there's a report for customers and the report contains a tag <customerName>. You give the respective customer id while uploading the report and vphrase will replace the tag with the customer name that's linked to the provided customer id. Problem is, it doesn't detect the tags properly. It reads <> and the name inside it separately. Typing the tag in bold, underline and italics doesn't work. So, is there a way to add tags so that vphrase can read it?


Solution

  • Word has document properties that can be accessed using vba. Those can be reflected in the document text using DOCPROPERTY fields. Word documents also can have stored variables that are then shown in the document using DOCVARIABLE fields in the body.

    You could also include XML nodes in a document attached to Content Controls in the document. These are called Mapped Content Controls.

    How to use a single VBA procedure to read or write both custom and built-in Document Properties

    Article contributed by Astrid Zeelenberg The vba shown is also quoted.

    When you work with Document Properties in code, most people end up with two functions or subroutines, one to write built-in Document Properties and one for custom Document Properties; because in each case the object used to refer to the Document Properties is different – you have to use the CustomDocumentProperties and BuiltinDocumentProperties collection as appropriate. But this can be very inconvenient. Writing Document Properties

    However, you can write a procedure which checks whether the property you want to write the value for is custom or built-in, and then uses the appropriate collection. (Note: If you are not familiar with calling subroutines with arguments, see: How to cut out repetition and write much less code, by using subroutines and functions that take arguments).

    This is how to do it:

    Public Sub WriteProp(sPropName As String, sValue As String, _
          Optional lType As Long = msoPropertyTypeString)
    
    'In the above declaration, "Optional lType As Long = msoPropertyTypeString" means 'that if the Document Property's Type is Text, we don't need to include the lType argument 'when we call the procedure; but if it's any other Prpperty Type (e.g. date) then we do
    
    Dim bCustom As Boolean
    
      On Error GoTo ErrHandlerWriteProp
    
      'Try to write the value sValue to the custom documentproperties   'If the customdocumentproperty does not exists, an error will occur   'and the code in the errorhandler will run   ActiveDocument.BuiltInDocumentProperties(sPropName).Value = sValue   'Quit this routine   Exit Sub
    
    Proceed:   'We know now that the property is not a builtin documentproperty,   'but a custom documentproperty, so bCustom = True  bCustom = True
    
    Custom:   'Try to set the value for the customproperty sPropName to sValue   'An error will occur if the documentproperty doesn't exist yet   'and the code in the errorhandler will take over   ActiveDocument.CustomDocumentProperties(sPropName).Value = sValue   Exit Sub
    
    AddProp:   'We came here from the errorhandler, so know we know that   'property sPropName is not a built-in property and that there's   'no custom property with this name   'Add it   On Error Resume Next   ActiveDocument.CustomDocumentProperties.Add Name:=sPropName, _
        LinkToContent:=False, Type:=lType, Value:=sValue
    
      If Err Then
        'If we still get an error, the value isn't valid for the Property Type
        'e,g an invalid date was used
        Debug.Print "The Property " & Chr(34) & _
         sPropName & Chr(34) & " couldn't be written, because " & _
         Chr(34) & sValue & Chr(34) & _
         " is not a valid value for the property type"   End If
    
      Exit Sub
    
    ErrHandlerWriteProp:   Select Case Err
        Case Else    'Clear the error    Err.Clear    'bCustom is a boolean variable, if the code jumps to this    'errorhandler for the first time, the value for bCustom is False    If Not bCustom Then
         'Continue with the code after the label Proceed
         Resume Proceed    Else
         'The errorhandler was executed before because the value for
         'the variable bCustom is True, therefor we know that the
         'customdocumentproperty did not exist yet, jump to AddProp,
         'where the property will be made
         Resume AddProp    End If   End Select
    
    End Sub
    

    We could call the above procedure like this:

    Sub Test()   'Author is a built-in property
      Call WriteProp(sPropName:="Author", sValue:="William Shakespeare")
    
      'Date Updated is a custom document property
      Call WriteProp(sPropName:="Date Updated", sValue:="11 Mar 2001", _
        lType:=msoPropertyTypeDate)
    End Sub 
    

    Reading Document Properties

    The same principle can be used when reading Document Properties:

    Function ReadProp(sPropName As String) As Variant
    
      Dim bCustom As Boolean Dim sValue As String
    
      On Error GoTo ErrHandlerReadProp
     'Try the built-in properties first
     'An error will occur if the property doesn't exist
     sValue = ActiveDocument.BuiltInDocumentProperties(sPropName).Value
     ReadProp = sValue
     Exit Function
    
    ContinueCustom:
     bCustom = True
    
    Custom:
     sValue = ActiveDocument.CustomDocumentProperties(sPropName).Value 
     ReadProp = sValue   Exit Function
    
    ErrHandlerReadProp:
     Err.Clear
    'The boolean bCustom has the value False, if this is the first
    'time that the errorhandler is runned
    If Not bCustom Then
        'Continue to see if the property is a custom documentproperty
        Resume ContinueCustom
    Else
        'The property wasn't found, return an empty string
        ReadProp = ""
        Exit Function
     End If
    
    End Function
    

    We could call the function like this:

    Sub Test()
        Dim PropVal As String
        PropVal = ReadProp("Author")
        Debug.Print PropVal
        PropVal = ReadProp("Date Completed")
        Debug.Print PropVal
    End Sub
    

    TIP: The Word add-ins DocTools DocPropertyManager lets you copy custom document properties from one document to another. You can select whether to also include the built-in properties in the copy.