Finding text between font sizes in Word VBA - vba

I'm looking to find text between font sizes in Word VBA. I'm wondering if there's a better way than my code below.
It looks for the minimum font size and then iterates, incrementing by .5 until the maximum. As far as I can tell, there's no way to search for a font size range.
There's a bit of extra matching that you can ignore (it's part of a semantic-less footnote reference matching script)
Dim findResults As Scripting.Dictionary
Set findResults = CreateObject("Scripting.Dictionary")
Set contentRange = ActiveDocument.Content
' Find fonts between range
Dim min
min = 6
Dim max
max = 8
Dim currentFontSize
currentFontSize = min
Do While max >= currentFontSize
Selection.HomeKey Unit:=wdStory
Set contentRange = ActiveDocument.Content
With contentRange.Find.Font
.Size = currentFontSize
End With
With contentRange.Find.Font.Shading
.ForegroundPatternColor = wdColorAutomatic
End With
With contentRange.Find
.Text = "[0-9]{1,3}"
.MatchWildcards = True
.Wrap = wdFindStop
End With
contentRange.Find.Execute
While contentRange.Find.Found
If contentRange.Font.Position > 2 Then
Set myRange = ActiveDocument.Range(start:=contentRange.start - 10, End:=contentRange.start + Len(contentRange.Text))
findResults.Add contentRange.Text, Trim(Replace(myRange.Text, vbCr, ""))
End If
'Selection.MoveRight Unit:=wdCharacter, Count:=Len(contentRange.Text)
contentRange.Collapse wdCollapseEnd
contentRange.Find.Execute
Wend
currentFontSize = currentFontSize + 0.5
Loop

My approach would be to find all instances of the text, then test the font size within the loop. That way, you need only do two font size tests - .Font.Size > 5.5 and .Font.Size < 8.5. Try something based on:
Dim FindResults As Scripting.Dictionary, Rng As Range
Set FindResults = CreateObject("Scripting.Dictionary")
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "[0-9]{1,3}"
.Font.Shading.ForegroundPatternColor = wdColorAutomatic
.Forward = True
.MatchWildcards = True
.Wrap = wdFindStop
.Execute
End With
Do While .Find.Found = True
If .Font.Size > 5.5 Then
If .Font.Size < 9.5 Then
If .Font.Position > 2 Then
Set Rng = .Duplicate
Rng.Start = Rng.Start - 10
FindResults.Add .Text, Trim(Replace(Rng.Text, vbCr, ""))
End If
End If
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With

Related

Range.Find Word VBA: finding heading with specific heading number only works if heading style is specified

I'd like to find the location of a heading that has a specific heading number. E.g. "2.3."
For some reason, I can only find the location of the heading if i specify what Style that heading is going to be. If i don't specify the heading style then I don't get any matches (i.e. .Execute is never True).
How can I find the location of a heading without having to specify it's style?
Code that works:
Function FindHeadingPos(oRng As Word.Range) As Long
Dim rng As Word.Range
With oRng.Find
.ClearAllFuzzyOptions
.ClearHitHighlight
.ClearFormatting
.Text = ""
.Forward = True
.Wrap = 2
.Format = True
.Style = "Heading 2,H2 Numb"
Do While .Execute
'.Parent contains the found range
Set rng = .Parent
If rng.ListFormat.ListString = "2.3." Then
FindHeadingPos = rng.Start
Exit Do
End If
'below statement seems to prevent code hanging on some headings.
rng.Collapse Direction:=wdCollapseEnd
Loop
End With
End Function
Code that doesn't work:
Function FindHeadingPos(oRng As Word.Range) As Long
Dim rng As Word.Range
With oRng.Find
.ClearAllFuzzyOptions
.ClearHitHighlight
.ClearFormatting
.Text = ""
.Forward = True
.Wrap = 2
'.Format = True
'.Style = "Heading 2,H2 Numb"
Do While .Execute
'.Parent contains the found range
Set rng = .Parent
If rng.ListFormat.ListString = "2.3." Then
FindHeadingPos = rng.Start
Exit Do
End If
'below statement seems to prevent code hanging on some headings.
rng.Collapse Direction:=wdCollapseEnd
Loop
End With
End Function
Thanks #GSerg for suggesting the .ParagraphFormat.OutlineLevel property.
The code below seems to solve my problem in case it helps anyone else.
Function getParaOutlineLevel(headNumberRaw As String) As Integer
Dim numberOfDecimals As Integer
numberOfDecimals = Len(headNumberRaw) - Len(Replace(headNumberRaw, ".", ""))
If Not IsNumeric(Left(headNumberRaw, 1)) Then
getParaOutlineLevel = numberOfDecimals + 5
Else
getParaOutlineLevel = numberOfDecimals
End If
End Function
Function FindHeadingPos(oRng As Word.Range) As Long
Dim headNumber As String
Dim rng As Word.Range
headNumber = "2.3."
With oRng.Find
.ClearAllFuzzyOptions
.ClearHitHighlight
.ClearFormatting
.Text = ""
.Forward = True
.Wrap = 2
.Format = True
.ParagraphFormat.OutlineLevel = getParaOutlineLevel(headNumber)
Do While .Execute
'.Parent contains the found range
Set rng = .Parent
If rng.ListFormat.ListString = headNumber Then
FindHeadingPos = rng.Start
Exit Do
End If
'below statement seems to prevent it hanging on some headings.
rng.Collapse Direction:=wdCollapseEnd
Loop
End With
End Function

