VBA: Format MS Word text - vba

I am trying to format text of multiple words. So far, the code below will only allow me to format the font of one word. What do I need to add / delete in order to have as many words as I input be formatted?
Cheers!
Sub FnFindAndFormat()
Dim objWord
Dim objDoc
Dim intParaCount
Dim objParagraph
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open("C:\USERPATH")
objWord.Visible = True
intParaCount = objDoc.Paragraphs.Count
Set objParagraph = objDoc.Paragraphs(1).range
objParagraph.Find.Text = "deal"
Do
objParagraph.Find.Execute
If objParagraph.Find.Found Then
objParagraph.Font.Name = "Times New Roman"
objParagraph.Font.Size = 20
objParagraph.Font.Bold = True
objParagraph.Font.Color = RGB(200, 200, 0)
End If
Loop While objParagraph.Find.Found
End Sub

Let's say your word document looks like this
Since I am not sure whether you are doing this from Word-VBA or from some other application like say Excel-VBA so I am including both methods.
Now if you are doing this from Word-VBA then you do not need to LateBind with it. Use this simple code.
Option Explicit
Sub Sample()
Dim oDoc As Document
Dim MyAr() As String, strToFind As String
Dim i As Long
'~~> This holds your search words
strToFind = "deal,contract, sign, award"
'~~> Create an array of text to be found
MyAr = Split(strToFind, ",")
'~~> Open the relevant word document
Set oDoc = Documents.Open("C:\Sample.docx")
'~~> Loop through the array to get the seacrh text
For i = LBound(MyAr) To UBound(MyAr)
With Selection.Find
.ClearFormatting
.Text = MyAr(i)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Execute
'~~> Change the attributes
Do Until .Found = False
With Selection.Font
.Name = "Times New Roman"
.Size = 20
.Bold = True
.Color = RGB(200, 200, 0)
End With
Selection.Find.Execute
Loop
End With
Next i
End Sub
However if you are doing from say Excel-VBA then use this
Const wdFindContinue = 1
Sub FnFindAndFormat()
Dim objWord As Object, objDoc As Object, Rng As Object
Dim MyAr() As String, strToFind As String
Dim i As Long
'~~> This holds your search words
strToFind = "deal,contract, sign, award"
'~~> Create an array of text to be found
MyAr = Split(strToFind, ",")
Set objWord = CreateObject("Word.Application")
'~~> Open the relevant word document
Set objDoc = objWord.Documents.Open("C:\Sample.docx")
objWord.Visible = True
Set Rng = objWord.Selection
'~~> Loop through the array to get the seacrh text
For i = LBound(MyAr) To UBound(MyAr)
With Rng.Find
.ClearFormatting
.Text = MyAr(i)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Execute
Set Rng = objWord.Selection
'~~> Change the attributes
Do Until .Found = False
With Rng.Font
.Name = "Times New Roman"
.Size = 20
.Bold = True
.Color = RGB(200, 200, 0)
End With
Rng.Find.Execute
Loop
End With
Next i
End Sub
OUTPUT

Works like a charm for me:
Public Sub Find_some_text()
'setting objects
Dim objWord
Dim objDoc
Dim objSelection
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open("H:\Test.docx")
'set visibility
objWord.Visible = True
'set array of words to format
words_list = Array("Findme_1", "Findme_2", "etc")
'formatting text
For Each w In words_list
Set Frange = objDoc.Range
Frange.Find.Text = w
Do
Frange.Find.Execute
If Frange.Find.Found Then
Frange.Font.Name = "Times New Roman"
Frange.Font.Size = 20
Frange.Font.Bold = True
Frange.Font.Color = RGB(200, 200, 0)
End If
Loop While Frange.Find.Found
Next
'de-set visibility
objWord.Visible = False
'saving (optional)
objDoc.Save
End Sub

