Replace text in Word document from Excel - vba

I need to go through a row in excel table and use cell values to do replacements in Word document. I used record macro to get the code, it actually replaces the text. But when I use it from Excel Macros it doesn't work.
Dim WordApp As Object
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
Dim WordDoc As Object
Set WordDoc = WordApp.Documents.Open(doc_path_str)
Dim find_what, find_repl As String
For col_idx = params_hdr_range.Column To params_hdr_range.Column + params_hdr_range.Columns.Count - 1
find_what = CStr(scnd_sheet.Cells(params_hdr_range.Row - 1, col_idx).Value)
find_repl = CStr(scnd_sheet.Cells(model_found_range.Row, col_idx).Value)
WordApp.Selection.Find.ClearHitHighlight
WordApp.Selection.Find.ClearFormatting
WordApp.Selection.Find.Replacement.ClearFormatting
With WordApp.Selection.Find
.Text = find_what
.Replacement.Text = find_repl
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
WordApp.Selection.Find.Execute Replace:=wdReplaceAll
Next col_idx
find_what and find_repl have proper values ("{MODEL}" and "F22-2"), the same ones I used when recorded the macro, but no replacements are made. The only thing this code does it selects the text "{MODEL}" in the document. But it doesn't replace it, and though it goes through a lot of columns and other values (e.g. "{PRICE}"), nothing else happens.
How can I fix this?

Unless you add a reference to the Word object library in your Excel VBA project, Excel isn't going to know the values of Word constants such as wdReplaceAll.
You can either add the reference, declare the constants in your Excel VBA, or use the constants' values instead (which can be found in the Word VBA Object Browser)

Related

How replace word tables chr(13)?

I am working on copy and past the word tables to excel. but there are a lot of 'enter' key in word tables. could I know how to replace the the enter key in whole word tables.
I am encountering issue" wrong number of argument or invalid property assignment"
You have more than one problem with this code.
The first is that you are not setting oLookWordDoc to point to a document, so none of the Word code will work.
Second, you have two variables pointing to the same table, oLookwordTbl and r. You only need one of these.
Third, you are selecting the table to run Find instead of simply using the Find method of Table.Range.
Fourth, your find and replacement texts are incorrect.
The tidied code below will replace the paragraph marks in the table with a space.
Dim oLookWordDoc As Word.document
Dim oLookwordTbl As Word.Table
Dim iRow As Long 'row index
'you need to set oLookWordDoc to point to a document here
'Grab the word table
Set oLookwordTbl = oLookWordDoc.Tables(1)
With oLookwordTbl.Range.Find
.Text = "^p"
.Replacement.Text = " "
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With
'rows 2 - end
For iRow = 2 To oLookwordTbl.Rows.Count
oLookwordTbl.Rows(iRow).Range.Copy
'Paste
xWs.Paste
xWs.Cells(xWs.Rows.Count, 1).End(3).Offset(1).Select
Next
With Selection.find references the Excel selection object. But you want to work with the Word selection object.
Do you have a variable for the word application, e.g. appWord?
Use this: With appWord.Selection.find
If not With oLookWordDoc.parent.selection.find should work

Replace text with matching Mail Merge Field

