Macro to convert intext notes to endnotes in MS Word - vba

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

Related

How to find all instances of highlighted text in the active document and removes the highlight formatting with mark-up?

How do you find all instances of the highlighted text in the active document and remove the highlight formatting with mark-up?
I found a macro in https://learn.microsoft.com/en-us/office/vba/api/word.find.highlight. But I want it to remove the highlight formatting with mark-up. I tried to add " ActiveDocument.TrackRevisions = True" to turn on the Track Changes but in vain.
Sub A()
Dim rngTemp As Range
Set rngTemp = ActiveDocument.Range(Start:=0, End:=0)
With rngTemp.Find
.ClearFormatting
.Highlight = True
With .Replacement
.ClearFormatting
.Highlight = False
End With
.Execute Replace:=wdReplaceAll, Forward:=True, FindText:="", _
ReplaceWith:="", Format:=True
End With
End Sub
Then I tried to record a Macro and edited it as follows:
Sub Macro1()
Selection.Find.ClearFormatting
Selection.Find.Highlight = True
With Selection.Find
.Text = ""
.Replacement.Text = "^&"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Options.DefaultHighlightColorIndex = wdNoHighlight
Selection.Range.HighlightColorIndex = wdNoHighlight
Selection.Find.Execute
End Sub
The second one can only change highlighted text to no highlight with mark-up one by one. It is not convenient since I have at least 200 highlighted texts to decide whether they should be corrected in a document. How can I edit it to automatically select all highlighted text and then remove their highlights with mark-ups?
Sub FindRemoveHighlighting()
Dim findRange As Range: Set findRange = ActiveDocument.Content
ActiveDocument.TrackRevisions = True
With findRange
With .Find
.Highlight = True
.Text = ""
.Format = True
End With
Do While .Find.Execute() = True
.HighlightColorIndex = wdNoHighlight
.Collapse wdCollapseEnd
Loop
End With
End Sub

Use VBA regular expression in Word Find/Replace macro?