This code:
For Each w In words_list
Set Frange = objDoc.Range
Frange.Find.Text = w
Do
Frange.Find.Execute
If Frange.Find.Found Then
Frange.Font.Name = "Times New Roman"
Frange.Font.Size = 20
Frange.Font.Bold = True
Frange.Font.Color = RGB(200, 200, 0)
End If
Loop While Frange.Find.Found
Next
is inefficient. Try:
With objDoc.Range.Find
.ClearFormatting
With .Replacement
.ClearFormatting
.Text = "^&"
With .Font
.Name = "Times New Roman"
.Size = 20
.Bold = True
.Color = RGB(200, 200, 0)
End With
End With
.Format = True
.Forward = True
.Wrap = 1 'wdFindContinue
For Each w In words_list
.Text = w
.Execute Replace:=2 'wdReplaceAll
Next
End With

Related

Word VBA copy highlighted text to new document and preserve formatting

I have a word document with multiple highlighted words that I want to copy into another word file. The code I'm using works fine, but does not preserve the original formatting in the source document. Here's the entire code (1st section finds words using wildcards and highlights them, and the 2nd section finds the highlighted words and copies them to a new word document):
Sub testcopytonewdoc2()
'
Dim ThisDoc As Document
Dim ThatDoc As Document
Dim r, newr, destr As Range
Dim rangestart, rangeend As Long
Set r = ActiveDocument.Range
rangeend = r.Characters.Count
r.Find.Execute FindText:="39.13 [Amended]"
rangestart = r.Start
'find words and highlight them
x = 0
Do While x < 4
Application.ScreenUpdating = False
Options.DefaultHighlightColorIndex = wdYellow
With ActiveDocument.Content.Find
'.ClearFormatting
If x = 0 Then
.text = "[!)][(][1-9][)]?{7}"
ElseIf x = 1 Then
.text = "[!?][(][a-z][)][ ][A-Z]?{6}"
ElseIf x = 2 Then
.text = "[!?][(][ivx]{2}[)][ ][A-Z]?{6}"
Else
.text = "[!?][(][ivx]{3}[)][ ][A-Z]?{6}"
End If
With .Replacement
' .ClearFormatting
.Highlight = True
End With
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
Application.ScreenUpdating = True
x = x + 1
Loop
Set ThisDoc = ActiveDocument
Set newr = ThisDoc.Range
Set ThatDoc = Documents.Add
newr.SetRange Start:=rangestart, End:=rangeend
'find highlighted words and add to a new document (preserve BOLD font):
With newr.Find
.text = ""
.Highlight = True
.Format = True
.Wrap = wdFindStop
While .Execute
Set destr = ThatDoc.Range
destr.Collapse wdCollapseEnd
destr.FormattedText = newr.FormattedText
ThatDoc.Range.InsertParagraphAfter
newr.Collapse wdCollapseEnd
Wend
End With
Application.ScreenUpdating = True
End Sub
Can anyone help? The highlighted words are a mix of bold and non-bold text and it's important to maintain this difference. Thanks in advance for your help!
Holly
Try it this way.
Sub ExtractHighlightedText()
Dim oDoc As Document
Dim s As String
With Selection
.HomeKey Unit:=wdStory
With .Find
.ClearFormatting
.Text = ""
.Highlight = True
Do While .Execute
s = s & Selection.Text & vbCrLf
Loop
End With
End With
Set oDoc = Documents.Add
oDoc.Range.InsertAfter s
End Sub
This comes from my book.
http://www.lulu.com/shop/ryan-shuell/ebook/product-22936385.html

Find all text formatted with given color

