My goal is to be able to run this script and have the document search for and highlight a set number of terms, typically 10+ terms. I figured out how to do this with another script I found here, but every time I use it Word crashes.
Below is a simpler version I have pieced together from different forums/videos I found online. It does exactly what I want it to do except I can't figure out how to make it look for more than one term.
The .Text = "Text" works great but only for one term. If I list multiple then it only looks for the one I listed last. I have tested other chunks of code I found online but I can't figure it out.
I am hoping it is a simple fix, especially since the rest of the code does what I want. TIA!
Sub UsingTheFindObject_Medium()
'Declare Variables.
Dim wrdFind As Find
Dim wrdRng As range
Dim wrdDoc As Document
'Grab the ActiveDocument.
Set wrdDoc = Application.ActiveDocument
'Define the Content in the document
Set wrdRng = wrdDoc.Content
'Define the Find Object based on the Range.
Set wrdFind = wrdRng.Find
'Define the parameters of the Search.
With wrdFind
'Search the text for the following term(s)
.Text="Test"
.Format = True
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Do While wrdFind.Execute = True
'Change the color to Yellow.
wrdRng.HighlightColorIndex = wdYellow
Loop
End Sub
This will do what you want.
Sub HighlightMultipleWords()
Dim sArr() As String
Dim rTmp As Range
Dim x As Long
sArr = Split("highlight specific words") ' your list
Options.DefaultHighlightColorIndex = wdYellow
For x = 0 To UBound(sArr)
Set rTmp = ActiveDocument.Range
With rTmp.Find
.Text = sArr(x)
.Replacement.Text = sArr(x)
.Replacement.Highlight = True
.Execute Replace:=wdReplaceAll
End With
Next
End Sub
Before:
After:
Use your current routine as a function.
Here is an example.
Function FindAndMark(sText As String) ' UsingTheFindObject_Medium()
' https://stackoverflow.com/questions/69633517/how-do-i-search-and-highlight-multiple-terms-in-microsoft-word
' Charles Kenyon
'Declare Variables.
Dim wrdFind As Find
Dim wrdRng As Range
Dim wrdDoc As Document
'Grab the ActiveDocument.
Set wrdDoc = Application.ActiveDocument
'Define the Content in the document
Set wrdRng = wrdDoc.Content
'Define the Find Object based on the Range.
Set wrdFind = wrdRng.Find
'Define the parameters of the Search.
With wrdFind
'Search the text for the following term(s)
.Text = sText
.Format = True
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
' Mark text
Do While wrdFind.Execute = True
'Change the color to Yellow.
wrdRng.HighlightColorIndex = wdYellow
Loop
Set wrdFind = Nothing
Set wrdRng = Nothing
Set wrdDoc = Nothing
End Function
Sub MultiFindMark()
' https://stackoverflow.com/questions/69633517/how-do-i-search-and-highlight-multiple-terms-in-microsoft-word
' Charles Kenyon
Dim i As Integer
Const n As Integer = 4 ' set number (n) of terms in search
Dim sArray(n) As String ' Create array to hold terms
' Assign values, starting at 0 and going to n-1
Let sArray(0) = "Aenean"
Let sArray(1) = "Pellentesque"
Let sArray(2) = "libero"
Let sArray(3) = "pharetra"
For i = 0 To n - 1
FindAndMark (sArray(i))
Next i
End Sub
Here is a revision using the code from ASH to handle the Array
Sub MultiFindMark2()
' https://stackoverflow.com/questions/69633517/how-do-i-search-and-highlight-multiple-terms-in-microsoft-word
' Charles Kenyon
' modified to use methods proposed by ASH
Dim i As Long
Dim sArray() As String ' Create array to hold terms
' Assign values, starting at 0 and going to n-1
sArray = Split("Aenean Pellentesque libero pharetra") ' your list separated by spaces
For i = 0 To UBound(sArray)
FindAndMark (sArray(i))
Next i
End Sub
With some of the changes showing as comments:
Sub MultiFindMark2()
' https://stackoverflow.com/questions/69633517/how-do-i-search-and-highlight-multiple-terms-in-microsoft-word
' Charles Kenyon
' modified to use methods proposed by ASH
Dim i As Long
' Const n As Integer = 4 ' set number (n) of terms in search
Dim sArray() As String ' Create array to hold terms
' Assign values, starting at 0 and going to n-1
sArray = Split("Aenean Pellentesque libero pharetra") ' your list separated by spaces
' Let sArray(0) = "Aenean"
' Let sArray(1) = "Pellentesque"
' Let sArray(2) = "libero"
' Let sArray(3) = "pharetra"
For i = 0 To UBound(sArray)
FindAndMark (sArray(i))
Next i
End Sub
Note, this still requires the function.
Related
I have the code helps me find multiple texts. I want to do the following thing but i get stucked:
Select the entire row of found item
Copy the selected row to new table
Thanks
Sub FindMultiItemsInDoc()
Dim objListDoc As Document
Dim objTargetDoc As Document
Dim objParaRange As Range, objFoundRange As Range
Dim objParagraph As Paragraph
Dim strFileName As String
strFileName = InputBox("Enter the full name of the list document here:")
Set objTargetDoc = ActiveDocument
Set objListDoc = Documents.Open(strFileName)
objTargetDoc.Activate
For Each objParagraph In objListDoc.Paragraphs
Set objParaRange = objParagraph.Range
objParaRange.End = objParaRange.End - 1
With Selection
.HomeKey Unit:=wdStory
' Find target items.
With Selection.Find
.ClearFormatting
.Text = objParaRange
.MatchWholeWord = True
.MatchCase = False
.Execute
End With
Next objParagraph
End Sub
I am trying to create a macro that finds all text formulas and replaces it with OMath formulas.
I create a text, where all formulas are surrounded with special tags (in my case its word "formula"). Then I find all cases with regex and create variable that contains found formula. Then I give this variable to find method to create range, which I then modify.
Some formulas contain special characters (in my case its caret (^), which is used to create power) and find method doesn't select them.
How can I ignore special characters in variable that I give to find method?
Macro that I created:
Dim regexObject As Object
Set regexObject = CreateObject("VBScript.RegExp")
Dim matches As Object
Dim objEq As OMath
Dim objRange As Range
Dim match As Object
regexObject.Pattern = "formula(.*?)formula"
regexObject.MultiLine = True
Selection.WholeStory
While regexObject.test(Selection.Text)
Set matches = regexObject.Execute(Selection.Text)
For Each match In matches
MsgBox match
With Selection.Find
.Text = match
.MatchWildcards = False
.Execute
Set objRange = Selection.Range
objRange.Text = Mid(match, 8, Len(match) - 14)
Set objRange = Selection.OMaths.Add(objRange)
Set objEq = objRange.OMaths(1)
objEq.BuildUp
End With
Selection.WholeStory
Next
Wend
Sample Text:
formulaΨ=1,67∙0,72∙0,9∙1=1,09.formula
formulac_c=0,9formula
formulaE_q=Ψ WV_n^2/2,formula
formulac_m, c_e, c_c, c_sformula
For example:
Sub FindFormulaeCreateOMath()
Dim objEq As OMath
Dim findRange As Range
Dim eqRange As Range
Set findRange = ActiveDocument.Content
With findRange
With .Find
.Text = "formula*formula"
.MatchWildcards = True
End With
Do While .Find.Execute
.Text = Mid(.Text, 8, Len(.Text) - 14)
Set eqRange = findRange.OMaths.Add(.Duplicate)
Set objEq = eqRange.OMaths(1)
objEq.BuildUp
.Collapse wdCollapseEnd
Loop
End With
End Sub
I am creating a macro to search word documents for exact matches against acronyms in an Excel file. If the acronym is in the Word file, the macro highlights the acronym and inserts the row number into an array for use in a to-be-written macro to generate a Table of Acronyms.
The below macro works, however there are several false positives whenever I run it. This occurs when certain acronyms contain special characters, notably "&", "/" and "-".
For example, if I run the below macro on a file that contains RT&E, the code will insert the row number for "RT and "RT&E" and "T&E" into the array (provided all three are in the first column in the excel file).
This is not a problem on small documents, but for 150 page documents, it's just too much. I also apologize for the bad code. Suggestions to make it better are appreciated.
Dim rng As range
Dim i As Long
Dim acro As String
Dim acrolist As Excel.Application
Dim acrobook As Excel.Workbook
Dim acromatch() As Variant
ReDim acromatch(0 To 1)
Set acrolist = New Excel.Application
Set acrobook = acrolist.Workbooks.Open("P:\AcronymMacro\MasterAcronymList.xlsm")
' Count from first row with acronym to maximum # of rows
' That way, list can be as long or short as needed
For i = 3 To 1048576
Set rng = ActiveDocument.range
acro = acrobook.Sheets(1).Cells(i + 1, 1)
' Loop breaks when it finds an empty cell
' i.e. the last acronym in the document.
If acro = "" Then Exit For
' Find and Replace code
With rng.Find
.Text = acro
.Format = True
.MatchCase = True
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
' Do While loop
Do While .Execute(Forward:=True) = True
rng.HighlightColorIndex = wdPink
Call InsertIntoArray(acromatch(), i + 1)
Loop
End With
Next
MsgBox Join(acromatch(), ",")
'Make sure you close your files, ladies and gentlemen!
acrobook.Close False
Set acrolist = Nothing
Set acrobook = Nothing
' This function resizes array and insert value as last value
Public Function InsertIntoArray(InputArray As Variant, Value As Variant)
ReDim Preserve InputArray(LBound(InputArray) To UBound(InputArray) + 1)
InputArray(UBound(InputArray)) = Value
End Function
One thing I tried was to run another Range.Find method in the Do While Loop, with a slight change to the acronym. For instance the below code makes sure there is a space, period, or close parentheses and not an ampersand and hyphen after the acronym. If it is different, then it doesn't get added.
Do While .Execute(Forward:=True) = True
rng.HighlightColorIndex = wdPink
acro = acro + "[ .)]"
With rng.Find
.Text = acro
.MatchWildCards = True
If rng.Find.Execute(Forward=True) = True Then Call InsertIntoArray(acromatch(), i + 1)
End With
Loop
This code, however, makes sure nothing gets into the array.
How to I present false positives when acronyms have special characters in acronyms?
here is a rewrite of your code
it puts the data from excel into an array, then the array is searched
no correction made for the problem with special characters
Sub acroTest()
Dim acromatch() As Variant
ReDim acromatch(0 To 1)
Dim acrolist As Excel.Application
Set acrolist = New Excel.Application
Dim acrobook As Excel.Workbook
Set acrobook = acrolist.Workbooks.Open("P:\AcronymMacro\MasterAcronymList.xlsm")
Dim rng As Range ' msWord range
Set rng = ActiveDocument.Range
With rng.Find ' set up find command
.Format = True ' these are "remembered" until changed
.MatchCase = True ' same as the "find" dialog box
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
' Count from first row with acronym to maximum # of rows
' That way, list can be as long or short as needed
' could loop excel range this way
' constant xlCellTypeConstants = 2
' Dim acro As Excel.Range
' For Each acro In acrobook.Sheets(1).Range("a3:a1048576").SpecialCells(xlCellTypeConstants) ' all non-blank, non-formula cells
Dim acro As Excel.Range
Set acro = acrolist.Range(acrobook.Sheets(1).Range("A3"), acrobook.Sheets(1).Cells(1048576, "A").End(xlUp)) ' range A3 to last used cell in A column
Dim wordsInExcel As Variant ' column A gets put into an array for faster execution
wordsInExcel = acro.Value ' convert excel range to 2d array (1 x N)
wordsInExcel = acrolist.Transpose(wordsInExcel) ' convert result to 2d array (N x 1)
wordsInExcel = acrolist.Transpose(wordsInExcel) ' convert again to get 1d array
Dim i As Long
For i = 1 To UBound(wordsInExcel)
rng.Find.Text = wordsInExcel(i) ' this is "search text"
Do While rng.Find.Execute(Forward:=True) = True ' do the actual search
rng.HighlightColorIndex = wdPink
Call InsertIntoArray(acromatch(), i + 1)
Loop
Next
MsgBox Join(acromatch(), ",")
' Make sure you close your files, ladies and gentlemen!
acrobook.Close False
Set acrolist = Nothing
Set acrobook = Nothing
End Sub
' This function resizes array and insert value as last value
Public Function InsertIntoArray(InputArray As Variant, Value As Variant)
ReDim Preserve InputArray(LBound(InputArray) To UBound(InputArray) + 1)
InputArray(UBound(InputArray)) = Value
End Function
I have a macro in Word that searches a document, and then does things when found.
I would like to check if the Found text is in a table of contents, but it doesn't seem to be liking how I have the code:
Sub test()
Dim myDoc As Word.Document
Dim oRng As Word.Range, rng As Word.Range, rngXE As Word.Range
Dim addDefinition$, editedDefinition$ ',findText$
Dim rngEdited
Dim bFound As Boolean
Dim findText() As Variant
Dim y&
Set myDoc = ActiveDocument
bFound = True
Call Clear_Index
findText = Array("whatever", "whatever:", "Whatever:")
For y = LBound(findText) To UBound(findText)
'Loop through the document
Set oRng = myDoc.Content
Set rngXE = oRng.Duplicate
With oRng.Find
.ClearFormatting
.ClearAllFuzzyOptions
.Text = findText(y)
.MatchCase = False
.Wrap = wdFindStop
End With 'orng.find
Do While bFound
bFound = oRng.Find.Execute
If bFound Then
Set rngXE = oRng.Paragraphs(1).Range.Duplicate
rngXE.Select
'
' THIS IS WHERE I NEED HELP :(
If rngXE.Fields.Type = wdFieldTOC Then ' This doesn't work.
MsgBox (" In a TOC!")
End If
End If
End Sub
It throws
Compile Error: Method or data member not found
I've seen loops of
For each fld in myDoc.Fields
If fld.Type = wbFieldTOC Then
'Do something
end if
next fld
Which work - I'm just having a hard time understanding to find specific text's field.
The InRange method is useful for discovering if one range is located within another range. Since there is a TableOfContents collection for the Document object, it's simple enough to get that range and test whether some other ange (even Selection.Range) is within it.
The following snippet assumes the document has a TOC and that you're interested in the first TOC. If your situation is otherwise, you need to do some checking to make sure the reference is to the correct TOC:
oRng.InRange(ActiveDocument.TablesOfContents(1).Range)
I'm entirely new to VBA. I need to write a macro to do as the following pseudo code describes. Any references to VBA code are from looking at examples I've found so far from googling. Many thanks for any guidance you can offer.
Dim myText as string;
Dim myAutoTextFieldValue as string;
Set myText='Figure';
Set myAutoTextFieldValue = 'fignum';
// fignum is a autotext value that will insert a sequence type field
.Find text which matches this Word expression \[[0-9]*[0-9]*[0-9]\]
// this expression works in the Find what function in Word, not strictly regex
For each
.InsertBefore (myText + myTextAutoFieldValue);
// I'm guessing I'll need a With expression and a Do While.
EDIT:
I now have the following but I get "Method or Data Member not found" when I try to run it.
Sub EditFindLoop()
'find text where the string equals [00:00:00] or numeric sequence as per input mask
'then insert myText and myAutoTextFieldValue before it
Dim myText As String
Dim myAutoTextFieldValue As String
Dim myFind As String
myFind = "\[[0-9]*[0-9]*[0-9]\]"
myAutoTextFieldValue = "fignum"
myText = "Figure"
With ActiveDocument.Content.Find
'.Text = myFind
'.ClearFormatting
.MatchWildcards = True
Do While .Execute(findText:=myFind, Forward:=True) = True
.InsertBefore myText & myAutoTextFieldValue
Loop
End With
End Sub
And here's the answer to my own question, should anyone else require a similar piece of code.
Sub EditFindLoop()
Dim myText As String
Dim myFind As String
Dim x As Integer
myFind = "\[[0-9]*[0-9]*[0-9]\]"
myText = "Figure "
mySpace = ". "
x = 1
Dim oRange As Word.Range
Set oRange = ActiveDocument.Range
With oRange.Find
.Text = myFind
.ClearFormatting
.MatchWildcards = True
.MatchCase = False
.MatchWholeWord = False
Do While .Execute = True
If .Found Then
oRange.InsertBefore (myText & x & mySpace)
End If
oRange.Start = oRange.End
oRange.End = ActiveDocument.Range.End
x = x + 1
Loop
End With
End Sub