Solved

Change Word Field Types in Documents

Posted on 2013-12-18
15
918 Views
Last Modified: 2014-01-03
Microsoft Word VBA Code /macro needed

I'd like to loop thru Word documents in a directory, open each document and change each Word field's type (WdFieldType) in each document to a "Mergefield" type.

This is what fields are in a sample doc now as an example:


Here is the macro I wrote to tell what the supposed Boookmarks really were:

Sub IdentifyFields()

Dim f As Word.Field
Dim b As Word.Bookmark

For Each f In ActiveDocument.Fields
    Debug.Print ("Field Index: " & f.Index & " Field Code: " & f.Code & " Type: " & f.Type & " Kind: " & f.Kind & " ")
Next f

End Sub
Here is the result (The only bookmark was the one I added as a test):

Field Index: 1 Field Code:  OrdClosingDate_1_14_0  Type: 3 Kind: 2
Field Index: 2 Field Code:  OrdDPSell1.1_1_0_0  Type: -1 Kind: 0
Field Index: 3 Field Code:  SellVestTxt_2_0_2  Type: 3 Kind: 2
Field Index: 4 Field Code:  GrantorAddress_1_0_0  Type: 3 Kind: 2
Field Index: 5 Field Code:  SellNameFL_23_0_2  Type: 3 Kind: 2
Field Index: 6 Field Code:  SellNameFL_26_0_2  Type: 3 Kind: 2
Field Index: 7 Field Code:  OrdDPBuy1.1_1_0_0  Type: -1 Kind: 0
Field Index: 8 Field Code:  GranteeAddress_1_0_0  Type: 3 Kind: 2
Field Index: 9 Field Code:  BuyNameFL_24_0_2  Type: 3 Kind: 2
Field Index: 10 Field Code:  BuyNameFL_29_0_2  Type: 3 Kind: 2
Field Index: 11 Field Code:  OrdSalesPrice_1_1_0  Type: 3 Kind: 2
Field Index: 12 Field Code:  OrdSalesPrice_2_0_0  Type: 3 Kind: 2
Field Index: 13 Field Code:  SellNameFL_31_0_2  Type: 3 Kind: 2
Field Index: 14 Field Code:  SellNameFL_32_0_2  Type: 3 Kind: 2
Field Index: 15 Field Code:  OrdDPBuy1.1_2_0_0  Type: -1 Kind: 0
Field Index: 16 Field Code:  OtherTenancyLang_1_0_0  Type: 3 Kind: 2
Field Index: 17 Field Code:  DoYouWantLots_1_0_0  Type: 3 Kind: 2
Field Index: 18 Field Code:  OrdPrimCntyName_3_0_0  Type: 3 Kind: 2
Field Index: 19 Field Code:  Legal_1_0_0  Type: 3 Kind: 2
Field Index: 20 Field Code:  HomesteadLanguageY/N_1_0_0  Type: -1 Kind: 0
Field Index: 21 Field Code:  HomesteadLanguageY/N_2_0_0  Type: -1 Kind: 0
Field Index: 22 Field Code:  OwnerOccLangSoleY/N_2_0_0  Type: -1 Kind: 0
Field Index: 23 Field Code:  OwnerOccLang2MoreBwrrsY/N_2_0_0  Type: -1 Kind: 0
0
Comment
Question by:swendell
  • 10
  • 5
15 Comments
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 39728262
At first glance, there seem to be a number of problems with what you are trying to do.

Firstly, a merge field needs to be of the general format

{ MERGEFIELD fieldname } where fieldname refers to a field name in a specified data source

Secondly, only Form Fields can have a bookmark to define their positions in a document, so the question is quite confusing
0
 

Author Comment

by:swendell
ID: 39728297
Here are the advanced field properties for one specific MERGEFIELD field code I wish to convert TO:
MERGEFIELD  RESWARE_SP_GetBuyerSellerCityStateZip_Buyer_1

Above you can see the debug.print of some fields and their .FieldTypes I am converting FROM.

So for the first one; I would like the field changed to be:
MERGEFIELD OrdClosingDate_1_14_0
It will work if I change the type to MERGEFIELD, a 3ed party module interprets and replaces these Word MergeFields.

Maybe cut the current Word Field while saving Word.Field.code then .add a new MergeField in the position with the saved Word.Field.code ?
0
 

Author Comment

by:swendell
ID: 39730368
One step closer,
This code successfully found and replaced the first field with a mergefield
Unfortunately it did not move onto the next field in the loop to continue replacing the remaining fields in the document, but a great start

Dim f As Word.Field
Dim MyRange As Object

For Each f In ActiveDocument.Fields
     Debug.Print ("Field Index: " & f.Index & " Field Code: " & f.Code & " Type: " & f.Type & " Kind: " & f.Kind & " ")
     
f.Select

Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
        "MERGEFIELD OrdClosingDate_1_14_0", PreserveFormatting:=False
Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend

Next f

End Sub
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 76

Expert Comment

by:GrahamSkan
ID: 39730395
Sorry. I thought that I posted some code last night. The way round that problem  is to use indexing instead of For Each. Modifying the field modifies the Fields collection, so the Next doesn't work. This is what I wrote last night:
Sub ChangeToMergeFields()
    Dim fld As Field
    Dim rng As Range
    Dim strWords() As String
    Dim strText As String
    
    Dim w As Integer
    Dim f As Integer
    
    For f = 1 To ActiveDocument.Fields.Count
        Set fld.Kind = ActiveDocument.Fields(f)
        Set rng = fld.Code
        strText = rng.Text
        strWords = Split(strText, " ")
        For w = 0 To UBound(strWords)
            If Len(Trim(strWords(w))) > 0 Then
                strWords(w) = "MERGEFIELD"
                Exit For
            End If
        Next w
        strText = Join(strWords, " ")
        fld.Delete
        ActiveDocument.Fields.Add rng, wdFieldEmpty, strText
    Next f
