Searching for Text in Header Section of A Word Document - vba

I am trying to confirm if a document contains some text, the only problem is this text is in the Header. This is the code I am using which constantly returns false even though the text exists:
Set CurrentDoc = Documents.Open("a.doc")
With CurrentDoc.Sections(1).Headers(wdHeaderFooterFirstPage).Range.Find
.Text = "This is the text to find"
.Forward = True
.Execute
If (.Found = True) Then Debug.Print "Match"
End With
The following also doesn't seem to work (I assume .Content doesn't include header/footers):
With CurrentDoc.Content.Find
.Text = "This is the text to find"
.Forward = True
.Execute
If (.Found = True) Then Debug.Print "Match"
End With
Any help would be greatly appreciated.

You're probably trying to search in the wrong section/headertype. You could try this code:
Dim rng As Range
Dim intSecCount As Integer
Dim intHFType As Integer
intSecCount = ActiveDocument.Sections.Count
For intSection = 1 To intSecCount
With ActiveDocument.Sections(intSection)
For intHFType = 1 To 3
Set rng = ActiveDocument.Sections(intSection).Headers(intHFType).Range
rng.Find.Execute findtext:="This is the text to find", Forward:=True
If rng.Find.Found = True Then
Debug.Print "Match"
End If
Next intHFType
End With
Next intSection

