VBA - WORD Deleting rows after and before specific word - vba

I'm trying to clean up my Word document using VBA.
What i need to do is to find a specific word (usually a website) then select the line it is in and then select and then remove text line above(only 1 line), the lines under that website line as well (sometimes more than 2 - if the text is longer). I'll try to show you how the line looks now.
Something happend at someplace!
website.com 08.01.2019
Something happend at someplace and it was a bad person doing it.
He used spaces instead of tabs in his code.
TAG-important stuff
The website 99% of times doesn't show in the 1st line, so im trying to find the 2nd line.
There are other websites and texts i would like to keep (so it would skip newsbetter.com)
In every document there are about 30-100 pharagraphs like the one I've typed earlier (the ones do delete)
I've been searching on the internet for a possible solution but they usually are for Excel. I think that strings are not working for me here.
Sub ScratchMacroII()
Dim oRng As Word.Range
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "news.pl"
While .Execute
While oRng.Find.Found
oRng.Select
Selection.Expand Unit:=wdParagraph
Selection.Delete
Wend
End With
End Sub
I expected the result to delete the whole pharagraph, but it justs deletes one line and leaves the other ones. I need some pointers since I'm new at VBA.

The following code, based on the sample in the question, searches the term from the beginning to the end of the document. When found, the paragraphs following and preceding the term are deleted. The search Range is then set to the document content following the found instance so that the same instance is not picked up repeatedly.
Note that I included Find.Wrap = wdFindStop to prevent the code from cycling through the document again. It's also necessary to repeat the Execute method within the loop, rather than trying to loop on it. While...Wend is an old type of loop; preferred is Do While...Loop.
Sub ScratchMacroII()
Dim oRng As Word.Range
Dim para As Word.Paragraph
Dim found As Boolean
Set oRng = ActiveDocument.Range
With oRng.Find
.Text = "news.pl"
.wrap = wdFindStop
found = .Execute
Do While found
Set para = oRng.Next(wdParagraph, 1).Paragraphs(1)
para.Range.Delete
Set para = oRng.Next(wdParagraph, -1).Paragraphs(1)
para.Range.Delete
oRng.Collapse wdCollapseEnd
oRng.End = ActiveDocument.content.End
found = oRng.Find.Execute
Loop
End With
End Sub

Related

How do I make the last two words of each footnote bold using Word VBA?

I've changed balloon comments to footnotes, taking the author's name too. I need the author's name to be in bold but I can't get my code to read the footnotes. My problem is in setting : oFootnote
I've tried calling on the strAuthor and making that bold but because it is no longer a comment.author I can no longer set it as it's now in the footnote. I've tried many examples on the internet but I just can't get them to work:
StackOverflow's How do i make a string bold; Insert bold text into Word using VBA
also
Set oFootnote = oDoc.Footnotes.Add(Range:=Selection.Range, Text:="Some text")
I am a trainee so please don't judge me too harshly
'Convert comments to footnotes with Author name in bold
Dim i As Long
Dim oDoc As Document
dim oComment as Comments
Dim oFootnote As Footnotes
'Document is the ActiveDocument
Set oDoc = Application.ActiveDocument
'the author's name needs to be bold (the last two words in each footnote)
Set oFootnote = oDoc.Footnotes
With oFootnote
Selection.Range.Words.Last.Words (2)
'Make the last two words bold'
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Font.bold = True
End With
End With
Selection.Find.Execute
'Set oFootnote = Nothing
Next
I tried
Set oFootnote = oDoc.Footnotes Range:=Selection.Words.Last.Words(2)
but it doesn't like "Range:= onwards" so I did
Selection.Range.Words.Last.Words (2) invalid use of a property
There is usually more than one way to achieve something like this, but the key is usually to work with a dedicated Range object.
In the code below, that bases on the code in the question, the Range object is assigned to each individual Footnote object in a loop of the Footnotes. It is then collapsed to its end-point and the start extended backwards by two words. (To better understand how this works, think of selecting the footnote, pressing right-arrow, then pressing ctrl+shift+left arrow twice to select the last two words.)
Dim oDoc As Document
Dim oFootnotes As Footnotes
Dim Ftnote As Footnote
Dim rngFootnote As Word.Range
'Document is the ActiveDocument
Set oDoc = Application.ActiveDocument
'the author's name needs to be bold (the last two words in each footnote)
Set oFootnotes = oDoc.Footnotes
For Each Ftnote In oFootnotes
Set rngFootnote = Ftnote.Range
rngFootnote.Collapse wdCollapseEnd
rngFootnote.MoveStart wdWord, -2
rngFootnote.Font.Bold = True
Next
Note that the reason for one of the errors in the question is because Words.Last returns a Range object containing the last word. Since it contains only one word - the last - Words(2) can't find anything it can work with.
The reason for the other error is that it's not possible to assign a Range to a Footnote or Footnotes object. They're different things, entirely...
Not super familiar with word objects, but try this. Worked for my couple of tests.
Basically it loops through all foot notes. And uses the index of the word to set that word's bold property to true.
Sub Test()
Dim oFootNote As Footnote
Dim oLastIndex As Long
For Each oFootNote In ActiveDocument.Footnotes
oLastIndex = oFootNote.Range.Words.Count
If oLastIndex > 2 Then
oFootNote.Range.Words(oLastIndex).Bold = True
oFootNote.Range.Words(oLastIndex - 1).Bold = True
End If
Next
End Sub