I am looking for a way to create a new document containing all the text with a specific format from my document.
See below for what I wrote so far, but I'm stuck here:
how do I stop my loop when end of document is reached? or how do I add intelligence to my code to avoid a static loop, and rather do a "scan all my document"?
Option Explicit
Sub Macro1()
Dim objWord As Application
Dim objDoc As Document
Dim objSelection As Selection
Dim mArray() As String
Dim i As Long
Dim doc As Word.Document
For i = 1 To 100
ReDim Preserve mArray(i)
With Selection.Find
.ClearFormatting
.Font.Color = wdColorBlue
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = True
.Execute
End With
mArray(i) = Selection.Text
Next
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
objWord.Visible = True
Set objSelection = objWord.Selection
For i = 1 To 100
objSelection.TypeText (mArray(i))
Next
End Sub
Thanks to Cindy's nice tip (I could also have found relevant information in Loop through Word document, starting from beginning of file at start of each loop), and in case this could help someone some day:
define the format you are looking for thanks to Word's Macro Recorder
position yourself at the beginning of your document
Use a while loop checking wdFindStop -- It also demonstrate how to use Array of String in VBA--:
...
Sub Macro2()
Dim mArray() As String
Dim i As Long, n As Long
Dim doc As Word.Document
Dim isFound As Boolean
isFound = True
i = 1
'For i = 1 To 40
Do While (isFound)
ReDim Preserve mArray(i)
With Selection.Find
.ClearFormatting
.Font.Color = wdColorBlue
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = True
isFound = .Execute
End With
mArray(i) = Selection.Text
i = i + 1
Loop
'Next
n = i - 2
MsgBox n & " occurrences found."
'
' create a new document with the phrases found
Dim objWord As Application
Dim objDoc As Document
Dim objSelection As Selection
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
objWord.Visible = True
Set objSelection = objWord.Selection
For i = 1 To n 'mArray's Size
objSelection.TypeText (mArray(i))
objSelection.TypeParagraph
Next
End Sub
NB: I could also have greatly benefited from https://msdn.microsoft.com/en-us/library/office/aa211953%28v=office.11%29.aspx that explains how to find without changing the selection:
With ActiveDocument.Content.Find
.Text = "blue"
.Forward = True
.Execute
If .Found = True Then .Parent.Bold = True
End With
And from here: Find text only of style "Heading 1" (Range.Find to match style)

Automatic formatting for certain words found in Outlook email body

Problem:
We have certain branding formatting for our product names, but manually changing the colour and font style in every email across the company is time consuming.
Solution:
I am trying to build a Macro VBA code to instantly find these words and change the formatting.
The code needs to find a word that starts with the string "abc" and then reformats the entire word to bold and then changes the colour of the "abc" string to the correct brand's colour corresponding to the letters following the full word/product. Once it has been bolded, I don't want clicking the button again to increase the font size, so an "if bolded do nothing" is required
e.g. any word with "abctelephone" needs to be bolded and the abc changed to the corresponding brand's colour. (abctelephone with the abc in blue)
I have this scenario working in Word 2013, and I have an example code set below that I have tried to modify from the existing to replicate this functionality in an Outlook email by referencing Microsoft Word 15.0 Object Library in the Visual Basic References Tool.
Any pointers?
Sub Branding()
Dim insp As Outlook.Inspector
Dim myObject As Object
Dim msg As Outlook.MailItem
Dim myDoc As Word.Document
Dim mySelection As Word.Selection
Dim strItem As String
Dim strGreeting As String
Dim StrTxt As String, Rng As Range
Dim tempFont As String
Dim tempColour As String
Dim tempBold As String
StrTxt = "abc"
Set insp = Application.ActiveInspector
Set myObject = insp.CurrentItem
'The active inspector is displaying a mail item.
If myObject.MessageClass = "IPM.Note" And _
insp.IsWordMail = True Then
Set msg = insp.CurrentItem
'Grab the body of the message using a Word Document object.
Set myDoc = insp.WordEditor
Set mySelection = myDoc.Application.Selection
Set hed = msg.GetInspector.WordEditor
Set appWord = hed.Application
Set appRng = appWord.Selection
With mySelection.Range
With mySelection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<" & StrTxt & "*>"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.MatchCase = False
.Execute
End With
Do While .Find.Found
If .Font.Name <> "Arial" Then
tempFont = .Duplicate.Font.Name
tempColour = .Duplicate.Font.Color
tempBold = .Duplicate.Font.Bold
With .Duplicate
.Font.Size = .Font.Size + 2
.Font.Name = "Zrnic"
.Font.Bold = True
If .Text <> "" Then
Select Case Split(.Text, StrTxt)(1)
Case "telephone"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(0, 122, 135)
Case "handset"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(0, 122, 135)
Case "speaker"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(0, 122, 135)
End Select
End If
End With
End If
mySelection.Find.Execute
Loop
End With
End If
End Sub
Thought I would post my final code here that updates the changes on the fly to work in the Outlook draft email.
This could be modified for your own use case.
Paste into your ThisOutlookSession
You need to add the Word Reference library.
Function GetCurrentItem() As MailItem
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
End Select
Set objeApp = Nothing
End Function
Sub test()
Dim doc As Document
Dim myInspactor As Outlook.Inspector
Dim CurrMsg As Outlook.MailItem
Set CurrMsg = GetCurrentItem()
Set myInspector = CurrMsg.GetInspector
Set doc = myInspector.WordEditor
ABCBranding doc
End Sub
Sub ABCBranding(doc As Document)
Dim StrTxt As String, Rng As Range
Dim tempFont As String
Dim tempColour As String
Dim tempBold As String
StrTxt = "abc"
With doc.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<" & StrTxt & "*>"
.Replacement.Text = ""
.forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.MatchCase = False
.Execute
End With
Do While .Find.Found
If .Font.Name <> "Verdana" Then
tempFont = .Duplicate.Font.Name
tempColour = .Duplicate.Font.Color
tempBold = .Duplicate.Font.Bold
With .Duplicate
.Font.Name = "Arial"
.Font.Bold = True
Select Case Split(.Text, StrTxt)(1)
Case "telephone"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(0, 222, 111)
Case "handset"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(50, 200, 100)
Case "speaker"
.End = .Start + Len(StrTxt)
.Font.Color = RGB(43, 101, 412)
End Select
End With
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End Sub

