I know it is a very basic question, but I still can't quite understand how .Find.Execute method works in MS Word files.
For example, I see a lot of codes with this snippet
Selection.Find.Execute FindText:="some text"
Do While Selection.Find.Found
Selection.Find.Execute
Loop
My basic questions are:
1- Is there a difference between using .Find.Text and .Find.Execute FindText?
2- Why is the while loop Do While Selection.Find.Found used instead of using If Selection.Find.Found ? Or what does it mean?
3- What is the meaning of Selection.Find.Execute? And what is its role at the end of the while loop?
I have already posted an answer to one of your questions showing how to use that approach. In any event, using Selection is both inefficient and liable to produce excessive screen flicker. Moreover, unless you collapse the found range, you're liable to end up with an endless loop.
The following three approaches are functionally equivalent:
Sub Demo1()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Text = "<[ACEMR]{3}[1-4][1-9]{2}>"
.Replacement.Text = ""
End With
Do While .Find.Execute = True
'Do whatever with the found range
MsgBox .Text
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
End Sub
Sub Demo2()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Text = "<[ACEMR]{3}[1-4][1-9]{2}>"
.Replacement.Text = ""
.Execute
End With
Do While .Find.Found = True
'Do whatever with the found range
MsgBox .Text
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Sub Demo3()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Text = "<[ACEMR]{3}[1-4][1-9]{2}>"
.Replacement.Text = ""
.Execute
Do While .Found = True
'Do whatever with the found range
With .Parent
MsgBox .Text
.Collapse wdCollapseEnd
.Find.Execute
End With
Loop
End With
End With
Application.ScreenUpdating = True
End Sub
Related
I am trying to figure a way to convert intext notes (notes and references within the text body) to endnotes in an MS Word document that has existing endnotes and this is my first macro in decades.
My intext notes can be identified since they are in dark blue between curled brackets. So far I managed to record a macro for the single steps: Search for pattern, cut pattern, insert endnote, paste pattern, search pattern again in endnotes, remove curled brackets, focus back to the beginning of the document (out of endnotes).
Here is how it looks:
Sub inline2endnote()
Selection.Find.ClearFormatting
Selection.Find.Font.Color = 6299648
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "\{(*?)\}"
.Replacement.Text = "\1"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute
Selection.Cut
With Selection
With .EndnoteOptions
.Location = wdEndOfDocument
.NumberingRule = wdRestartContinuous
.StartingNumber = 1
.NumberStyle = wdNoteNumberStyleArabic
End With
.Endnotes.Add Range:=Selection.Range, Reference:=""
End With
Selection.PasteAndFormat (wdFormatOriginalFormatting)
Selection.Find.ClearFormatting
Selection.Find.Font.Color = 6299648
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "\{(*?)\}"
.Replacement.Text = "\1"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute
With Selection
If .Find.Forward = True Then
.Collapse Direction:=wdCollapseStart
Else
.Collapse Direction:=wdCollapseEnd
End If
.Find.Execute Replace:=wdReplaceOne
If .Find.Forward = True Then
.Collapse Direction:=wdCollapseEnd
Else
.Collapse Direction:=wdCollapseStart
End If
.Find.Execute
End With
Selection.HomeKey Unit:=wdStory
End Sub
I had to focus back on top because I needed to exit the endnotes section and go back to body text. Also, I have no idea what the last "With" section is meant to do.
Now I would like to loop this pattern in order to fix all the inline notes, but I seem unable to find away. I was using this thread as a reference but I can't figure out how to properly set my scope and define the fields for my iterations.
I was also wondering if there is a cleaner way to write the steps, like pasting my content without curled brackets directly, like store my find in a variable and use a second one with stripped content.
Try:
Sub Demo()
Application.ScreenUpdating = False
Dim Rng As Range, E_Nt As Endnote
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "\{[!\{]#\}"
.Font.Color = 6299648
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = True
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
Set Rng = .Duplicate
With Rng
.Start = .Start + 1
.End = .End - 1
End With
Set E_Nt = .Endnotes.Add(.Duplicate)
E_Nt.Range.FormattedText = Rng.FormattedText
E_Nt.Range.Font.ColorIndex = wdAuto
.Text = vbNullString
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Thanks in advance for any reply.
I am working on presentation of some reports. The periodical reports are imported from a different software into Word template. For all tables and for each row I would like to change the color of the negative numbers in column 14 only if there is a certain text in column 3.
Unfortunately I have to use a Word template to do this. It seems that a macro is my only option so I have tried to Frankenstein something from different macros I found online:
Dim varColumn As Column
Dim clColumn As Column
Dim cCell As Variant
Set clColumn = Selection.Columns(3)
Set varColumn = Selection.Columns(14)
With clColumn
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.text = "value"
.Replacement.text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .Information(wdWithInTable) = True Then
Selection.MoveRight Unit:=wdCell, Count:=11
End If
If cCell < 0 Then
Selection.Font.color = wdColorRed
End If
Loop
End With
End Sub
I think the macro needs lines to repeat the search. See the two lines added before Loop.
With Selection
.HomeKey Unit:=wdStory 'Starts at the beginning, to search all tables.
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "value"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .Information(wdWithInTable) = True And _
.Cells(1).ColumnIndex = 3 Then 'Confirms it's in the 3rd column.
.MoveRight Unit:=wdCell, Count:=11
End If
If .Range < 0 Then
.Font.Color = wdColorRed
End If
.Collapse wdCollapseEnd 'Collapses the selection to no characters.
.Find.Execute 'Searches again from the current selection point.
Loop
End With
Try:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "-[0-9][0-9,.]{1,}"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found = True
If .Information(wdWithInTable) = True Then
If .Cells(1).ColumnIndex = 14 Then
If Split(.Rows(1).Cells(3).Range.Text, vbCr)(0) = "specified text" Then
.Font.ColorIndex = wdRed
End If
End If
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
If the table might have vertically-merged cells, change:
If Split(.Rows(1).Cells(3).Range.Text, vbCr)(0) = "specified text" Then
to:
If Split(.Tables(1).Cell(.Cells(1).RowIndex, 3).Range.Text, vbCr)(0) = "specified text" Then
extreme VBA noob here. I'm trying to write a macro that searches for every tab and the letter following it, and replaces it with a tab and that capitalised letter.
I've figured out the following using internet articles around the place, but I'm not sure how to correctly write the Replacement.Text line. Thanks in advance.
Sub Capitaliser()
With Selection.Find
Text = "^t?"
Replacement.Text = UCase(Text)
Forward = True
Wrap = wdFindContinue
Format = False
MatchCase = False
MatchWholeWord = False
MatchWildcards = True
MatchSoundsLike = False
MatchAllWordForms = False
Execute Replace:=wdReplaceAll
End With
End Sub
Try:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "^t[a-z]"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
.Text = UCase(.Text)
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
How can i remove all words after <de> till the end of the last word, not the line itself?
I have used this code, but have a problem selecting the expansion range:
With Selection
.HomeKey Unit:=wdStory
' Find the entered texts.
With Selection.Find
.ClearFormatting
.Text = strTexts
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
Do While .Find.Found = True
' Expand the selection to the entire sentence.
Selection.Expand Unit:=wdLine
Selection.Delete
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End Sub
The code is very close. What's missing is moving it back by one character (wdCharacter, -1).
Note I've also corrected the Find.Wrap setting to wdFindStop. If you use wdFindContinue your code could enter an infinite loop - it could keep starting over at the beginning of the document.
Sub FindTheDeleteToEndOfLine()
Dim searchTerm As String
Dim bFound As Boolean
searchTerm = "<de>"
Selection.HomeKey wdStory
'Basic Find settings
With Selection.Find
.Forward = True
.wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
'Execute the Find
Do
With Selection.Find
.Text = searchTerm
bFound = .Execute
If bFound Then
Selection.MoveEnd wdLine, 1
Selection.MoveEnd wdCharacter, -1
Selection.Delete
End If
End With
Loop While bFound
End Sub
The code below deletes everything after Slim Shady up to the end of the line.
Thus from:
you get:
Public Sub DeleteAfterEminem()
Do While True
Selection.HomeKey wdStory
With Selection
.Find.Text = "Slim Shady"
If .Find.Execute Then
.MoveEnd wdLine, 1
.MoveEnd wdCharacter, -1
.Delete
Else
Exit Do
End If
End With
Loop
End Sub
If you want to remove everything from Slim Shady to the end of the document this is a working solution:
Public Sub DeleteAfterEminem()
With Selection
.Find.Text = "Slim Shady"
If .Find.Execute Then
.End = ActiveDocument.Range.End
' .End = Selection.End
.Delete
End If
End With
End Sub
I have a VBA macro(Word2010) script to highlight all the text in italics. But when executed in large file say a document with more than 10 pages the Word get crashed.
I have used the below code for this purpose.
Sub Italics_Highlight()
'
' test_italics_highlight_ Macro
'
'
Application.ScreenUpdating = False
Dim myString As Word.Range
Set myString = ActiveDocument.Content
With myString.Find
.ClearFormatting
.Text = ""
.Font.Italic = True
While .Execute
myString.HighlightColorIndex = wdTurquoise
myString.Collapse wdCollapseEnd
Wend
End With
MsgBox "Thank you!"
End Sub
Could you please help to overcome this. Thanks for your help in advance.
Your error description looks like your code is running forever and doesn't finish.
You might want to add a DoEvents inside your While loop to keep Word responsive while running the code.
With myString.Find
.ClearFormatting
.Text = ""
.Font.Italic = True
While .Execute
DoEvents 'keeps Word responsive
myString.HighlightColorIndex = wdTurquoise
myString.Collapse wdCollapseEnd
Wend
End With
I'm not sure if your code will ever stop. The loop might not stop at the end of the document but start again from beginning, and therefore always find something italic again and again, looping forever.
So you might need to set the .Wrap = wdFindStop to stop at the end of the document.
See Find.Wrap Property (Word).
With myString.Find
.ClearFormatting
.Text = ""
.Font.Italic = True
.Wrap = wdFindStop 'stop at the end of the document
While .Execute
DoEvents 'keeps Word responsive
myString.HighlightColorIndex = wdTurquoise
myString.Collapse wdCollapseEnd
Wend
End With
You don't need to stop at each "found" and apply highlighting. You can do it as part of a Find/Replace:
Sub testInfiniteLoop()
Dim myString As word.Range
Set myString = ActiveDocument.content
Options.DefaultHighlightColorIndex = wdTurquoise
With myString.Find
.ClearFormatting
.Text = ""
.Font.Italic = True
.Replacement.Text = ""
.Replacement.Highlight = wdTurquoise
.wrap = wdFindStop 'stop at the end of the document
.Execute Replace:=wdReplaceAll
End With
End Sub
The following code not only highlights but also restores whatever highlight settings were previously in force:
Sub Italics_Highlight()
Application.ScreenUpdating = False
Dim i As Long: i = Options.DefaultHighlightColorIndex
Options.DefaultHighlightColorIndex = wdTurquoise
With ActiveDocument.Content.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = "^&"
.Replacement.Highlight = True
.Format = True
.Font.Italic = True
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Options.DefaultHighlightColorIndex = i
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
As you can see, you also don't need:
Dim myString As Word.Range
Set myString = ActiveDocument.Content