vba word macro to put a string to an existing Heading - vba

i am attempting to write a macro that with find/replace a string and than move it to an existing heading. The original text is like this:
1. Heading 1
ID: abcd
1.1 Heading 2
ID: abcd
And it should look like:
1.Heading 1 abcd
1.1 Heading 2 abcd
I am having some problems with the code i tried to write, mostly because i am kinda new, but this is what i created so far:
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Style = "Heading 2"
With Selection.Find
.Text = "abcd"
.Replacement.Text = "abcd^p"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
The text is not so important because i managed to replace with what i want but i don't know how to align it with the Heading style.. Thanks
EDIT: I hope i don't screw up again, sorry big :). So i have raw which is the raw text and i want to process it to look like this final. I already found out, thanks to you how to replace the text, it's just that i stuck in the raw version. Thanks, I kinda own you a beer, or two
LATER EDIT: So i have 5 types of Heading formats, 1. Heading 1, 1.1 Heading 2 etc till 5, and all of them have below them an ID, each with a specific number, but the name is the same, ID ASD_PC_AWP_[XXXX]. I just have to get rid of ID ASD_PC_ and put AWP_[xxxx] at same level of the Heading eg: 1.Heading 1 AWP_[xxxx1] ** , **2. Heading 2 AWP_[xxx2]...

Try:
Sub Demo()
Application.ScreenUpdating = False
Dim Rng As Range
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "ID:*^13"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
Set Rng = .Duplicate.GoTo(What:=wdGoToBookmark, Name:="\HeadingLevel")
Rng.End = Rng.Paragraphs.First.Range.End - 1
Rng.InsertAfter Split(Split(.Duplicate.Text, ":")(1), vbCr)(0)
.Text = vbNullString
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub

Do a wildcard find for any paragraph marker which is followed by ID:.
.Text = "^13ID:"
.Replacement.Text = ""
You will need to specify the style of the replacement text to the heading style because when you delete the paragraph marker at the end of the Heading paragraph you will also delete the style information for the heading paragraph.
You will need to do this with every style heading followed by the ID: text.
Updated 2018-11-01
The following code should work. I got some hints from Macropods ingeneous code.
Update 2 2018-11-01
Revised to work with a list of styles defined by user at OPs request
Sub ConsolidateHeadingWithID()
Const HEADINGS As String = "Heading 1,Heading 2,Heading 3,Heading 4,Heading 5,Other style,another style"
Dim my_headings As Variant
Dim my_heading As Variant
my_headings = Split(HEADINGS, ",")
For Each my_heading In my_headings
With ActiveDocument.StoryRanges(wdMainTextStory)
With .Find
.ClearFormatting
.format = True
.Text = ""
.Style = my_heading
.MatchWildcards = True
.Wrap = wdFindStop
.Execute
End With
Do While .Find.Found
If .Duplicate.Next(unit:=wdWord).Text = "ID" Then
.Duplicate.Next(unit:=wdParagraph).Style = my_heading
End If
.Collapse wdCollapseEnd
.MoveStart unit:=wdCharacter, Count:=2
.Find.Execute
Loop
End With
With ActiveDocument.Range.Find
.ClearFormatting
.format = True
.Text = "(^13)(ID:)(*)(AWP_)([0-9]{1,})"
.Style = my_heading
.Replacement.Text = " [\4\5]"
.MatchWildcards = True
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next
End Sub

Related

Interacting with a document without using selection

