Apply find/replace routine to entire document - vba

I have a macro to ensure large numbers have commas in the correct locations.
My routine to insert commas works, but also includes dates, street #s, etc. (e.g., 15 January 2,022 and 1,234 Smith Street).
I am attempting to correct the street addresses, but am doing something wrong with my looping. It is only finding/fixing the first instance of a street number with a comma in it.
Note that the code snippet included several commented commands that I tried during troubleshooting.
'remove commas from street addresses
Set oRange = ActiveDocument.Range
With oRange.Find
'Set the search conditions
.ClearFormatting
.Text = "(<[0-9]{1,2})(,)([0-9]{3})"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchWildcards = True
.Execute
'If .Found Then
Do While .Found
oRange.Select 'for debugging purposes
If (InStr(1, "NorthEastWestSouth", Trim(oRange.Words(3).Next(wdWord, 1)), 0) <> 0 And Len(Trim(oRange.Words(3).Next(wdWord, 1))) > 1) Or _
(InStr(1, "StreetAvenueRoadRdBoulevardBlvdPikeCircleHighwayHwyCourtCtLaneWayParkwayAlleyBypassEsplanadeFreewayJunctionRouteRteTraceTrailTurnpikeVille", _
Trim(oRange.Words(3).Next(wdWord, 2)), 0) <> 0 And Len(Trim(oRange.Words(3).Next(wdWord, 2))) > 1) Or _
(InStr(1, "StreetAvenueRoadRdBoulevardBlvdPikeCircleHighwayHwyCourtCtLaneWayParkwayAlleyBypassEsplanadeFreewayJunctionRouteRteTraceTrailTurnpikeVille", _
Trim(oRange.Words(3).Next(wdWord, 3)), 0) <> 0 And Len(Trim(oRange.Words(3).Next(wdWord, 3))) > 1) Or _
InStr(1, "N.E.W.S.", Trim(oRange.Words(3).Next(wdWord, 1) & Trim(oRange.Words(3).Next(wdWord, 2))), 0) <> 0 Then
.Replacement.Text = "\1\3"
.Execute Replace:=wdReplaceAll
'oRange.Text = VBA.Replace(oRange.Text, ",", "")
End If
'.Execute
'End If
Loop 'continue finding
End With

Try:
Sub Demo()
Application.ScreenUpdating = False
Dim StrFnd As String, i As Long
StrFnd = "Alley|Avenue|Av|Boulevard|Blvd|Bypass|Circuit|Crct|Circle|Crcl|Court|Ct|Esplanade|Esp|Freeway|Fwy|" & _
"Junction|Jnc|Highway|Hwy|Lane|Ln|Way|Parkway|Pike|Road|Rd|Street|St|Route|Rt|Trace|Trail|Turnpike|Ville"
With ActiveDocument.Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchWildcards = True
'Process dates
.Text = "([JFMASOND][anuryebchpilgstmov]{2,8} [12]),([0-9]{3})>"
.Replacement.Text = "\1\2"
.Execute Replace:=wdReplaceAll
'Process addresses
For i = 0 To UBound(Split(StrFnd, "|"))
.Text = "([0-9]),([0-9]{3} <[A-Z][a-z]#> " & Split(StrFnd, "|")(i) & ")"
.Execute Replace:=wdReplaceAll
.Text = "([0-9]),([0-9]{3} [NSEW]. <[A-Z][a-z]#> " & Split(StrFnd, "|")(i) & ")"
.Execute Replace:=wdReplaceAll
.Text = "([0-9]),([0-9]{3} <[A-Za-z]#> <[A-Z][a-z]#> " & Split(StrFnd, "|")(i) & ")"
.Execute Replace:=wdReplaceAll
.Text = "([0-9]),([0-9]{3} [NSEW]. <[A-Za-z]#> <[A-Z][a-z]#> " & Split(StrFnd, "|")(i) & ")"
.Execute Replace:=wdReplaceAll
Next
End With
Application.ScreenUpdating = True
End Sub
Not sure what you're trying to achieve with 'NorthEastWestSouth' and 'N.E.W.S.'

Related

Remove OR replace faulty paragraph marks using VBA macro