Select all pages except the 3 last ones

I am trying to select all pages of a document except the 3 last ones. My final goal is to apply a style to text who have a specific font name and a specific font size. I am receiving an error message when running the code below about my 3rd code line : "object doesn't support this property or method". Any idea what this is about? Thanks!
Sub aHeadlines()
Dim V As Integer
Dim Z As Integer
V = ActiveDocument.Information(wdNumberOfPagesInDocument)
Z = 3
Dim rgePages As Range
Selection.GoTo What:=wdGoToPage, Which:=wdGoToAbsolute, Count:=1
Set rgePages = Selection.Range
Selection.GoTo What:=wdGoToPage, Which:=wdGoToAbsolute, Count:=V - Z
rgePages.End = Selection.Bookmarks("\Page").Range.End
rgePages.Select
With Selection.Find
.ClearFormatting
.Text = ""
.Font.Size = 10
.Font.Name = "Arial"
.Font.Bold = True
With .Replacement
.ClearFormatting
.Text = ""
.Style = ActiveDocument.Styles("Heading 1")
End With
.Execute Replace:=wdReplaceAll
End With
End Sub
Way simpler:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument
With .Range(0, .Range.GoTo(What:=wdGoToPage, Which:=wdGoToAbsolute, _
Count:=.ComputeStatistics(wdStatisticPages) - 2).End - 1).Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = ""
.Font.Size = 10
.Font.Name = "Arial"
.Font.Bold = True
.Replacement.Style = wdStyleHeading1
.Execute Replace:=wdReplaceAll
End With
End With
Application.ScreenUpdating = True
End Sub
Information is a property of the Range object, not Document.
V = ActiveDocument.Range.Information(wdNumberOfPagesInDocument)
NOTE:
It is rarely necessary to select anything when working with VBA. Using the Selection object slows down your code as the cursor moves with each change of the selection which means the screen has to be redrawn each time. Instead of Selection use the appropriate object for what you are trying to do, e.g. Range, Table, Shape, etc.
Your code can be rewritten using Range as below:
Sub aHeadlines()
Dim V As Integer
Dim Z As Integer
V = ActiveDocument.Range.Information(wdNumberOfPagesInDocument)
Z = 3
Dim rgePages As Range
Set rgePages = ActiveDocument.GoTo(What:=wdGoToPage, Which:=wdGoToAbsolute, Count:=V - Z)
rgePages.End = rgePages.Bookmarks("\Page").Range.End
rgePages.Start = ActiveDocument.Range.Start
With rgePages.Find
.ClearFormatting
.Text = ""
.Font.Size = 10
.Font.Name = "Arial"
.Font.Bold = True
.Wrap = wdFindStop
With .Replacement
.ClearFormatting
.Text = ""
.Style = ActiveDocument.Styles("Heading 1")
End With
.Execute Replace:=wdReplaceAll
End With
End Sub

VBA Word: Applying Character Style to first two words of specific paragraph style