VBA: Automate task in MS Word when running through Excel

I am trying to run this VBA in an excel file. The first part of this code allows me to select a file and open it. I now want to have the code search the file and format the words I ask it to. I have written this code in Word before and am now just having trouble getting it into excel. Is there a line such as "withwdapp" that tells the excel vba to perform the next set of steps in Word?
Sub Find_Key_Words()
'Open an existing Word Document from Excel
Dim FileToOpen
Dim appwd As Object
ChDrive "C:\"
FileToOpen = Application.GetOpenFilename _
(Title:="Please choose a file to import", _
FileFilter:="Word Files *.docx (*.docx),")
If FileToOpen = False Then
MsgBox "No file specified.", vbExclamation, "Error"
Exit Sub
Else
Set appwd = CreateObject("Word.Application")
appwd.Visible = True
appwd.Documents.Open Filename:=FileToOpen
End If
Dim objWord As Object, objDoc As Object, Rng As Object
Dim MyAr() As String, strToFind As String
Dim i As Long
'This holds search words
strToFind = "w1,w2, w3, w4"
'Create an array of text to be found
MyAr = Split(strToFind, ",")
Set objWord = CreateObject("Word.Application")
'Open the relevant word document : CAN THIS BE DELETED?
Set objDoc = objWord.Documents.Open("C:\Sample.docx")
objWord.Visible = True
Set Rng = objWord.Selection
'Loop through the array to get the seacrh text
For i = LBound(MyAr) To UBound(MyAr)
With Rng.Find
.ClearFormatting
.Text = MyAr(i)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Execute
Set Rng = objWord.Selection
'Change the attributes
Do Until .Found = False
With Rng.Font
.Name = "Times New Roman"
.Size = 20
.Bold = True
.Color = RGB(200, 200, 0)
End With
Rng.Find.Execute
Loop
End With
Next i
End Sub
Change your code to this.
Const wdFindContinue = 1
Sub FnFindAndFormat()
Dim FileToOpen
Dim objWord As Object, objDoc As Object, Rng As Object
Dim MyAr() As String, strToFind As String
Dim i As Long
'~~> This holds your search words
strToFind = "deal,contract,sign,award"
'~~> Create an array of text to be found
MyAr = Split(strToFind, ",")
FileToOpen = Application.GetOpenFilename _
(Title:="Please choose a file to import", _
FileFilter:="Word Files *.docx (*.docx),")
If FileToOpen = False Then Exit Sub
Set objWord = CreateObject("Word.Application")
'~~> Open the relevant word document
Set objDoc = objWord.Documents.Open(FileToOpen)
objWord.Visible = True
Set Rng = objWord.Selection
'~~> Loop through the array to get the seacrh text
For i = LBound(MyAr) To UBound(MyAr)
With Rng.Find
.ClearFormatting
.Text = MyAr(i)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Execute
Set Rng = objWord.Selection
'~~> Change the attributes
Do Until .Found = False
With Rng.Font
.Name = "Times New Roman"
.Size = 20
.Bold = True
.Color = RGB(200, 200, 0)
End With
Rng.Find.Execute
Loop
End With
Next i
End Sub