Macro for Adding Text To Begining of Every Paragraph

I am trying to create a Word macro that will go through a large document that I have and add the text "SAMPLE" to the beginning of every paragraph.
The document contains a Title page, Table of Contents and Headings throughout and I would prefer none of these have the "SAMPLE" text on them, just the paragraphs.
Below is some macro code I have found on various sites and kind of pieced together to do somewhat of what I want. It does place the "SAMPLE" text at the beginning of some paragraphs but not all, usually only the first paragraph of a new section within my document. And it also places it at the end of the Table of Contents and Beginning of the Title page.
I am brand new to macros in Word so any help is appreciated or if there is a better way of doing this perhaps? There might even be some unnecessary bits in this code since it is pieced together from other samples.
Sub SAMPLE()
Application.ScreenUpdating = False
Dim Par As Paragraph, Rng As Range
For Each Par In ActiveDocument.Paragraphs
If Par.Style = "Normal" Then
If Rng Is Nothing Then
Set Rng = Par.Range
Else
Rng.End = Par.Range.End
End If
Else
Call RngFmt(Rng)
End If
If Par.Range.End = ActiveDocument.Range.End Then
Call RngFmt(Rng)
End If
Next
Application.ScreenUpdating = True
End Sub
Sub RngFmt(Rng As Range)
If Not Rng Is Nothing Then
With Rng
.End = .End - 1
.InsertBefore "SAMPLE"
End With
Set Rng = Nothing
End If
End Sub
Provided your Title, Table of Contents and Headings etc. don't use the Normal Style - as they shouldn't - you really don't need a macro for this - all you need is a wildcard Find/Replace where:
Find = [!^13]*^13
Replace = SAMPLE: ^&
and you specify the Normal Style as a Find formatting parameter. You could, of course, record the above as a macro, but that seems overkill unless you're doing this often.

What's the best way to update LINK fields with path of current document using VBA?