I often use a legacy text editor (Vim) to take meeting notes because I can keep up with the talking. However, most people (including myself) prefer the final notes to be in Word, with bullets and sub-bullets. Here is an example of a text file that I wanted to convert to Word bullets:
Meeting notes
-------------
* The quick brown fox
* The quick brown fox
- Jumped over the lazy dogs
- Jumped over the lazy dogs
* The quick brown fox
I recorded a macro to convert text bullets to Word bullets. Any paragraph starting with text bullet "*" gets converted to "List Bullet 2", then I globally replace "*" with "" (i.e., deleted). Any paragraph starting with the more indented text bullet " -" gets converted to "List Bullet 4", then I globally delete " -". The "BulletsTxt2wrd" macro is shown below.
The problem is, I use Word's Find/Replace function, which can't really restrict the search of the above strings to the beginning of a paragraph. If there is a "*" in the middle of the paragraph (perhaps "25 * 3.1415"), the same paragraph formatting and deletion occurs.
Regular expressions can confine searches to the start of a paragraph. I used regular expressions in a unix environment, and after years of reading that it can be done in VBA, I used it in simple Excel function to convert time durations specified in days/minutes to hours. For example (see "DurtnStr2hrs" function below:
"20 hours" becomes 20
"1 hour" becomes 1
"1 day" becomes 24
"3 days" becomes 3*24
"1 minute" becomes 1/60
"70 minutes" becomes 70/60
I use this function within a spreadsheet cell, with the argument being another cell containing the string to be converted.
Is there a way to use the regular expression package and objects in the "BulletsTxt2wrd" Word macro? It seems to function like a black box, and the VBA code doesn't really expose the object property containing the string that I want to operate on.
P.S. This post doesn't deal with the Find/Replace method that I recorded, which goes through the entire document to locate matches.
This post refers to VBScript, but I really would like to avoid having to figure out another language to accomplish my simple task.
This post also doesn't use the Find/Replace recorded in my macro.
Sub BulletsTxt2wrd()
'
' BulletsTxt2wrd Macro
'
'
Selection.HomeKey Unit:=wdStory
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles("List Bullet 2")
With Selection.Find
.Text = " * "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = " * "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles("List Bullet 4")
With Selection.Find
.Text = " - "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = " - "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
Function DurtnStr2hrs(str) As Double
' Use for DurtnHrs column
Dim NewStr As String
Dim regex1 As Object
Set regex1 = New RegExp
NewStr = str
regex1.Pattern = " hours?"
NewStr = regex1.Replace(NewStr, "")
regex1.Pattern = " minutes?"
NewStr = regex1.Replace(NewStr, "/60")
regex1.Pattern = " days?"
NewStr = regex1.Replace(NewStr, "*24")
DurtnStr2hrs = Evaluate(NewStr)
End Function
«The problem is, I use Word's Find/Replace function, which can't really restrict the search of the above strings to the beginning of a paragraph» Au contraire, you could use:
Sub Demo1()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "^13[ *-]{1,}"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
End With
Do While .Find.Execute
.Start = .Start + 1
Select Case Trim(.Text)
Case "*": .Paragraphs.Last.Style = wdStyleListBullet2
Case "-": .Paragraphs.Last.Style = wdStyleListBullet4
End Select
.Text = vbNullString
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
End Sub
As for the DurtnStr2hrs conversion, I note there remains a disconnect between your text description of ""20 hours" becomes 20*60" and your Regex of "NewStr = regex1.Replace(NewStr, "/60")". That said, try:
Sub Demo2()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<[0-9]# [dh][ao][yu]*>"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
End With
Do While .Find.Execute
.Start = .Start + 1
Select Case Split(.Text, " ")(1)
Case "hour": .Text = Split(.Text, " ")(0)
Case "hours": .Text = Split(.Text, " ")(0) & "/60"
Case "day": .Text = "24"
Case "days": .Text = Split(.Text, " ")(0) & "*24"
End Select
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
End Sub
The following seems to do the job:
Sub BulletTxt2doc()
doL1bullet:
Selection.HomeKey Unit:=wdStory
Selection.Find.ClearFormatting
With Selection.Find
.Text = "^p * "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
Selection.Find.Execute
If .Found = True Then
Selection.EndKey Unit:=wdLine
Selection.Style = ActiveDocument.Styles("List Bullet 2")
Selection.MoveUp Unit:=wdParagraph, Count:=1
Selection.MoveRight Unit:=wdWord, Count:=2, Extend:=wdExtend
Selection.Delete Unit:=wdCharacter, Count:=1
GoTo doL1bullet
End If
End With
doL2bullet:
Selection.HomeKey Unit:=wdStory
Selection.Find.ClearFormatting
With Selection.Find
.Text = "^p - "
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
Selection.Find.Execute
If .Found = True Then
Selection.EndKey Unit:=wdLine
Selection.Style = ActiveDocument.Styles("List Bullet 4")
Selection.MoveUp Unit:=wdParagraph, Count:=1
Selection.MoveRight Unit:=wdWord, Count:=2, Extend:=wdExtend
Selection.Delete Unit:=wdCharacter, Count:=1
GoTo doL2bullet
End If
End With
End Sub

Only select bold & underline text in current paragraph (VBA macro, word 2016)

I'm trying to select any bolded & underlined text in a paragraph (in Microsoft word 2016). I really just want to select the text so I can manipulate in various ways (which will constantly vary depending on my needs for that specific text), eg highlight, unbold, copy etc.
I created the below macro using the macro recorder feature and when I was doing it it worked perfectly. But when I subsequently ran the macro it highlighted the whole paragraph, as opposed to just the bolded & underlined parts.
Sub SelectBoldandUnderlineCurrentParagraph()
'
' SelectBoldandUnderlineCurrentParagraph Macro
'
'
Selection.MoveUp Unit:=wdParagraph, Count:=1
Selection.MoveDown Unit:=wdParagraph, Count:=1, Extend:=wdExtend
Selection.Find.ClearFormatting
With Selection.Find.Font
.Bold = True
.Underline = wdUnderlineSingle
End With
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindAsk
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchKashida = False
.MatchDiacritics = False
.MatchAlefHamza = False
.MatchControl = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
End Sub
Try:
Sub Demo()
With Selection.Paragraphs.First.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Font.Bold = True
.Font.Underline = wdUnderlineSingle
.Text = ""
.Replacement.Text = ""
.Format = True
.Forward = True
.Wrap = wdFindStop
.Execute
End With
.Select
End With
End Sub

Word macro for changing color for negative numbers in a specific column depending on value in a different column

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

How to delete all words that follow a certain string to the end of a line, using VBA?

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