I found the answer on this site and it's a lot more complex than initially thought: http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm
The following code is from the site above, in addition to searching the entire document it includes text replace functionality:
Public Sub FindReplaceAnywhere()
Dim rngStory As Word.Range
Dim pFindTxt As String
Dim pReplaceTxt As String
Dim lngJunk As Long
Dim oShp As Shape
pFindTxt = InputBox("Enter the text that you want to find.", "FIND" )
If pFindTxt = "" Then
MsgBox "Cancelled by User"
Exit Sub
End If
TryAgain:
pReplaceTxt = InputBox( "Enter the replacement." , "REPLACE" )
If pReplaceTxt = "" Then
If MsgBox( "Do you just want to delete the found text?", vbYesNoCancel) = vbNo Then
GoTo TryAgain
ElseIf vbCancel Then
MsgBox "Cancelled by User."
Exit Sub
End If
End If
'Fix the skipped blank Header/Footer problem
lngJunk = ActiveDocument.Sections( 1 ).Headers( 1 ).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case WdStoryType.wdEvenPagesHeaderStory, _
WdStoryType.wdPrimaryHeaderStory, _
WdStoryType.wdEvenPagesFooterStory, _
WdStoryType.wdPrimaryFooterStory, _
WdStoryType.wdFirstPageHeaderStory, _
WdStoryType.wdFirstPageFooterStory
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
End Sub
Public Sub SearchAndReplaceInStory(ByVal rngStory As Word.Range, ByVal strSearch As String , ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
End Sub

Related

Add Page Number To Footer

I've got a bunch of documents that I need to add page numbering in the footer.
I tried writing a macro to do this but after I run there's still no page numbers (in header or footer)
Sub AddPageNumberToFooter()
Call DeleteExistingFooters
With ActiveDocument
.PageSetup.DifferentFirstPageHeaderFooter = False
.Sections(1).Footers(wdHeaderFooterPrimary).PageNumbers.Add
End With
End Sub
Sub DeleteExistingFooters()
Dim iSectionCnt As Integer
iSectionCnt = ActiveDocument.Sections.Count
If iSectionCnt > 0 Then
ActiveDocument.Sections(iSectionCnt).Footers(wdHeaderFooterPrimary).Range.Delete
End If
End Sub
What am I missing?
The following code will add Page #s to all documents lacking them in every page in the selected folder:
Sub UpdateDocumentFooters()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String
Dim wdDoc As Document, Sctn As Section, HdFt As HeaderFooter
strFolder = GetFolder: If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> ThisDocument.FullName Then
Set wdDoc = Documents.Open(FileName:=strFolder & "\" & strFile, _
AddToRecentFiles:=False, Visible:=False)
With wdDoc
For Each Sctn In .Sections
For Each HdFt In Sctn.Footers
With HdFt
If .Exists Then
If Sctn.Index = 1 Then
Call AddPgFld(HdFt)
ElseIf .LinkToPrevious = False Then
Call AddPgFld(HdFt)
End If
End If
End With
Next
Next
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDoc = Nothing
Application.ScreenUpdating = True
End Sub
Sub AddPgFld(HdFt As HeaderFooter)
Dim Fld As Field, bFld As Boolean
With HdFt
bFld = False
For Each Fld In .Range.Fields
If Fld.Type = wdFieldPage Then
bFld = True: Exit For
End If
Next
If bFld = False Then
With .Range.Paragraphs.Last.Range
If Len(.Text) > 2 Then .InsertAfter vbCr
End With
With .Range.Paragraphs.Last.Range
.Text = "Page "
.Fields.Add Range:=.Characters.Last, Type:=wdFieldEmpty, Text:="PAGE", PreserveFormatting:=False
.ParagraphFormat.Alignment = wdAlignParagraphCenter
End With
End If
End With
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
As you are writing that you have a bunch of documents: Could it be that ActiveDocument isn't the correct reference.
This works for me - you can replace ActiveDocument from the test-sub with any other document:
Option Explicit
Sub testPagenumbersForActiveDocument()
dim docToTest as Word.Document
set docToTest = ActiveDocument 'replace ActiveDocument with another doc you have opened
deleteExistingPageNumbers docToTest
addPageNumberToFooter docToTest
End Sub
Sub addPageNumberToFooter(doc As Word.Document)
With doc
.PageSetup.DifferentFirstPageHeaderFooter = False
.Sections(1).Footers(wdHeaderFooterPrimary).PageNumbers.Add
End With
End Sub
Sub deleteExistingPageNumbers(doc As Word.Document)
Dim sec As Section, pn As PageNumber
For Each sec In doc.Sections
For Each pn In sec.Footers(wdHeaderFooterPrimary).PageNumbers
pn.Delete
Next
Next
End Sub
The delete-sub only deletes PageNumbers - this is safer then your version as that will delete the whole footer-text ... which might be not what you want.

Run Time Error '91': Object variable or With block variable not set Catalogue Mailmerge

I'm trying out the tutorial from macropod for using a directory for a mailmerge, but I keep getting an error which I don't understand.
I've gotten to the last step in the tutorial and I wanted to try out the actual e-mail merge. I created a macro with the code below in the Catalog/Directory mailmerge main document and saved the document in the same folder as the 'Email Merge Main Document'. But now when I run the macro RunMerge I get the error
Run Time Error '91': Object variable or With block variable not set
When I click on debug it highlights the first .Paragraphs(1).Range.Delete in Sub EmailMergeTableMaker(DocName As Document). This is the first time I've had to do anything with VBA and I have no idea how to solve this.
What does the error mean? I'm guessing the line references a variable which isn't set right, but I just copied the code from the tutorial and I don't know which variable is being referenced.
Edit: this is the link to the tutorial http://www.gmayor.com/Zips/Catalogue%20Mailmerge.zip
Sub RunMerge()
Application.ScreenUpdating = False
Dim Doc1 As Document, Doc2 As Document, Doc3 As Document, StrDoc As String
Set Doc1 = ThisDocument
StrDoc = ThisDocument.Path & "\EmailDataSource.doc"
If Dir(StrDoc) <> "" Then Kill StrDoc
With Doc1.MailMerge
If .State = wdMainAndDataSource Then
.Destination = wdSendToNewDocument
.Execute
Set Doc2 = ActiveDocument
End If
End With
Call EmailMergeTableMaker(Doc2)
With Doc2
.SaveAs FileName:=StrDoc, AddToRecentFiles:=False, FileFormat:=wdFormatDocument
StrDoc = .FullName
.Close
End With
Set Doc2 = Nothing
Set Doc3 = Documents.Open(FileName:=Doc1.Path & "\Email Merge Main Document.doc", _
AddToRecentFiles:=False)
With Doc3.MailMerge
.MainDocumentType = wdEMail
.OpenDataSource Name:=StrDoc, ConfirmConversions:=False, ReadOnly:=False, _
LinkToSource:=True, AddToRecentFiles:=False, Connection:="", SQLStatement:="", _
SQLStatement1:="", SubType:=wdMergeSubTypeOther
If .State = wdMainAndDataSource Then
'.Destination = wdSendToNewDocument
.Destination = wdSendToEmail
.MailAddressFieldName = "Recipient"
.MailSubject = "Monthly Sales Stats"
.MailFormat = wdMailFormatPlainText
.Execute
End If
End With
Doc3.Close SaveChanges:=False
Set Doc3 = Nothing
Application.ScreenUpdating = True
End Sub
Sub EmailMergeTableMaker(DocName As Document)
Dim oTbl As Table, i As Integer, j As Integer, oRow As Row, oRng As Range, strTxt As String
With DocName
.Paragraphs(1).Range.Delete <---- this line
Call TableJoiner
For Each oTbl In .Tables
j = 2
With oTbl
i = .Columns.Count - j
For Each oRow In .Rows
Set oRng = oRow.Cells(j).Range
With oRng
.MoveEnd Unit:=wdCell, Count:=i
.Cells.Merge
strTxt = Replace(.Text, vbCr, vbTab)
On Error Resume Next
If Len(strTxt) > 1 Then .Text = Left(strTxt, Len(strTxt) - 2)
End With
Next
End With
Next
For Each oTbl In .Tables
For i = 1 to j
oTbl.Columns(i).Cells.Merge
Next
Next
With .Tables(1)
.Rows.Add BeforeRow:=.Rows(1)
.Cell(1, 1).Range.Text = "Recipient"
.Cell(1, 2).Range.Text = "Data"
End With
.Paragraphs(1).Range.Delete
Call TableJoiner
End With
Set oRng = Nothing
End Sub
Private Sub TableJoiner()
Dim oTbl As Table
For Each oTbl In ActiveDocument.Tables
With oTbl.Range.Next
If .Information(wdWithInTable) = False Then .Delete
End With
Next
End Sub

Do a simple calculation in word using VBA

I have many documents i need to edit, i have the Version of the document in the Header like "Version #" these documents have different versions, but are all a single integer value. These versions need to +1 so i need to get the number then just add 1 then save.
This is seeming pretty tricky and im not sure its possible. Any Help would be appreciated.
For example.
Old Document
"Version 2"
New Edit
"Version 3"
I can find and replace as i have learned from here.
Try:
Sub UpdateVersions()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String, strDocNm As String
Dim wdDoc As Document, wdSctn As Section, wdHdFt As HeaderFooter
strDocNm = ActiveDocument.FullName
strFolder = GetFolder: If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> strDocNm Then
Set wdDoc = Documents.Open(FileName:=strFolder & "\" & strFile, AddToRecentFiles:=False, Visible:=False)
With wdDoc
For Each wdSctn In .Sections
With wdSctn
For Each wdHdFt In .Headers
With wdHdFt
If .LinkToPrevious = False Then
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "Version [0-9]{1,}"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Execute
End With
Do While .Find.Found = True
.Text = "Version " & Split(.Text, " ")(1) + 1
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End If
End With
Next
End With
Next
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDoc = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
This is a quick hack that may do what you wish.
First of all, make sure that you have the Scripting Runtime referenced in the Tools>Project>References menu. Secondly, I have understood that you have more than one document so this lot does everything in a folder.
I have just assumed, for this example, that the folder name is fixed. In Real Life you can modify the code to select the folder and then modify the code to go through sub-folders, but this is (a) a quick hack and (b) out of scope.
Public Sub IncreaseVersionNumbers()
' Make sure that the "Microsoft Scripting Runtime" library is enabled in the Tools>Projects>References
Dim sRootFolder As String
Dim oFSO As Scripting.FileSystemObject
Dim oFolder As Scripting.Folder
Dim oFile As Scripting.File
sRootFolder = "C:\_Documents\VersionNumberTest\" ' You can grab this by a Folder Selection dialog box instead
Set oFSO = New Scripting.FileSystemObject
Set oFolder = oFSO.GetFolder(sRootFolder)
For Each oFile In oFolder.Files
If InStr(1, oFile.Name, ".doc", vbTextCompare) > 0 Then
ProcessDocument (sRootFolder & oFile.Name)
End If
Next oFile
End Sub
Private Sub ProcessDocument(sDocument As String)
Dim oDoc As Word.Document
Dim oSection As Word.Section
Dim oRange As Range
Dim sHeaderText As String
On Error Resume Next
Set oDoc = Documents.Open(sDocument)
For Each oSection In oDoc.Sections
Set oRange = oSection.Headers(wdHeaderFooterPrimary).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Set oRange = oSection.Headers(wdHeaderFooterFirstPage).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Set oRange = oSection.Headers(wdHeaderFooterEvenPages).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Next oSection
oDoc.Close wdSaveChanges
End Sub
Private Sub ProcessHeaderRange(oRange As Range)
Dim sText As String, sNewText As String
Dim nPosn As Long, nStart As Long, nEnd As Long
Dim sVersion As String, nVersion As Long
sText = oRange.Text & " "
nPosn = InStr(1, sText, "Version", vbTextCompare)
If nPosn > 0 Then
nStart = InStr(nPosn, sText, " ")
If nStart > 0 Then
nStart = nStart + 1
nEnd = InStr(nStart, sText, " ")
If nEnd > 0 Then
sVersion = Mid$(sText, nStart, nEnd - nStart)
nVersion = Val(sVersion)
nVersion = nVersion + 1
sNewText = Left$(sText, nStart - 1) & Trim$(Str$(nVersion)) & " " & Right$(sText, Len(sText) - nEnd)
sNewText = Left$(sNewText, Len(sNewText) - 1)
oRange.Text = sNewText
End If
End If
End If
End Sub
This is, as I say, a quick hack so it may not work perfectly but, as always, have backups!
This works by going through each of the three possible headers in each possible section of the document. And if it finds a header in a section then it does what you say.
And this version does go above single digit version numbers. But it's a quick hack, as I say and so needs extra work to make it really bullet-proof. Having said that, it's a reasonable start I would think.
Hope that this helps,
Malc

Using VBA code how to extract Non HTML data content residing under each heading from a word document

How to extract text and non text data content (ex: Tables, pictures) associated with each heading irrespective of heading style?
With below code I am able to reach out to each header, post that I am failing to extract content associated with that heading:
Option Explicit
Sub Main()
Dim strFile As String
Dim oWord As Word.Application
Dim oWdoc As Word.Document
Dim oPar As Word.Paragraph
Dim rng As Word.Range
strFile = "C:\Users\SQVA\Desktop\My_Work\MyTest3.docx"
'Set oWord = CreateObject("Word.Application")
Set oWord = New Word.Application
Set oWdoc = oWord.Documents.Open(strFile)
Call Get_Heading_Name(oWord, oWdoc, strFile, rng)
Call Close_Word(oWord, oWdoc)
End Sub
Sub Get_Heading_Name(oWord As Word.Application, oWdoc As Word.Document, strFile As String, rng As Word.Range)
oWord.Visible = True
Dim astrHeadings As Variant
Dim strText As String
Dim intItem As Integer
Set rng = oWdoc.Content
astrHeadings = _
oWdoc.GetCrossReferenceItems(wdRefTypeHeading)
For intItem = LBound(astrHeadings) To UBound(astrHeadings)
strText = Trim$(astrHeadings(intItem))
'Debug.Print CStr(strText)
'Debug.Print astrHeadings(intItem).
Dim my_String As String
Dim intLevel
If CStr(strText) <> "" Then
my_String = Right(strText, Len(strText) - InStr(strText, " "))
intLevel = GetLevel(CStr(astrHeadings(intItem)))
' Call GetHeadingNextText(oWdoc, my_String)
' Debug.Print my_String
' Debug.Print intLevel
' rng.Style = "Heading " & intLevel
Dim sTextSearch() As String
Dim StrHdTxt1
Dim nStart As Long, nEnd As Long, n As Long, k As Long
Dim wdTable
Dim wdTbl As Word.Table, wdCell As Word.cell, wdCellRng As Word.Range
Dim wdIshp As Word.InlineShape, wdShp As Word.Shape, StrHdTxt As String
oWdoc.Range(0, 0).Select
With oWord.Selection.Find
.Style = oWdoc.Styles("Heading " & intLevel)
.Text = my_String
If .Execute Then
'Debug.Print "Found"
Call SelectHeadingandContent(oWdoc, oWord)
End If
End With
End If
Next intItem
End Sub
Sub Close_Word(oWord As Word.Application, oWdoc As Word.Document)
oWdoc.Close SaveChanges:=wdDoNotSaveChanges
oWord.Quit
Set oWdoc = Nothing
Set oWord = Nothing
End Sub
Private Function GetLevel(strItem As String) As Integer
' Return the heading level of a header from the
' array returned by Word.
' The number of leading spaces indicates the
' outline level (2 spaces per level: H1 has
' 0 spaces, H2 has 2 spaces, H3 has 4 spaces.
Dim strTemp As String
Dim strOriginal As String
Dim longDiff As Integer
' Get rid of all trailing spaces.
strOriginal = RTrim$(strItem)
' Trim leading spaces, and then compare with
' the original.
strTemp = LTrim$(strOriginal)
' Subtract to find the number of
' leading spaces in the original string.
longDiff = Len(strOriginal) - Len(strTemp)
GetLevel = (longDiff / 2) + 1
End Function
Sub SelectHeadingandContent(oWdoc As Word.Document, oWord As Word.Application)
Dim headStyle 'As Style
' Checks that you have selected a heading. If you have selected multiple paragraphs,checks only the first one. If you have selected a heading, makes sure the whole paragraph is selected and records the style. If not, exits the subroutine.
If oWdoc.Styles(oWord.Selection.Paragraphs(1).Style).ParagraphFormat.OutlineLevel < wdOutlineLevelBodyText Then
Set headStyle = oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Style
oWord.Selection.Expand wdParagraph
Else: Exit Sub
End If
' Turns off screen updating so the the screen does not flicker.
Application.ScreenUpdating = False
' Loops through the paragraphs following your selection, and incorporates them into the selection as long as they have a higher outline level than the selected heading (which corresponds to a lower position in the document hierarchy). Exits the loop if there are no more paragraphs in the document.
Dim My_Text As String
My_Text = ""
Do While oWdoc.Styles(oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Next.Style).ParagraphFormat.OutlineLevel > headStyle.ParagraphFormat.OutlineLevel
'Debug.Print oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Range.Text
oWord.Selection.MoveEnd wdParagraph
' Debug.Print oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Range.Text
My_Text = My_Text + vbCr + oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Range.Text
If oWord.Selection.Paragraphs(oWord.Selection.Paragraphs.Count).Next Is Nothing Then Exit Do
Loop
Debug.Print My_Text
' Turns screen updating back on.
Application.ScreenUpdating = True
End Sub
You can loop through all the Heading1 ranges and their 'non-text' objects, as you call them, with code like:
Sub Read_Heading_Contents()
Dim wdApp As New Word.Application, wdDoc As Word.Document, wdRng As Word.Range
Dim wdTbl As Word.Table, wdCell As Word.Cell, wdCellRng As Word.Range
Dim wdIshp As Word.InlineShape, wdShp As Word.Shape, StrHdTxt As String
Const strFile As String = "C:\Users\SQVA\Desktop\My_Work\MyTest3.docx"
With wdApp
.Visible = True
Set wdDoc = .Documents.Open(Filename:=strFile, ReadOnly:=True, AddToRecentFiles:=False, Visible:=False)
With wdDoc
With .Range
With .Find
.Style = wdStyleHeading1
.Text = ""
.Wrap = wdFindStop
.Execute
End With
If .Find.Found = False Then
MsgBox "No 'Heading 1' style found."
Else
Do While .Find.Found = True
StrHdTxt = .Duplicate.Text: MsgBox StrHdTxt
Set wdRng = .Duplicate.GoTo(What:=wdGoToBookmark, Name:="\HeadingLevel")
For Each wdTable In .Tables
With wdTbl
For Each wdCell In .Range.Cells
Set wdCellRng = wdCell.Range
wdCellRng.End = wdCellRng.End - 1
MsgBox wdCellRng.Text
Next
End With
Next
For Each wdIshp In wdRng.InlineShapes
With wdIshp
If Not .TextEffect Is Nothing Then
MsgBox .TextEffect.Text
End If
End With
Next
For Each wdShp In wdRng.ShapeRange
With wdShp
If Not .TextFrame Is Nothing Then
MsgBox .TextFrame.TextRange.Text
End If
End With
Next
.Collapse wdCollapseEnd
.Find.Execute
Loop
End If
End With
.Close SaveChanges:=wdDoNotSaveChanges
End With
.Quit
End With
Set wdRng = Nothing: Set wdDoc = Nothing: Set wdApp = Nothing
End Sub
The above code includes message boxes to display the heading names and whatever it finds in the heading range's 'non-text' content. I'll leave it to you to turn the textbox output into whatever else you want it to be. Of course, not all inline & floating shapes have text; the loops find those, too, but I have no idea how you intend to 'read' those.

Find and replace in Word a referenced array from Excel

I wrote the following macro to scan through a PPT document and find/replace a range of words on a referenced excel sheet. This works more or less exactly how I'd like it to. I'm now attempting to set this up for use with Word documents as well, but am having some trouble with the "Word" syntax as it differs a bit. Can anyone help me get started here?
Maybe there's a better way to do this - I wrote it in this manner because it allows any user to open the Excel document, click a button, pull up their document and have the macro do its work.
Sub QE_US()
'VARIABLES
Dim PowerPointApp As PowerPoint.Application
Dim myPresentation As PowerPoint.presentation
Dim fnd As Variant
Dim rplc As Variant
Dim FindArray As Variant
Dim ReplaceArray As Variant
Dim TxtRng As PowerPoint.TextRange
Dim TmpRng As PowerPoint.TextRange
Dim sld As PowerPoint.Slide
Dim shp As PowerPoint.Shape
Dim objPPT As Object
'PROMPT USER TO OPEN POWERPOINT DOC
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
AppActivate Application.Caption
strFileToOpen = Application.GetOpenFilename _
(Title:="Please Choose PowerPoint for QE - US Conversion")
If strFileToOpen = False Then
MsgBox "No file selected.", vbExclamation, "Sorry!"
GoTo Ending
End If
objPPT.Presentations.Open Filename:=strFileToOpen
'PULLING ARRAY FROM EXCEL
FindArray = Application.Transpose(ThisWorkbook.Worksheets("Conversion").Range("C3:C64"))
ReplaceArray = Application.Transpose(ThisWorkbook.Worksheets("Conversion").Range("B3:B64"))
'LOOP THROUGH EACH SLIDE
For Each sld In objPPT.ActivePresentation.Slides
objPPT.Activate
objPPT.ActiveWindow.View.GotoSlide sld.SlideIndex
For y = LBound(FindArray) To UBound(FindArray)
For Each shp In sld.Shapes
fnd = FindArray(y)
rplc = ReplaceArray(y)
If shp.HasTextFrame Then
If shp.TextFrame.HasText Then
Set TxtRng = shp.TextFrame.TextRange.Find(fnd, 0, True, WholeWords:=msoFalse)
If TxtRng Is Nothing Then GoTo NextTxtRng
TxtRng.Select
AppActivate Application.Caption
If MsgBox("Replace " & fnd & " with " & rplc & "?", vbYesNo + vbSystemModal) = vbYes _
Then Set TmpRng = TxtRng.Replace(FindWhat:=fnd, _
ReplaceWhat:=rplc, WholeWords:=False, MatchCase:=True)
End If
End If
'REPLACE OTHER INSTANCES
Do While Not TmpRng Is Nothing
Set TmpRng = TxtRng.Replace(FindWhat:=fnd, _
ReplaceWhat:=rplc, WholeWords:=False, MatchCase:=False)
Loop
'IF TEXT RANGE IS NOTHING (NO VALUE FOUND)
NextTxtRng:
Next shp
Next y
Next sld
AppActivate Application.Caption
MsgBox "QE replaced with US"
'IF NO POWERPOINT SELECTED
Ending:
End Sub
I imagine it can be simplified quite a bit as it's no longer looking through slides, shapes, etc and can just scan the entire document?
Using http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm as a starting point:
Sub ReplaceInWord()
Dim wdApp As New Word.Application, wdDoc As Word.Document, c As Range
wdApp.Visible = True
Set wdDoc = wdApp.Documents.Open("C:\Users\twilliams\Desktop\test.docx")
For Each c In ActiveSheet.Range("C3:C64")
If c.Value <> "" Then
FindReplaceAnywhere wdDoc, c.Value, c.Offset(0, -1).Value
End If
Next c
wdDoc.Close True
End Sub
Public Sub FindReplaceAnywhere(doc As Word.Document, pFindTxt As String, pReplaceTxt As String)
Dim rngStory As Word.Range
Dim lngJunk As Long
Dim oShp As Shape
'Fix the skipped blank Header/Footer problem
lngJunk = doc.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In doc.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, _
pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
End Sub
Public Sub SearchAndReplaceInStory(ByVal rngStory As Word.Range, _
ByVal strSearch As String, ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
End Sub
Thanks for pointing me in the right direction. Below is the resulting working code.
Sub US_QE_Word()
'VARIABLES
Dim rngXL As Range
Dim x As Range
Dim strFind As String
Dim strReplace As String
Dim rngStory As Object
Dim lngJunk As Long
Dim objWord As Object
'PROMPT USER TO OPEN DOC
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
AppActivate Application.Caption
strFileToOpen = Application.GetOpenFilename _
(Title:="Please Choose File for US - QE Conversion")
If strFileToOpen = False Then
MsgBox "No file selected."
GoTo Ending
End If
objWord.Documents.Open Filename:=strFileToOpen
'FIND/REPLACE
objWord.ActiveDocument.TrackRevisions = True
Set rngXL = ThisWorkbook.Worksheets("List").Range("B3:B80")
For Each rngStory In objWord.ActiveDocument.StoryRanges
For Each x In rngXL
strFind = x.Value
strReplace = x.Offset(0, 1).Value
With rngStory.Find
.Text = strFind
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next
Next
AppActivate Application.Caption
MsgBox ("US replaced with QE. Please review changes.")
'IF NO FILE SELECTED
Ending:
End Sub