So I have 4 documents, 3 excel spreadsheets and 1 document. All four are in the same directory "test." All four will always remain in the same directory no matter what. However, the goal of the document is to build a report out of the three spreadsheets for multiple properties. This means that the paths would be different for every different computer that it was used on. I want a macro that will auto-update the LINK fields with the current path but I'm running into some trouble.
So far I have
SendKeys "%{F9}"
Dim path As String
path = ActiveDocument.path
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "C:\\Users\\Gianni\\Desktop"
.Replacement.Text = path
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
SendKeys "%{F9}"
There are two problems with this from what I can tell. If I just view the fields manually and run the code without the first SendKeys command, the find & replace works. With the first SendKeys command, however, the code doesn't replace the text with the new path. Still, the path that pastes ends up breaking the link anyway. How do I go about fixing these?
Often, it's better in Word to work with the underlying object model of a Word document, than trying to reproduce exactly what you do as a user. Understanding how Word works, from a user point-of-view is very important and there are many things you you're able to do by converting those steps into a macro. But digging into the object model is generally faster and more accurate.
Changing a LINK field code is one of those things - and like many things, there's more than one way to go about it. Here are two possibilities.
The first is close to how you're approaching it, by manipulating the field code. Note that it's not necessary, using VBA, to actually display the field code. The object model lets you manipulate it "behind the scenes".
This procedure loops all the Fields in the document, checks whether each is a LINK field. If it is, the alternate path is substituted in the field code for the original path using the VBA Replace function, then this is written to the field code.
'Assumes the linked Excel workbook is an inline shape
Sub ChangePathInLinkField()
Dim doc As word.Document
Dim fld As word.Field
Dim strSearchPath As String
Dim strReplacePath As String
Dim strNewFieldCode As String
Set doc = ActiveDocument
strSearchPath = "C:\\Users\\[user name]\\Documents\\SampleChart.xlsx"
strReplacePath = "C:\\Test\\SampleChart.xlsx"
For Each fld In doc.Fields
If fld.Type = wdFieldLink Then
strNewFieldCode = Replace(fld.code.Text, strSearchPath, strReplacePath)
fld.code.Text = strNewFieldCode
End If
Next
doc.Fields.Update
End Sub
The second procedure shows how the link path can be changed for Shapes as well as InlineShapes (if you have a Shape you can't see the LINK field). It can also be used only on InlineShapes, of course. This loops the collection, checks whether the object is a linked OLE object and, if it is, changes the path.
Which one to use will depend on your situation - test them both and decide based on that.
'Alternate: works with OLE object
Sub ChangePathInLinkedObject()
Dim doc As word.Document
Dim ils As word.InlineShape
Dim shp As word.Shape
Dim strReplacePath As String
Dim i As Long
Set doc = ActiveDocument
strReplacePath = "C:\Users\Cindy Meister\Documents\SampleChart.xlsx"
strReplacePath = "C:\Test\SampleChart.xlsx"
'For Each doesn't work because updating the field
'destroys the object, so it loops over the same object
'For this reason it's also necessary to work backwards through the document
For i = doc.InlineShapes.Count To 1 Step -1
Set ils = doc.InlineShapes(i)
If ils.Type = wdInlineShapeLinkedOLEObject Then
ils.LinkFormat.SourceFullName = strReplacePath
ils.LinkFormat.Update
End If
Next
For i = doc.shapes.Count To 1 Step -1
Set shp = doc.shapes(i)
If shp.Type = msoLinkedOLEObject Then
shp.LinkFormat.SourceFullName = strReplacePath
shp.LinkFormat.Update
End If
Next
End Sub
Instead of using SendKeys you can show field codes with:
ActiveDocument.ActiveWindow.View.ShowFieldCodes = True
and to show field values
ActiveDocument.ActiveWindow.View.ShowFieldCodes = False
That may help with your first problem.
To see how to implement relative paths in Word, check out the solution I've posted at:
http://windowssecrets.com/forums/showthread.php/154379-Word-Fields-and-Relative-Paths-to-External-Files
Since you're working with LINK fields, you'll need the macro solution there.

Microsoft Word VBA Macro - One Paragraph Find-Replace Styles

I am executing a style search in Microsoft Word using a VBA Macro.
My goal is to perform certain actions once for every style found in the document.
The macro works correctly on documents that have at least two paragraphs, but the macro does not alert the style correctly in a document that has exactly one paragraph in it. It seems strange that when I enter a new paragraph mark, the styles are found, even though I did not add any new text or styles to the document, just an extra blank paragraph mark. Does anyone know what is wrong with my macro and how I can fix this? Thanks for taking a look.
Sub AlertAllStylesInDoc()
Dim Ind As Integer
Dim numberOfDocumentStyles As Integer
Dim styl As String
Dim StyleFound As Boolean
numberOfDocumentStyles = ActiveDocument.styles.count
For Ind = 1 To numberOfDocumentStyles
styl = ActiveDocument.styles(Ind).NameLocal
With ActiveDocument.Content.Find
.ClearFormatting
.text = ""
.Forward = True
.Format = True
.Style = styl
Do
StyleFound = .Execute
If StyleFound = True Then
' actual code does more than alert, but keeping it simple here'
MsgBox styl
GoTo NextStyle
Else
Exit Do
End If
Loop
End With
NextStyle:
Next
End Sub
I don't understand why ActiveDocument.Content is not working, but replacing it with ActiveDocument.Range(0,0) appears to resolve the issue (tested in Word 2016).
With ActiveDocument.Range(0, 0).Find

Outlook VBA find and add link; keeps skipping first hit

I'm a long-time beneficiary of the helpful advice folks on here have offered to others (sincere thanks, everyone), but this is my first time actually posting. My VBA skills are lackluster at best.
This is driving me nuts: I have an Outlook macro that's supposed to comb through an email message before it's sent and replace citations to our policy documents, all of which have a prefix of "A&P-" with a link to that document.
It actually works great, except that it stubbornly refuses to capture citations if they're the first word in the email. So, for example, if I have a list of entries that looks like this:
A&P-I-A-1-100, A&P-II-B-2-200, A&P-III-C-3-300
the script will add links to the second and third entry (and as many more as I want to add) but skip the first one entirely. Weirdly, if I add any characters at all to the start of the email (even just hitting the space bar a couple of times) this doesn't happen. It doesn't impact citations at the start of subsequent paragraphs either. Just that first word.
Here's the code I'm using. Any help very, very appreciated!:
Sub Citation3()
Dim myInspector As Outlook.Inspector
Dim myObject As Object
Dim myItem As Outlook.MailItem
Dim rngStory As Word.Range
Dim myDoc As Word.Document
Dim mySelection As Word.Selection
Dim strItem As String
Dim strItem2 As String
Dim strLink As String
Set myInspector = Application.ActiveInspector
Set myObject = myInspector.CurrentItem
Set myDoc = myInspector.WordEditor
Set mySelection = myDoc.Application.Selection
For Each rngStory In ActiveDocument.StoryRanges
With mySelection.Find
.ClearFormatting
.Text = "A&P-*-*-[0-9]{3}"
.Replacement.Text = ""
.Wrap = wdFindContinue
.MatchWildcards = True
If mySelection.Find.Execute = True Then
While mySelection.Find.Execute
strItem = mySelection.Text
strItem2 = Replace(strItem, "A&P", "AP")
mySelection.Hyperlinks.Add Anchor:=mySelection.Range, _
Address:="http://www.google.com/" & strItem2 & "_document.shtml", _
TextToDisplay:=strItem
End If
End With
Next rngStory
End Sub
The problem lines are:
If mySelection.Find.Execute = True Then
While mySelection.Find.Execute
When they're isolated like that, you can probably see what's happening.
You're doing one Execute in the If statement which finds the first occurrence of the pattern you're looking for and then immediately do another Execute in the While loop that now finds the second occurrence of that pattern, therefore ignoring the first match completely. After that, the code loops around the While loop and picks up any remaining matches correctly.
To fix this, simply remove the If and corresponding End If lines, because you don't need them. The While loop will take care of everything.
Now, for some observations.
In your code I don't see Next statement for your For Each loop, or a End With statement for your With block, or a Wend statement for your While loop, or a End Sub for that matter. I can only assume you've cut and pasted only selected bits of your code, so I'll ignore that.
You should probably indent your code a little better to make it easier on others (and on you!) to read and identify any potential errors.
Finally, I'm a little confused by your matching pattern: "A&P-*-*-[0-9]{3}". It would work equally well as "A&P*[0-9]{3}" or "A&P-*-*-*-[0-9]{3}". In the latter, note that there are 3 dashed bits of text between the P and the 3-digit number (according to your format specification for citations), whereas your original pattern only accounted for 2 dashed bits.