I am fairly new to VBA. I tag text with heading styles in large documents from a variety of authors. Is it possible identify a number pattern on a line of bolded text, and apply the appropriate style to that entire line (there is usually a hard return at the end of the line).
For example, often our documents are numbered as shown below, and we tag the text accordingly.
1.0 text here (apply Heading 1)
1.2 text here (apply Heading 2)
1.2.1 text here (apply Heading 3)
1.2.1.1 text here (apply Heading 4)
2.0 text here (apply Heading 1)
2.2 text here (apply Heading 2)
….and so on
I have done a lot of research, but I am not sure if this is possible. We do not use any type of auto numbering.
Yes, it's possible. Try this code:
Sub ApplyHeadings()
Dim rg1 As Range
Dim rg2 As Range
Dim pos As Long
Dim i As Long
Dim dots As Long
Set rg1 = ActiveDocument.Range
With rg1.Find
.MatchWildcards = True
.Text = "[0-9.]{2,}[!^13]#[^13]"
.Wrap = wdFindStop
While .Execute
Set rg2 = rg1.Duplicate
dots = 0
' isolate the numbering
pos = InStr(rg2.Text, " ")
If pos > 0 Then rg2.End = rg2.Start + pos - 1
For i = 1 To Len(rg2.Text)
' count the dots in the number
If Mid(rg2.Text, i, 1) = "." Then dots = dots + 1
Next i
' apply correct heading level
Select Case dots
Case 1
If Mid(rg2.Text, 3, 1) = "0" Then
rg1.Style = ActiveDocument.Styles("Heading 1")
Else
rg1.Style = ActiveDocument.Styles("Heading 2")
End If
Case 2, 3 ' maybe more...
rg1.Style = ActiveDocument.Styles("Heading " & CStr(dots + 1))
Case Else
' do nothing
End Select
' prepare for next find
rg1.Collapse wdCollapseEnd
Wend
End With
End Sub
Related
Greeting to all Members and Experts, I am trying to automate
the formatting process in word. The formatting is done by applying styles. But before applying styles I need to trim extra spaces between characters of serial numbers, for example, 1. a. i. and insert tabs after dot(.) and then apply the style. I have attached a sample document. Plz have a look. I have tried to get the desired result by using the following code but it doesn't get the work done
I am new here so i dont know how to attach sample files so, here is the link for sample file. https://docs.google.com/document/d/1Z1dB6tvPKVrxHlw7qV8VNyiy49c5lRZN/edit?usp=sharing&ouid=101706223056224820285&rtpof=true&sd=true
Any help or suggestion would be of great help. Thanks in advance...
Sub formatts()
Dim a As Integer
Dim i As Integer, n As Long, para As Paragraph, rng As Range, doc As Document
Set doc = ActiveDocument
With doc
For i = 1 To .Range.Paragraphs.Count
For n = 1 To doc.Paragraphs(i).Range.Characters.Count
If .Paragraphs(i).Range.Characters(n).Text = " " Or .Paragraphs(i).Range.Characters(n).Text = Chr(9) Or .Paragraphs(i).Range.Characters(n).Text = Chr(160) Then
.Paragraphs(i).Range.Characters(n).Select
'This line checks whether the first character is whitespace character or not and delete it.
doc.Paragraphs(i).Range.Characters(n).Delete
ElseIf .Paragraphs(i).Range.Characters(n).Text = "." Then
.Paragraphs(i).Range.Characters(n).InsertAfter (vbTab)
n = n + 1
a = a + 1
ElseIf .Paragraphs(i).Range.Characters(n).Text Like "[a-z]." And .Paragraphs(i).Range.Characters(n).Next.Next.Text <> "i" Then
Exit For
End If
If a >= 3 Then Exit For
Next
For n = 1 To doc.Paragraphs(i).Range.Characters.Count
If .Paragraphs(i).Range.Characters(n).Text = "i" And .Paragraphs(i).Range.Characters(n).Next.Text = "." And .Paragraphs(i).Range.Characters(n).Next.Next.Text = " " Then
doc.Range.Paragraphs(i).Style = "shh"
Exit For:
ElseIf .Paragraphs(i).Range.Characters(n).Text = "a" Or .Paragraphs(i).Range.Characters(n).Text = "b" Or .Paragraphs(i).Range.Characters(n).Text = "c" And .Paragraphs(i).Range.Characters(n).Next.Text = "." And .Paragraphs(i).Range.Characters(n).Next.Next.Text = " " Then
doc.Range.Paragraphs(i).Style = "sh"
Exit For
End If
Next
Next
End With
End Sub
I currently have a cope snippet that allows me to extract the first 6 characters of a filename to insert in the right of a document footer and the file title (not including extension) in the left of the footer. It was all based on character position and had served its purpose. However, a complexity has been introduced.
Our previous file naming structure was solely "###### - [Title]" (where we had 6 digits, a space, dash, a space, a title). We now have additional file names of the format "######.## - [TITLE]". I don't believe I can rely solely on character position to achieve extraction and insertion. I'm looking for some assistance in how I might be able to setup the code to determine whether the 7th character is a decimal or a space and proceed accordingly with inserting ##### versus ######.## into the footer. The flip side would also be true where I would need to determine the actual title (not relying on the position since it would be dependent on the first case.
Any assistance is appreciated. Below is the current code. It might not be the cleanest, but it gets the job done:
Sub FooterFields(myFooterHL, myTotalPageCount, myFooterBold)
sTitle = ActiveDocument.Name
J = InStrRev(sTitle, ".")
If J > 0 Then
sTitle = Left(sTitle, J - 9)
If Len(sTitle) > 5 Then
sTitle = Left(sTitle, 9)
End If
Dim specTitle As String
Dim specTitle2 As String
Dim specTitleInt As String
specTitle = ActiveDocument.Name
If Right(specTitle, 5) = ".docx" Then
specTitleInt = Left(specTitle, Len(specTitle) - 5)
specTitle2 = Right(specTitleInt, Len(specTitleInt) - 9)
ElseIf Right(specTitle, 4) = ".doc" Then
specTitleInt = Left(specTitle, Len(specTitle) - 4)
specTitle2 = Right(specTitleInt, Len(specTitleInt) - 9)
Else
End If
sDiv = ActiveDocument.Name
K = InStrRev(sDiv, ".")
If K > 0 Then
sDivIntermediate = Right(sDiv, K - 6)
sDivFinal = specTitle2
If Len(sDiv) > 5 Then
sDivIntermediate = Right(sDiv, K - 6)
sDivFinal = specTitle2
End If
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveWindow. _
ActivePane.View.Type = wdOutlineView Then
ActiveWindow.ActivePane.View.Type = wdPrintView
End If
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
Selection.WholeStory
Selection.Delete
Selection.Font.AllCaps = True
With Selection
.Range.Text = sTitle
.Range.InsertAlignmentTab wdRight, wdMargin
.EndKey Unit:=wdLine
.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:="PAGE ",
PreserveFormatting:=True
If myTotalPageCount = vbYes Then
.TypeText Text:="/"
.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty,
Text:="NUMPAGES ", PreserveFormatting:=True
Else
End If
.HomeKey Unit:=wdLine
.Range.Text = sDivFinal
End With
PageNumberAlignment:=wdAlignPageNumberRight, FirstPage:=True
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
Else
MsgBox "Document has no filename extension."
End If
End If
End Sub
I would suggest you consider using regular expressions for this. (The link is for using regular expressions in VBA hosted under Excel, but most of the information applies to VBA hosted under Word as well.)
A short introduction to regular expressions:
Define a pattern
Find one or more matches to the pattern in a string
You could use the following pattern to match all the variations:
^\d{6}(?:\.\d{2}) - .*(?:\.doc|\.docx)$
Add a reference (Tools -> References...) to the Microsoft VBScript Regular Expressions 5.5 library. Then you can use something like the following:
Sub FooterFields2(myFooterHL, myTotalPageCount, myFooterBold)
Dim re As New RegExp
re.Pattern = "^(\d{6}(?:\.\d{2})) - (.*)(?:\.doc|\.docx)$"
re.IgnoreCase = True
Dim matches As MatchCollection
Set matches = re.Execute(ActiveDocument.Name)
If matches.Count = 0 Then
MsgBox "Document name doesn't match"
Exit Sub
End If
Dim match As match
Set match = matches(0)
Dim code As String, title As String
code = match.SubMatches(0)
title = match.SubMatches(1)
'insert code and title in the appropriate location
End Sub
Explanation
\d -- matches a single digit character
\d{6} -- matches exactly 6 digits
\. -- matches a .. Because the . is a part of regular expression syntax, it has to be escaped with a \
\.\d{2} -- matches a . followed by (as before) exactly two digits
(?:\.\d{2}) -- groups \.\d{2} so we can apply an operator. Grouping with (?: (as opposed to with () does not store the value within the group to be referenced separately
(?:\.\d{2})?-- matches zero or one instances of (?:\.\d{2}), because the title might have the decimal and two successive digits, or it might not
- .* -- matches a space, a dash, and a space, followed by any number (*) of any character (.)
\.doc|\.docx -- matches either .doc or .docx
(?:\.doc|\.docx) -- groups together the different variants of the extension, but doesn't save the extension for further use
In order to extract the digits and the title after we've matched against the regular epression, we need to use capturing groups, which are indicated by parentheses -- (). In this case we want the numeric code (first capturing group) and the title (second capturing group):
(\d{6}(?:\.\d{2})) - (.*)(?:\.doc|\.docx)
I have cells in a sheet that include a bunch of text, but also have certain text within square brackets that look like this:
[Assign: some text here]
[Select: some text here]
I need a macro that will change the color of any text starting with Assign to green (including Assign) and any text starting with Select to blue (also including Select). Brackets themselves could be color changed or not, whatever is easiest.
I have tried multiple ways to do this but cannot figure out with a regex or a replace how to do this. Closest I have come was uppercasing all text within [] brackets but not making a distinction between Assign or Select.
Appreciate the help
Edit:
What I have so far:
Sub test()
Dim r As Range
Dim m As Object
Dim test As Range
Dim strInput As String
With CreateObject("VBScript.RegExp")
.Global = True
.IgnoreCase = True
.Pattern = "\[(.*?)\]"
For Each r In Range("C2:C2")
If .test(r.Value) Then
For Each m In .Execute(r.Value)
r.Value = Replace(r.Value, m.Value, UCase(m.Value))
Next
End If
Next
End With
End Sub
Range(SomeRange).Characters(start,length).Font.Color = vbGreen
To get your start and length, use Instr
start = Instr(1, Range(SomeRange).Value, "[Assign", vbTextCompare)
length = Instr(start, Range(SomeRange).Value, "]", vbTextCompare) - start + 1
If start is zero then string not found.
--
UPDATE:
Off top of my head, for multiple instances in the same cell:
start = 1
Do
start = Instr(start, Range(SomeRange).Value, "[Assign", vbTextCompare)
If start > 0 Then
length = Instr(start, Range(SomeRange).Value, "]", vbTextCompare) - start + 1
if length > 1 then Range(SomeRange).Characters(start, length).Font.Color = vbGreen
start = start + length
End If
Loop While start > 0
The following code works fine for finding exact duplicate paragraphs within a Word document. It ignores paragraphs shorter than min_chars length but I also want it to ignore paragraphs that are of a certain style.
So can someone help me with the syntax to add 'or if left(paragraph style, 3) <> "XXX" ' to the first If statement?
Many thanks!
ReDim Para_text(1 To Para_count) 'i.e. to last paragraph in document
For Para_num = 1 To Para_count
Para_text(Para_num) = ActiveDocument.Paragraphs(Para_num).range.Text
Next Para_num
For Para_A = 1 To Para_count
For Para_B = Para_A + 1 To (Para_count - 1)
'Ignore paragraphs < min_chars characters in length (entered on user form, default 100)
If Para_text(Para_A) Like "**" Or Para_text(Para_B) Like "**" Or Len(Para_text(Para_A)) < Form_min_chars_box Or Len(Para_text(Para_B)) < Form_min_chars_box Then
Else
If Para_text(Para_A) = Para_text(Para_B) Then
ActiveDocument.Paragraphs(Para_A).range.Select
Page_A = Selection.Information(wdActiveEndPageNumber)
ActiveDocument.Paragraphs(Para_B).range.Select
Page_B = Selection.Information(wdActiveEndPageNumber)
' Add a comment at this found location:
Call Repeat_Comment(Count_repeats, Para_A, Para_B, Page_A, Page_B)
End If
End If
Next Para_B
Next Para_A
Sub Repeat_Comment(Count_repeats As Integer, Para_A As Integer, Para_B As Integer, Page_A As Integer, Page_B As Integer)
'Adds a comment whenever a duplicate paragraph is found
Count_repeats = Count_repeats + 1
Selection.Paragraphs(1).range.Characters(1).Select
With ActiveDocument.Comments.Add(Selection.range, "This paragraph is also on page " & Page_A)
.Initial = "Repeat "
.Author = "Repeated"
End With
End Sub
I have some word documents that have custom heading styles.
I would like to iterate through all custom headings in a document, and replace the custom style with the standard heading style.
For example:
Custom Style Standard Style
=================== ==============
Heading 1. Numbered --> Heading 1
Heading 2. Numbered --> Heading 2
Heading 3. Numbered --> Heading 3
and so on up to Heading 5 ...
I am using MS Word 2007.
Question: how can I do this with VBA?
This worked for me:
Sub Macro1()
Dim DocPara As Paragraph
For Each DocPara In Application.ActiveDocument.Paragraphs
If DocPara.Range.Style Is Nothing Then
' do nothing
Else
Dim I As Integer
Dim H As String
For I = 1 To 5
H = "Heading " + CStr(I) + ". Numbered"
If Left(DocPara.Range.Style, Len(H)) = H Then
DocPara.Range.Style = "Heading " + CStr(I)
End If
Next I
End If
Next
End Sub
Code adapted from: https://stackoverflow.com/a/276397/1033422