I have a transliteration function (from cyrillic to latin). I will use this function in a unviersal subroutine (with text of any lenght). This sub must to copy the source text, transliterate (from cyrillic to latin) and paste it below without any formatting changes and without using selection. The next step is reverse transliteration (again copy and paste below). There must be 3 textes in the final. I kinda know how to realize it, but i don't know what i should use instead of selection.
*
P.S. i tried use For Each word In ActiveDocument.Range.Words but it works bad with reverse transliteration (exactly that. without it, the function works perfectly in debugging)
P.P.S. sorry for mistakes in the text, i'm not a native speaker
Since you haven't posted any actual transliteration code, I'll leave you to add the cyrillic and latin character sets to the code below:
Sub Transliterate()
Application.ScreenUpdating = False
Dim p As Long, i As Long, StrLng1, StrLng2
'Insert the character codes for the cyrillic characters here
StrLng1 = Array(ChrW(&H430), ChrW(&H431), ChrW(&H432))
'Insert the corresponding latin characters here
StrLng2 = Array("a", "b", "c")
With ActiveDocument.Range
Do While .Characters.Last.Previous = vbCr
.Characters.Last.Previous.Delete
Loop
.InsertAfter vbCr
'Duplicate Content
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Wrap = wdFindContinue
.MatchWildcards = True
.Text = "^13"
.Replacement.Text = "^l"
.Execute Replace:=wdReplaceAll
.Font.Bold = True
.Text = "[!^l]#^l"
.Replacement.Text = "^p^&"
.Execute Replace:=wdReplaceAll
.ClearFormatting
.Text = "^l^13"
.Replacement.Text = "^p"
.Execute Replace:=wdReplaceAll
.Execute Replace:=wdReplaceAll
.Text = "[!^13]#^13"
.Replacement.Text = "^&^&^p"
.Execute Replace:=wdReplaceAll
End With
.Characters.Last.Previous.Delete
.Characters.First.Delete
'Loop through duplicated paragraphs
For p = .Paragraphs.Count - 1 To 2 Step -3
With .Paragraphs(p).Range
.Font.Italic = True
'Transliterate paragraph
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Wrap = wdFindStop
.MatchWildcards = False
.MatchCase = True
.Font.Bold = False
For i = 0 To UBound(StrLng1)
.Text = StrLng1(i)
.Replacement.Text = StrLng2(i)
.Execute Replace:=wdReplaceAll
Next
End With
'Duplicate translated paragraph
.Characters.Last.Next.FormattedText = .FormattedText
End With
Next
.Characters.Last.Previous.Delete
'Loop through duplicated paragraphs
For p = .Paragraphs.Count To 3 Step -3
With .Paragraphs(p).Range
.Font.Underline = wdUnderlineSingle
'Reverse Transliterate paragraph
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Wrap = wdFindStop
.MatchWildcards = False
.Font.Bold = False
.MatchCase = True
For i = 0 To UBound(StrLng1)
.Text = StrLng2(i)
.Replacement.Text = StrLng1(i)
.Execute Replace:=wdReplaceAll
Next
End With
End With
Next
End With
Application.ScreenUpdating = True
End Sub

Macro to convert intext notes to endnotes in MS Word

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

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

Ensure Replace Text function only looks at a specific Word table VBA

I have a Word table where I apply a routine that replaces paragraph marks with a comma and a space. However, in doing so there is now some text like '..., There...' and my client wanted to replace the Upper Case to Lower Case as much as possible.
So, I wrote some secondary code that I call from the previous routine as follows:
Sub LowerCaseAfterComma()
With Selection.Find
.ClearFormatting
.Text = ", ([A-Z])"
.Forward = True
.Wrap = wdFindStop
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
While .Found
Selection.Range.Case = wdLowerCase
Selection.Collapse Direction:=wdCollapseEnd
.Execute
Wend
End With
End Sub
Although this identifies the instances of Upper Case characters in the table and replaces them accordingly, the code then looks for all other instances outside the table in the document, which I don't want the code to do. I have tried using the Range object in Word for the table I want edited but haven't been successful in the syntax needed.
NB. I have problems in ensuring the editing stays within the specific table. There can be a differing number of tables prior to the one I wish to edit so
ActiveDocument.Tables() specifying the number of the table doesn't seem to work.
I am sure I doing some basically wrong and the code just needs a little tinkering. However, I am just a novice developer learning.
Try
Sub Demo()
Application.ScreenUpdating = False
Dim Rng As Range
With ActiveDocument.Tables(1)
Set Rng = .Range
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ", ([A-Z])"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
If .InRange(Rng) Then
.Case = wdLowerCase
Else
Exit Do
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End With
Application.ScreenUpdating = True
End Sub

Inserting a Space Before and Italicized Word

I have a document in Word which contains hundreds of the Italicized words that have no space in between themselves and the previous word.
For example:
The quickbrown fox jumps over the lazydog.
The result I am looking for is:
The quick brown fox jumps over the lazy dog.
I've been trying to construct a macro using the Find and replace and .InsertBefore to solve this issue for me but with no success.
This is the code I have so far.
Sub FindItalics()
Selection.Find.ClearFormatting
Selection.Find.Font.Italic = True
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
InsertBefore
End Sub
Sub InsertBefore()
With Selection
.InsertBefore " "
End With
End Sub
I have found that this works and does what I require, however it only does it for the first italicized word in the document and will not continue throughout the rest of the document.
I think you can do this without VBA:
In Word's Find/Replace turn on search with wildcards, search for Format, Font..., Italic and search for the pattern (*>).
The * means find anything,
the > means find to the end of the word, and
the () parentheses will create a autonumbered group when the pattern is matched.
In the Replace box, don't change the format and Replace with text: <space>\1 to insert a space followed by group #1.
This worked for me:
Sub FindItalics()
Dim rng As Range
Set rng = Selection.Range
With rng.Find
.Text = ""
.Replacement.Text = ""
.ClearFormatting
.Wrap = wdFindStop
.Format = True
.Font.Italic = True
.MatchWholeWord = False
.Forward = True
While .Execute
'Note: 'rng' is now the range containing the matched content
rng.InsertBefore " "
rng.Collapse wdCollapseEnd
Wend
End With
End Sub