Solved

Change Word Field Types in Documents

Posted on 2013-12-18
15
942 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

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

In this post we will learn different types of Android Layout and some basics of an Android App.
This article will inform Clients about common and important expectations from the freelancers (Experts) who are looking at your Gig.
Six Sigma Control Plans
Introduction to Processes

689 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