I would like to create a macro in MS Word that when run searches the document for text that appears in the body of the document that matches the mail merge field name. Once identified it would change the text in the document to the actual matching mail merge field name. For example, if there was a mail merge field named "project_date" and in the Word document there was the text "project_date" the macro would turn the text into the actual mail merge field "project_date".
Ideally, the macro would do this for all mail merge fields that exists at once.
Below is as far as I have come with formulating my desired code.
I found this code here ( https://answers.microsoft.com/en-us/msoffice/forum/msoffice_word-mso_other-mso_2007/how-do-i-replace-words-in-a-document-with-a-mail/da323980-7c7d-e011-9b4b-68b599b31bf5 ) but it only will do one specified mail merge field at a time.
Dim oRng As Range
Set oRng = ActiveDocument.Range
With oRng.Find
Do While .Execute(FindText:="(Player 1)")
oRng.Fields.Add oRng, wdFieldMergeField, "Player_1", False
oRng.Collapse wdCollapseEnd
Loop
End With
I recorded this myself, but am not sure how to search and replace text with desired merge field.
With Selection.Find
.Text = "project_name"
.Replacement.Text = "project_name"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
The solution for this combines the code for inserting all merge fields into a document with the basic code you found / recorded. Inserting the merge field is moved into the Function that searches the field names in the document. I've set the function up to return the number of times the field is inserted.
The tricky, or special, part of the Function is setting up the Range after a successful Find to continue the search. The end-point of a merge field is still within the merge field, thus the line oRng.MoveStart wdCharacter, 2 is required after collapsing the Range. If the Range stays within the field, the merge field name inside it will be found again, and again, and again...
Sub InsertAllMergeFieldsAtPlaceholders()
Dim doc As word.Document
Dim rng As word.Range
Dim mm As word.MailMergeDataField
Set doc = ActiveDocument
Set rng = doc.content
If doc.MailMerge.MainDocumentType <> wdNotAMergeDocument Then
For Each mm In doc.MailMerge.DataSource.DataFields
Debug.Print ReplaceTextWithMergeField(mm.NAME, rng) & " merge fields inserted for " & mm.NAME
Set rng = doc.content
Next
End If
End Sub
Function ReplaceTextWithMergeField(sFieldName As String, _
ByRef oRng As word.Range) As Long
Dim iFieldCounter As Long
Dim fldMerge As word.Field
Dim bFound As Boolean
With oRng.Find
.ClearFormatting
.Forward = True
.wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
bFound = .Execute(findText:=sFieldName)
End With
Do While bFound
iFieldCounter = iFieldCounter + 1
Set fldMerge = oRng.Fields.Add(oRng, wdFieldMergeField, sFieldName, False)
Set oRng = fldMerge.result
oRng.Collapse wdCollapseEnd
oRng.MoveStart wdCharacter, 2
oRng.End = oRng.Document.content.End
bFound = oRng.Find.Execute(findText:=sFieldName)
Loop
ReplaceTextWithMergeField = iFieldCounter
End Function

Word 2016/VBA Highlight first use of each word from a word list

I am working on a macro for Word that accesses a separately saved doc file with a long word list of several pages. The word list doc is formatted like,
FMS
CPR
Abc
...to separate each word by the line break.
The macro needs to highlight the first use of each word from the list.
Right now, the macro highlights every use of the word, and in addition, highlights that word when it's part of another word. For example, it highlights EZE in the word freeze, but it should only highlight when eze stands alone.
Can someone help with how to,
1. highlight first-use only, and
2. how to make sure it's only catching the actual word, not all the other words that contain that word? I can't seem to make that happen with VBA.
My current code:
Sub TD()
'
Dim sCheckDoc As String
Dim docRef As Document
Dim docCurrent As Document
Dim wrdRef As String
Dim wrdPara As Paragraph
sCheckDoc = "c:\check.docx"
Set docCurrent = Selection.Document
Set docRef = Documents.Open(sCheckDoc)
docCurrent.Activate
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Replacement.Highlight = True
.Replacement.Text = "^&"
.Forward = True
.Format = True
.MatchWholeWord = True
.MatchCase = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
For Each wrdPara In docRef.Paragraphs
wrdRef = wrdPara.Range.Text
If Asc(Left(wrdRef, 1)) > 32 Then
' remove the paragraph mark:
wrdRef = Left(wrdRef, Len(wrdRef) - 1)
With Selection.Find
.Wrap = wdFindContinue
.Text = wrdRef
.Execute Replace:=wdReplaceAll
End With
End If
Next wrdPara
docRef.Close
docCurrent.Activate
End Sub
Try wdReplaceOne instead wdReplaceAll.
.MatchWholeWord = True should prevent highlighting embedded strings but it seems to be ignored.
I tested your original code in module behind ThisDocument and it highlighted all instances of only the last string from check document, ignoring the MatchWholeWord parameter. After the suggested edit, the code highlighted first instance of only the last string from check document. Now I can't get the procedure to work. It runs but words do not highlight. I've never used VBA behind Word. Hope this change works for you.

How to detect end of range object while searching in word document in vb.net

I have programmatically define range object in word document. Now I am trying to search perticular word in this range, but my search is going beyond the range object. how do I restrict my search within the range.
below is code snippet
WordApp.Selection.Find.Execute(<Text to find>) ' To set start of range
StartRng = WordApp.Selection.Start
With WordApp.Selection.Find
.Forward = True
.MatchCase = False
.MatchWholeWord = True
.Wrap = Word.WdFindWrap.wdFindContinue
End With
WordApp.Selection.Find.Execute(<Text to find>) ' To set end of range
EndRng = WordApp.Selection.End
WordRng = WordDoc.Range(Start:=StartRng, [End]:=EndRng)
WordRng.Select()
With WordRng.Find
.Text = "CR"
.Forward = True
.MatchCase = True
.MatchWholeWord = False
End With
WordRng.Find.Execute()
Do While WordRng.Find.Found = True
Console.WriteLine(WordRng.Text)
WordRng.Find.Execute()
CRCount += 1
Loop
this Do while loop Finds the text "CR" beyond the selected range.
The following line of code causes the issue you faced with:
.Wrap = Word.WdFindWrap.wdFindContinue
The Wrap property of the Find class returns or sets what happens if the search begins at a point other than the beginning of the document and the end of the document is reached (or vice versa if Forward is set to False) or if the search text isn't found in the specified selection or range.

VBnet MSword Automation "Replace Text"

I would like to do a replace all using VBnet 2003 and MSword 2007.
I got to this
Dim Selection As Word.Selection
Selection.Find.ClearFormatting()
Selection.Find.Replacement.ClearFormatting()
Selection.Find.Replacement.Font.Underline = Word.WdUnderline.wdUnderlineSingle
With Selection.Find
.Text = "Text"
.Replacement.Text = "Replacement"
.Forward = True
.Format = True
.Wrap = Word.WdFindWrap.wdFindContinue
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = False
End With
Selection.Find.Execute(Replace:=Word.WdReplace.wdReplaceAll)
It crashes EVERY line with the selection claiming that "Object reference not set to an instance of an object." I got the code by doing a macro recording and it worked fine as a macro but I do not want macros in my document. How do I fix this?
First you need to link to Word and the document. This code assumes Word is running with the correct document loaded and displayed.
Dim WordApplication As Word.Application = GetObject(, "Word.Application")
Dim Document As Word.Document = WordApplication.ActiveDocument
Document.Select()
Dim Selection As Word.Selection = Document.ActiveWindow.Selection
' Do your thing here.