I have some faulty paragraphs, which are causing my other macros to not work properly.
They are usually heading style 2, style 3
Empty (not sure)
before OR after table (not sure)
surrounded by dotted line
causes the heading and next table to merged together (not sure)
I tried to replace/removed those with the following macro:
Sub HeadingParaBug()
Dim H As Range
Set H = ActiveDocument.Range
LS = Application.International(wdListSeparator)
With H.Find
.Text = "^p "
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Text = " ^p"
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Text = "^p ^p"
.Replacement.Text = "^p^p"
.Execute Replace:=wdReplaceAll
.Text = "^13{2" & LS & "}"
.Replacement.Text = "^p"
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
.Text = ""
.Style = wdStyleHeading2
.MatchWildcards = False
Do While .Execute
If H.Text <> vbCr Then
H.Collapse 0
H.Select
H.InsertParagraph
H.Delete
End If
H.Collapse 0
Loop
End With
Set H = ActiveDocument.Range
With H.Find
.Style = wdStyleHeading3
Do While .Execute
If H.Text <> vbCr Then
H.Collapse 0
H.Select
H.InsertParagraph
H.Delete
End If
H.Collapse 0
Loop
End With
End Sub
But somehow, it do not completely removed/replace the faulty paragraph marks. The above macro finds those paragraphs, add new and then remove it. which eventually removed the dotted line.
Can anybody explain this phenomena? what is the right ways to remove/replace those paragraphs. please download and see test file with error on page 7
Update: Even I tried with the following code but it did nothing (on MacOS Video). I think it is not finding the hidden paragraphs:
Sub HidNempty()
Dim H As Range
Set H = ActiveDocument.Range
With H.Find
.Text = "^p "
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Text = " ^p"
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Text = "^p ^p"
.Replacement.Text = "^p^p"
.Execute Replace:=wdReplaceAll
.Text = "^p"
Do While .Execute
If H.Font.Hidden = True Then
H.Font.Hidden = False
If Len(Trim(H.Paragraphs(1).Range.Text)) = 1 Then
H.Delete
End If
End If
Loop
End With
End Sub
To unhide all document paragraphs, please try the next piece of code:
Sub UnHideParagraphs()
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
If para.Range.Font.Hidden Then
para.Range.Font.Hidden = False
End If
Next para
End Sub
It should work even if only part of the paragraph range is hidden...
Find/Replace won't delete duplicate paragraph breaks before a table, between tables, or after a table. Try:
Sub Demo()
Application.ScreenUpdating = False
Dim LS As String, Tbl As Table, bHid As Boolean
LS = Application.International(wdListSeparator)
bHid = ActiveWindow.View.ShowHiddenText
ActiveWindow.View.ShowHiddenText = True
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Format = True
.Forward = True
.Replacement.Font.Hidden = False
.Wrap = wdFindContinue
.MatchWildcards = False
.Text = "^p^w"
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Text = "^w^p"
.Execute Replace:=wdReplaceAll
.MatchWildcards = True
.Text = "^13{2" & LS & "}"
.Execute Replace:=wdReplaceAll
.Wrap = wdFindStop
End With
Do While .Find.Execute = True
With .Duplicate
.Font.Hidden = False
.Start = .Start + 1
.Text = vbNullString
End With
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
For Each Tbl In ActiveDocument.Range.Tables
With Tbl.Range
Do While .Characters.First.Previous.Previous = vbCr
.Characters.First.Previous.Previous = vbNullString
Loop
.Characters.First.Previous.Font.Hidden = False
Do While .Characters.Last.Next = vbCr
If .Characters.Last.Next.End = ActiveDocument.Range.End Then Exit Do
If .Characters.Last.Next.Next.Information(wdWithInTable) = True Then Exit Do
.Characters.Last.Next = vbNullString
Loop
.Characters.Last.Next.Font.Hidden = False
End With
Next
ActiveWindow.View.ShowHiddenText = bHid
Application.ScreenUpdating = True
End Sub
You will observe various lines in the code that apply .Font.Hidden = False. Depending on what you're trying to achieve visually, you may or may not want those.

How to find table column, then move down and replace the cell's content IF it is "N/A"