I would like to apply a character style ("Bold Italics") to the first two words of all paragraphs set in the "3 Species" style in MS Word (and later, I'd also like another macro to do same for all the words after the second tab in a different style). I know how to do all this in InDesign, but I'd like it set up in the original Word documents before they get flowed into InDesign.
I'm new at this and can't figure out how to apply it to only the first two words. I did get it to apply the character style to the whole paragraph or to a specific word in that style. It seems like it ought to be simple, but I've only learned to use find and replace type functions so far, and I imagine I will have to use the Range functions, which I don't understand yet. Thanks for any help!
Sub Add_Character_Style()
'
' Add_Character_Style Macro
'
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Style = "3 Species"
.Text = ""
.Replacement.Text = ""
.Replacement.Style = "Bold Italics"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
For example:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<*>[,. ^s^t]#<*>"
.Style = "3 Species"
.Replacement.Text = ""
.Format = True
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
End With
Do While .Find.Execute
.Style = "Bold Italics"
.Start = .Paragraphs(1).Range.End
Loop
End With
Application.ScreenUpdating = True
End Sub
Try this:
Sub Add_Character_Style()
Dim p As Paragraph
Dim doc As Document: Set doc = ActiveDocument
For Each p In doc.Paragraphs
p.Range.Select
Selection.Collapse Direction:=wdCollapseStart
Selection.MoveRight Unit:=wdWord, Count:=2, Extend:=wdExtend
With Selection
If .Style = "3 Species" Then .Style = "Bold Italic"
End With
Next p
End Sub
EDIT:
To avoid use of the Selection object (Timothy Rylatt)
Sub Add_Character_Style()
Dim p As Paragraph
Dim doc As Document: Set doc = ActiveDocument
Dim rng As Range
For Each p In doc.Paragraphs
If p.Range.Style = "3 Species" Then
Set rng = p.Range
With rng
.Collapse Direction:=wdCollapseStart
.MoveEnd Unit:=wdWord, Count:=2
.Style = "Bold Italics"
End With
End If
Next p
End Sub
FURTHER EDIT per macropod:
Sub Add_Character_Style()
Application.ScreenUpdating = False
Dim Para As Paragraph, Rng As Range
For Each Para In ActiveDocument.Paragraphs
With Para
If .Style = "3 Species" Then
If .Range.ComputeStatistics(wdStatisticWords) > 1 Then
Set Rng = .Range.Words.First
With Rng
Do While .ComputeStatistics(wdStatisticWords) < 2
.MoveEnd wdWord, 1
Loop
.Style = "Bold Italic"
End With
End If
End If
End With
Next
Application.ScreenUpdating = True
End Sub

add cross reference to number or text found using regex with numbered item macro

I have to find the text in the format or regex from the document - "([\(]){1}([0-9]){1, 2}([\)]){1}"
I want to replace the number alone found in the regex with a cross reference to the corresponding numbered item found using word macro. The only condition is that it should not take the number item with a style - "Heading1" (which has a number item to it)
For Ex: text found: "(1)" replace the text with cross reference at the number alone
The code I used throw a run time error: "Object Required".
Dim WorkPara As String
Dim CheckP() As Boolean
Dim NumPara As Integer, J As Integer
NumPara = ActiveDocument.Paragraphs.count
ReDim CheckP(NumPara)
For J = 1 To NumPara
CheckP(J) = False
WorkPara = ActiveDocument.Paragraphs(J).Range.Text
If InStr(WorkPara, regex.Pattern("([\(]){1}([0-9]){1}([\)]){1}")) > 0 Then
CheckP(J) = True
End If
Next J
For J = NumPara To 1 Step -1
If CheckP(J) Then
Selection.Range.InsertCrossReference wdRefTypeNumberedItem, wdNumberFullContext, "1"
End If
Next J
Could any one help me out with it
You don't need RegEx for this. Consider:
Sub Demo()
Application.ScreenUpdating = False
Dim Rng As Range
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "(^#)"
.Forward = True
.Format = False
.Wrap = wdFindStop
.MatchWildcards = False
.Execute
End With
Do While .Find.Found
If .Paragraphs(1).Style <> wdStyleHeading1 Then
Set Rng = .Characters(2)
With Rng
.InsertCrossReference wdRefTypeNumberedItem, wdNumberFullContext, .Text, True
End With
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Note: the above code assumes your cross-reference is to the heading with the found number.
If the bracketed numbers you want to process might be more than one digit, you could use Word's wildcard Find:
Sub Demo()
Application.ScreenUpdating = False
Dim Rng As Range
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "\([0-9]#\)"
.Forward = True
.Format = False
.Wrap = wdFindStop
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .Paragraphs(1).Style <> wdStyleHeading1 Then
Set Rng = .Duplicate
With Rng
.Start = .Start + 1
.End = .End - 1
.InsertCrossReference wdRefTypeNumberedItem, wdNumberFullContext, .Text, True
End With
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub

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