End Sub

Open in new window

0
 

Author Comment

by:swendell
ID: 39730465
Error: Invalid use of property - KIND
Set fld.Kind = ActiveDocument.Fields(f)
0
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 39730490
Yes that is not surprising.

I have no idea where that came from. The code worked 24 hours ago. It is trying to set a field property to the field object itself.

It should be:
Set fld = ActiveDocument.Fields(f)
0
 

Author Comment

by:swendell
ID: 39730585
It is inserting Mergefields without a field name where the old fields were. That is GREAT; Now we need to save the old field name then use it when adding this new MERGEFIELD so the MERGEFIELD name will not be empty  

It should look like: {MERGEFIELD OrdClosingDate_1_14_0}
Now it looks empty like this:  { MERGEFIELD \* MERGEFORMAT}
0
 

Author Comment

by:swendell
ID: 39730600
Maybe I should have attached this to begin with....
FM000391.doc
0
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 39730769
That certainly helps.

None of the fields in your document have a field type name in them. This makes them, by default, REF fields. REF fields display the text of the given bookmark name (the first word in the field, or the second if it us "REF").

When I said 'last night',  it was really so. I'm on GMT, so it's nearly midnight here. I'll try to get back in about eight hours' time
0
 

Author Comment

by:swendell
ID: 39731766
Thank you so much!!!!!!!!!!!
I was able to get the field name/code in my originally posted example so I guess you know what to do. The last piece is a loop that will:
- loop thru a directory of the docs to be converted. For example: C:\Input
- save each converted document with same name to a folder like C:\Output
0
 
LVL 76

Accepted Solution

by:
GrahamSkan earned 500 total points
ID: 39731819
Here is some code to loop through a folder and to save the modified document.
Some tweaks were necessary to the original procedure, so that is also here.
Sub ProcessFiles()
    Dim strFile As String
    Dim strInFolder As String
    Dim strOutFolder As String
    Dim doc As Document
    
    strInFolder = "C:\Input"
    strOutFolder = "C:\Output"
    
    strFile = Dir$(strInFolder & "\*.doc*")
    Do Until strFile = ""
        Set doc = Documents.Open(strInFolder & "\" & strFile)
        ChangeToMergeFields doc
        doc.SaveAs strFile & "\" & strOutFolder
        doc.Close
        strFile = Dir$()
    Loop
End Sub


Sub ChangeToMergeFields(doc As Document)
    Dim fld As Field
    Dim rng As Range
    Dim strWords() As String
    Dim strText As String
    
    Dim w As Integer
    Dim f As Integer
    
    For f = 1 To doc.Fields.Count
        Set fld = doc.Fields(f)
        Set rng = fld.Code
        strText = rng.Text
        strWords = Split(strText, " ")
        For w = 0 To UBound(strWords)
            If Len(Trim(strWords(w))) > 0 Then
                strWords(w) = "MERGEFIELD"
                Exit For
            End If
        Next w
        strText = Join(strWords, " ")
        fld.Delete
        doc.Fields.Add rng, wdFieldEmpty, strText
    Next f
End Sub

Open in new window

0
 

Author Comment

by:swendell
ID: 39731907
I am driving for the next day or two but will test it when I stop, thank you so much for all the help, I'd like to send you a gift of appreciation like an amazon gift card not just points,  just don't know where to send it...
0
 

Author Comment

by:swendell
ID: 39735966
Just at a glance I reversed the output file path but I do not think the new Mergefields have any field names...
0
 

Author Comment

by:swendell
ID: 39735969
OK , I fixed the output path and added Mergefield name, It 'seems' OK, but I will need to test to confirm:

Sub ProcessFiles()
    Dim strFile As String
    Dim strInFolder As String
    Dim strOutFolder As String
    Dim doc As Document
    
    strInFolder = "C:\AIMInput"
    strOutFolder = "C:\AIMOutput"
    
    strFile = Dir$(strInFolder & "\*.doc*")
    Do Until strFile = ""
        Set doc = Documents.Open(strInFolder & "\" & strFile)
        ChangeToMergeFields doc
        doc.SaveAs strOutFolder & "\" & strFile
        doc.Close
        strFile = Dir$()
    Loop
End Sub


Sub ChangeToMergeFields(doc As Document)
    Dim fld As Field
    Dim fldsave As String ' this is the field to store te old field name before we replce it
    
    Dim rng As Range
    Dim strWords() As String
    Dim strText As String
    
    Dim w As Integer
    Dim f As Integer
    
    For f = 1 To doc.Fields.Count
        Set fld = doc.Fields(f)
        Set rng = fld.Code
        fldsave = rng.Text
        strText = rng.Text
        strWords = Split(strText, " ")
        For w = 0 To UBound(strWords)
            If Len(Trim(strWords(w))) > 0 Then
                strWords(w) = "MERGEFIELD" & " " & fldsave ' added missing Mergefield name
                Exit For
            End If
        Next w
        strText = Join(strWords, " ")
        fld.Delete
        doc.Fields.Add rng, wdFieldEmpty, strText
    Next f
End Sub

Open in new window

0
 

Author Closing Comment

by:swendell
ID: 39755147
Sorry I took so long to test over the holiday but you got the essence of it very well
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you’re thinking to yourself “That description sounds a lot like two people doing the work that one could accomplish,” you’re not alone.
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question