I have almost 1,800 Word documents that have about 8 pages with unique data in tables. We were just informed that the data we were given for some of those tables is inaccurate and needs to be changed from "N/A" to "0.0%". As "N/A" is used a lot in the document, I unfortunately cannot just find/replace that text.
Using this thread (Macro to find in Word table for specific string in a cell and move x cell left, check isnumeric then set typography on down x cell in the same column) I was able to adjust the code below to find the column header (On-Time Completion Rate) and move to the adjacent cells to update them. However, since this column is for percentages, the IsNumeric code is changing any data it finds due to the percentage symbol.
Is there a way to do the same but instead of using IsNumeric (since it does not work for percentages) check the value in the cell and if it finds "N/A" change it to "0.0%"? This would then need to be repeated for two more tables, with one table have four rows to look through.
Thank you in advance for any help you can offer!
Screenshot of table
Sub Demo()
Application.ScreenUpdating = False
Dim r As Long, c As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "On-time Completion Rate" 'Column Header'
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .Information(wdWithInTable) = True Then
r = .Cells(1).RowIndex
c = .Cells(1).ColumnIndex
With .Tables(1)
If Not IsNumeric(Split(.Cell(r + 1, c).Range.Text, vbCr)(0)) Then .Cell(r + 1, c).Range.Text = "0.0%"
If Not IsNumeric(Split(.Cell(r + 2, c).Range.Text, vbCr)(0)) Then .Cell(r + 2, c).Range.Text = "0.0%"
End With
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Try this:
Sub Demo()
Application.ScreenUpdating = False
Dim r As Long, c As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "On-time Completion Rate" 'Column Header'
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .Information(wdWithInTable) = True Then
r = .Cells(1).RowIndex
c = .Cells(1).ColumnIndex
With .Tables(1)
If Split(.Cell(r + 1, c).Range.Text, vbCr)(0) = "N/A" Then .Cell(r + 1, c).Range.Text = "0.0%"
If Split(.Cell(r + 2, c).Range.Text, vbCr)(0) = "N/A" Then .Cell(r + 2, c).Range.Text = "0.0%"
End With
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
If all instances of N/A in the tables are to be replaced, the following would be more efficient:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "On-time Completion Rate"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
.Duplicate.Tables(1).Range.Find.Execute FindText:="N/A", ReplaceWith:="0.0%", Wrap:=wdFindStop, Replace:=wdReplaceAll
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Extending this to process a whole folder of documents, you could use code like:
Sub UpdateDocuments()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String, strDocNm As String, wdDoc As Document
strDocNm = ActiveDocument.FullName: strFolder = GetFolder
If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.docx", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> strDocNm Then
Set wdDoc = Documents.Open(FileName:=strFolder & "\" & strFile, AddToRecentFiles:=False, Visible:=False)
With wdDoc
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "On-time Completion Rate"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
.Duplicate.Tables(1).Range.Find.Execute FindText:="N/A", ReplaceWith:="0.0%", Wrap:=wdFindStop, Replace:=wdReplaceAll
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDoc = Nothing
Application.ScreenUpdating = True
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
To extend the code even further to process documents in sub-folders, see: https://www.msofficeforums.com/47785-post14.html
To save the updated documents as PDFs, insert:
.SaveAs FileName:=Split(.FullName, ".doc")(0) & ".pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
before:
.Close SaveChanges:=True

Style to a variable in VBA

so i have this code, it replaces every X in the text with "Asunto (1,2,..): Expediente N°". I try to style this part of the code:
What i want is put that text that replaces the X in Arial 11 Bold
.Text = "Asunto" & " " & i & " " & "Expediente N°"
i tried this but the style applies to the whole document instead of just that text, i don´t know what else to try
Sub Macro1()
'
' Macro1 Macro
'
'
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "X"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
i = i + 1
.Text = "Asunto" & " " & i & " " & "Expediente N°"
.Find.Execute
.Collapse wdCollapseEnd
.Find.Execute
Loop
With .Font
.Bold = True
.Name = "Arial"
.Size = 11
End With
Application.ScreenUpdating = True
MsgBox i & " Coincidencias."
End With
End Sub
You are NOT applying a Style - all you're doing is overriding whatever Style is already present with hard formatting. Do do with a Style, try for example:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "X"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
End With
Do While .Find.Execute
i = i + 1
.Text = "Asunto" & " " & i & " " & "Expediente N°"
.Style = wdStyleStrong
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
MsgBox i & " instances found."
End Sub
In the above, I've employed Word's 'Strong' Style, via the constant wdStyleStrong. If your text is already 11pt Arial, that's all you need. Otherwise, you should define a suitable 11pt Arial Bold character Style and apply that.

Repetitive search in VB (Word)

I have written a macro in Word to convert US spellings to UK. In summary, it looks like this:
US_spelling = analyze
UK-spelling = analyse
Call Spell_change (US_spelling, UK_spelling)
The Spell_change sub changes the spelling, adds a comment to the document, and adds 1 to a counter.
I repeat the above three lines, i.e. call the Spell_change sub, about 140 times (for 'program', 'dialog' etc).
Is there a more efficient way of doing this?
Many thanks.
Since you've changed the tag to refer to VBA, perhaps:
Sub Demo()
Application.ScreenUpdating = False
Dim StrFnd As String, StrRep As String, i As Long, Cmt As Comment, StrOut As String
StrFnd = "analyze,color,labor"
StrRep = "analyse,colour,labour"
StrOut = "US_spelling" & vbTab & "UK_spelling"
With ActiveDocument
With .Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = True
For i = 0 To UBound(Split(StrFnd, ","))
.Text = Split(StrFnd, ",")(i)
.Replacement.Text = Split(StrRep, ",")(i)
.Execute Replace:=wdReplaceAll
If .Found = True Then StrOut = StrOut & vbCr & Split(StrFnd, ",")(i) & vbTab & Split(StrRep, ",")(i)
Next
End With
Set Cmt = .Comments.Add(Range:=.Range(0, 0), Text:=StrOut & vbCr & "Total: " & UBound(Split(StrOut, vbCr)))
With Cmt
.Author = ""
With .Range.Paragraphs
.First.Range.Font.Bold = True
.Last.Range.Font.Bold = True
End With
End With
End With
Application.ScreenUpdating = True
End Sub
The above code inserts a comment at the top of the document with a record of all words found & changed, plus a count of those words (but not how many times each word was replaced).

How to insert fields within headings

I am trying to insert fields within the headings in a Word document, not before or after them. This is to prepare Word files for import to Madcap Flare which allows file names to be specified within a private Word field. The following code doesn't work because the field is appended before the start of the heading, it needs to be embedded within it. How can I do this.
Sub prepareDocForImport()
Dim headingText As String '
With Selection.Find
.ClearFormatting
.Wrap = wdFindContinue
.Forward = True
.Format = True
.MatchWildcards = False
.Text = ""
.Style = ActiveDocument.Styles("Heading 1 ")
.Execute
While .Found
headingText = Selection.Range.Text
headingText = Replace(headingText , " ", "_")
headingText = LCase(headingText )
Selection.Collapse Direction:=wdCollapseStart
Set myField = ActiveDocument.Fields.Add(Range:=Selection.Range, Type:=wdFieldEmpty, Text:="PRIVATE:MADCAP:FILENAME<" & headingText & ">")
.Execute
Wend
End With
End Sub
Try moving the cursor one character into the header word.
I also added a line for ensuring that the search starts at the beginning of the document.
Sub prepareDocForImport()
Dim headingText As String
Dim myfield As Field
'Moving to beginning of doc in case a different starting point is selected
Selection.HomeKey wdStory
With Selection.Find
.ClearFormatting
.Wrap = wdFindContinue
.Forward = True
.Format = True
.MatchWildcards = False
.Text = ""
.Style = ActiveDocument.Styles("Heading 1 ")
.Execute
While .Found
headingText = Selection.Range.Text
headingText = Replace(headingText, " ", "_")
headingText = LCase(headingText)
Selection.Collapse Direction:=wdCollapseStart
'Move seleection one character into the header text
Selection.MoveRight Count:=1
Set myfield = ActiveDocument.Fields.Add(Range:=Selection.Range, _
Type:=wdFieldEmpty, _
Text:="PRIVATE:MADCAP:FILENAME<" & headingText & ">", _
PreserveFormatting:=True)
.Execute
Wend
End With
End Sub