Looping through Word document to format text

I have a huge document in which the lines starting with some specific words text style should be changed. I have created an array for all those words and tried formatting the document using For loop. But only the style of first word in the array is getting changed not for all the words in the array.
Below is what I did, please have a look at it and suggest the solution:
Sub Variables_NormalTxt()
Dim oRng As Word.Range
Dim oRngFC As Word.Range
Dim varUbyteNormal As Variant
Dim ArrayItem As String
Dim i As Integer
varUbyteNormal = Array("uword", "ubyte", "bool", "sword", "const", "ulong", "static")
Set oRng = ActiveDocument.Range
i = 0
For i = 0 To UBound(varUbyteNormal)
With oRng.Find
.Text = varUbyteNormal(i)
.Font.Name = "Times New Roman"
.Font.Bold = False
.Font.size = 10
While .Execute
oRng.Select
Set oRngFC = ActiveDocument.Bookmarks("\Line").Range
oRngFC.Style = "variable normal"
Wend
End With
Next i
End Sub
Move this line
Set oRng = ActiveDocument.Range
into the For loop
i.e.
For i = 0 To UBound(varUbyteNormal)
Set oRng = ActiveDocument.Range
With oRng.Find
etc.
Incidentally...
You can remove the line
i = 0
Your For statement can be generalised to
For i = LBound(varUbyteNormal) To UBound(varUbyteNormal)
and perhaps others will suggest other improvements.
( ...a further look suggests the following, but it depends on precisley
what you are looking for)
Sub Variables_NormalTxt3()
Dim oRng As Word.Range
Dim varUbyteNormal As Variant
Dim ArrayItem As String
Dim i As Integer
varUbyteNormal = Array("uword", "ubyte", "bool", "sword", "const", "ulong", "static")
For i = LBound(varUbyteNormal) To UBound(varUbyteNormal)
Set oRng = ActiveDocument.Range
With oRng.Find
.ClearAllFuzzyOptions
.ClearFormatting
.Text = varUbyteNormal(i)
.Font.Name = "Times New Roman"
.Font.Bold = False
.Font.Size = 10
' perhaps also...
.MatchCase = False
While .Execute
oRng.Style = "variable normal"
Wend
End With
Set oRng = Nothing
Next 'i
End Sub
Dim varUbyteNormal As Variant
varUbyteNormal = Array("uword", "ubyte", "bool", "sword", "const", "ulong", "static")
Dim i As Long
For i = LBound(varUbyteNormal) To UBound(varUbyteNormal)
With ActiveDocument.Range.Find
.ClearFormatting
.ClearAllFuzzyOptions
With .Font
.Name = "Times New Roman"
.Bold = False
.Size = 10
End With
.Text = varUbyteNormal(i)
With .Replacement
.ClearFormatting
.Style = "variable normal"
End With
.Execute Replace:=wdReplaceAll
End With
Next