![]() |
|
|||||||
|
|
|
Thread Tools | Display Modes |
|
|
|
#1
|
|||
|
|||
|
I have many documents (Word templates - .dotx) that have various merge fields in them. Some are just regular merge fields while others may be IF fields or DATE fields.
While most of the fields are on their own line, some also have text before or after the field or are within paragraphs in some documents. I would like create a routine that will open each file in a particular folder and search for those particular fields and will replace the fields with text only. That is, the fields are no longer needed. I have tried creating the routine (using code from the internet - including from GMayor! - plus my own edits), using lists of search and replace terms, but seem to be getting stuck with the find and replace part of it. Specifically, I am not finding the fields that are not straightforward merge fields (ie; the DATE and IF fields). I suspect I am using the wrong approach (although I have tried several!) and would appreciate and assistance pointing me in the right direction. (My efforts are below) EDIT: A solution I thought may work (but I haven't been able to get working) was to unlink all mergefields, turning them to regular text and then searching for the relevant phrases with the double brackets that remain.. Would this be possible? Examples of things I am trying to search and replace for include: {IF TRUE {DATE \@ "d MMM yyyy" }, { MERGEFIELD COMPANY_NAME}, { MERGEFIELD ACN}, etc. Thanks in advance for any help. Code:
Sub SearchAndReplace()
Dim oWordApp As Object, oWordDoc As Object, rngStory As Object
Dim sFolder As String, strFilePattern As String
Dim strFileName As String, sFileName As String
Dim strFind, strRep, strSearchList, strRepList As String
Dim i, x As Long
Dim lngValidate As Long
Dim oShp As Shape
'Application.ScreenUpdating = False
strSearchList = "DATE \@, MERGEFIELD Company Name,(IN LIQUIDATION),MERGEFIELD ACN,MERGEFIELD Trading_Name,MERGEFIELD Trust"
strRepList = "[RF_TODAY_LONG],[RF_ADMIN_FULL_NAME],[RF_ADMIN_APPT_SUFFIX],[RF_JOBINFO_A.C.N.],[RF_JOBINFO_FORMERLY_TRADING_AS],[RF_JOBINFO_ TRUST_NAME],[RF_JOBINFO_A.B.N.]"
'Use to select folder
'sFolder = GetFolder & "\"
'~~> Change this to the folder which has the files (or comment and use GetFolder)
sFolder = "S:\TEMPLATES\APL Precedents\CVL\"
'~~> This is the file extension you want to loop through
strFilePattern = "*.dotx"
'~~> Establish an Word application object
On Error Resume Next
Set oWordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set oWordApp = CreateObject("Word.Application")
End If
Err.Clear
On Error GoTo 0
oWordApp.Visible = True
'~~> Loop through the folder to get the word files
strFileName = Dir$(sFolder & strFilePattern)
Do Until strFileName = ""
sFileName = sFolder & strFileName
'~~> Open the word doc
Set oWordDoc = oWordApp.Documents.Open(sFileName)
oWordDoc.ActiveWindow.View.ShowFieldCodes = True
'Convert merge fileds to text
'oWordDoc.Fields.Unlink
'Fix the skipped blank Header/Footer problem.
lngValidate = oWordDoc.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document.
For Each rngStory In oWordDoc.StoryRanges
'~~> Iterate through all linked stories. Do Find and Replace.
Do
For i = 0 To UBound(Split(strSearchList, ","))
strFind = Split(strSearchList, ",")(i)
strRep = Split(strRepList, ",")(i)
ReplaceFields rngStory, strFind, strRep
SearchAndReplaceInStory rngStory, strFind, strRep
Next
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
For x = 0 To UBound(Split(strSearchList, ","))
strFind = Split(strSearchList, ",")(x)
strRep = Split(strRepList, ",")(x)
ReplaceFields rngStory, strFind, strRep
SearchAndReplaceInStory oShp.TextFrame.TextRange, strFind, strRep
Next
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
'~~> Close the file after saving
oWordDoc.Close SaveChanges:=True
'~~> Find next file
strFileName = Dir$()
Loop
'Application.ScreenUpdating = true
'~~> Quit and clean up
oWordApp.Quit
Set oWordDoc = Nothing
Set oWordApp = Nothing
End Sub
Sub SearchAndReplaceInStory(ByVal rngStory As Word.Range, ByVal strSearch As String, ByVal strReplace As String)
rngStory.TextRetrievalMode.IncludeFieldCodes = True
rngStory.TextRetrievalMode.IncludeHiddenText = True
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Text = strSearch
.Replacement.Text = strReplace
.Execute Replace:=wdReplaceAll
End With
lbl_Exit:
Exit Sub
End Sub
Sub ReplaceFields(ByVal rngStory As Word.Range, ByVal strSearch As String, ByVal strReplace As String)
'Graham Mayor - http://www.gmayor.com - Last updated - 25 Sep 2018
'Modified by me
Dim oFld As Field
For Each oFld In rngStory.Fields
If oFld.Type = wdFieldMergeField Or oFld.Type = wdFieldDate Or oFld.Type = wdFieldIf Then
If InStr(1, oFld.Code, strSearch) > 0 Then
oFld.Code.Text = Replace(oFld.Code.Text, strSearch, strReplace)
oFld.Update
oFld.Unlink
End If
End If
Next oFld
lbl_Exit:
Set oFld = Nothing
Exit Sub
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
Last edited by Jakster; 03-16-2025 at 05:53 PM. |
|
#2
|
|||
|
|||
|
Just an update.... I think I may have found a way to make it work... I have used the following code (again, found online and modified) which seems to done the trick.
Code:
Sub ReplaceFields(ByVal rngStory As Word.Range, ByVal strSearch As String, ByVal strReplace As String)
Dim oFld As Field
Dim oRng As Range
For Each oFld In ActiveDocument.Fields
Set oRng = oFld.Code
If InStr(1, oRng.Text, strSearch) > 0 Then
oRng.MoveStart wdCharacter, -1
oRng.Collapse
oRng.InsertAfter strReplace
oFld.Delete
End If
Next oFld
lbl_Exit:
Set oFld = Nothing
Set oRng = Nothing
Exit Sub
End Sub
Last edited by Jakster; 03-16-2025 at 06:02 PM. |
|
#3
|
||||
|
||||
|
Surely the simplest way would be to connect the documents to a data source containing all the required fields and, for each field, a record with whatever ouput text you want, then merge to a new document.
Still, if you're wedded to a VBA approach, you might find the macro titled Create Text Representations of Working Fields in the Mailmerge Tips & Tricks 'Sticky' thread at the top of the Mailmerge forum helpful. That code converts field codes to text representations of their content. See: https://www.msofficeforums.com/mail-...ps-tricks.html PS: For mailmerges, you should be using mailmerge main documents, not templates.
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#4
|
|||
|
|||
|
Hi Paul,
Thanks so much for your reply and for the info.. Your idea regarding merging the documents is a very sensible one!! It would work for most fields however, I think it would fail for fields that didn't accept plain text (ie: date fields or fields formatted for numbers). It would probably be more time consuming as there are hundreds of documents I would need to merge and save. Also, I note your point regarding mailmerges - however I need the files for a particular application which uses templates... we therefore are moving from mailmerges using documents with fields to templates that use simple codes within square brackets. Therefore, my need to convert the field codes to text and the documents to templates. In any event, I think I am there now but thank you again for your assistance. |
|
#5
|
||||
|
||||
|
I can't see why merging shouldn't work for mergefields outputting dates or formatted numbers. At most, if the fields are remaining in the documents post-merge, your commented-out line of code:
oWordDoc.Fields.Unlink is all that's needed (the equivalent of Ctrl-A, Ctrl-Shift-F9). Indeed, you can even do that without doing any merging. Either way, having converted all your fields to plain text, replacing the text results with your "simple codes within square brackets" should be a breeze.
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
| Tags |
| mailmerge, ms-word, vba |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
Plain text help with returns - looking for marker to use when converting to plain text
|
redzan | Word | 1 | 04-18-2017 06:17 PM |
| Macro to keep formatted form fields after mail merge or replace text with formatted form fields | jer85 | Word VBA | 2 | 04-05-2015 10:00 PM |
| Searhc for Hyperlinked Word and replace with plain text or nothing | somniloquist | Word | 3 | 10-04-2011 02:33 AM |
Replace all occurrences of one merge field with plain text
|
blankenthorst | Mail Merge | 5 | 07-01-2011 05:18 AM |
| Replace All with plain text containing subscript | DeaducK | Word | 0 | 06-24-2010 08:16 PM |