I am trying to prompt every paragraph after every image in an active document. For some reason, the prompt pops up empty.
Sub Example1()
Dim intCount As Integer
Dim i As Integer
Dim strCaption As String
'loop through inline shapes
For i = 1 To ActiveDocument.InlineShapes.Count
'check if the current shape is an picture
If ActiveDocument.InlineShapes.Item(i).Type = wdInlineShapePicture Then
strCaption = Selection.Paragraphs(1).Range
MsgBox strCaption
End If
Next i
End Sub
This code might work, depending upon how your InlineShapes are positioned. The code presumes that each picture is in its own paragraph and then picks out the next.
Sub Example1()
Dim i As Integer
Dim strCaption As String
Dim Rng As Range
With ActiveDocument.InlineShapes
'loop through inline shapes
For i = 1 To .Count
With .Item(i)
'check if the current shape is a picture
If .Type = wdInlineShapePicture Then
Set Rng = .Range.Paragraphs(1).Range
With Rng
Do
.Collapse wdCollapseEnd
.MoveEnd wdParagraph
Loop While Len(Trim(.Text)) = 1 And _
.End < .Document.Content.End
strCaption = Rng.Text
End With
MsgBox strCaption
End If
End With
Next i
End With
End Sub
If the text you're after is in the same paragraph as the inlineshape you could use code like:
Sub Demo()
Dim iSHp As InlineShape, Rng As Range
For Each iSHp In ActiveDocument.InlineShapes
Set Rng = iSHp.Range.Paragraphs(1).Range
With Rng
.Start = iSHp.Range.End
MsgBox .Text
End With
Next
End Sub
If the text you're after is in the next paragraph after the inlineshape you could use code like:
Sub Demo()
Dim iSHp As InlineShape, Rng As Range
For Each iSHp In ActiveDocument.InlineShapes
Set Rng = iSHp.Range.Paragraphs(1).Range
With Rng
.Collapse wdCollapseEnd
.MoveEnd wdParagraph, 1
MsgBox .Text
End With
Next
End Sub
Related
I am trying to import some word documents as footer with the following code. Unfortunately, the selection.insertfile function inserts additionally a new line at the end of the footer. Is it possible to remove it? I've tried many things, without a result.
Public Sub AutoOpen()
'Fußzeile aktualisieren
Call UpdateFooter
End Sub
'Fußzeile für alle Seiten editieren
Sub UpdateFooter()
Application.ScreenUpdating = False
Dim oDoc As Word.Document, oSec As Word.section, rng As Word.Range
Set oDoc = ActiveDocument
For Each oSec In oDoc.Sections
Set rng = oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterFirstPage).Range
AddFooterToRange rng
'oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterFirstPage).Range.Font.Size = 5
Set rng = oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Range
AddFooterToRange rng
'oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Range.Font.Size = 5
Set rng = oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterEvenPages).Range
AddFooterToRange rng
'oSec.Footers(Word.WdHeaderFooterIndex.wdHeaderFooterEvenPages).Range.Font.Size = 5
Next oSec
Application.ScreenUpdating = True
End Sub
'Fußzeilendatei einfügen
Private Sub AddFooterToRange(rng As Word.Range)
With rng
.InsertFile "...fusszeile.docx"
End With
End Sub
Thanks in advance.
You just need to delete the last paragraph in the footer.
Private Sub AddFooterToRange(rng As Word.Range)
With rng
.InsertFile "...fusszeile.docx"
.Paragraphs.Last.Range.Delete
End With
End Sub
I am looking to search for a specified word or phrase in a presentation and then add a comment to all slides where it appears. I have the below code which works well, however I want to be be able to search for text boxes that are in groups (the below code only searches in text boxes)
Any suggestions would be really appreciated.
Sub FindWordAndAddComment()
Dim sld As Slide
Dim shp As Shape
Dim txtRng As TextRange, rngFound As TextRange
Dim i As Long, n As Long
Dim TargetList
'enter or word phrase here
TargetList = Array("this is a test")
For Each sld In Application.ActivePresentation.Slides
For Each shp In sld.Shapes
If shp.HasTextFrame Then
Set txtRng = shp.TextFrame.TextRange
For i = 0 To UBound(TargetList)
Set rngFound = txtRng.Find(TargetList(i))
Do While Not rngFound Is Nothing
n = rngFound.Start + 1
With sld.Comments.Add(12, 12, "found", "me", "'this is a test' has been found")
Set rngFound = txtRng.Find(TargetList(i), n)
End With
Loop
Next
End If
Next
Next
End Sub
This assumes that all groups have the default "Group" name:
Dim sld As Slide
Dim shp As Shape
Dim txtRng As TextRange, rngFound As TextRange
Dim i As Long, n As Long
Dim TargetList(2) As String
Sub FindWordAndAddComment()
'enter or word phrase here
TargetList(0) = "This is a test"
TargetList(1) = "This is a text"
TargetList(2) = "Here we go"
For Each sld In Application.ActivePresentation.Slides
For Each shp In sld.Shapes
If InStr(shp.Name, "Group") <> 0 Then
For X = 1 To shp.GroupItems.Count
If shp.GroupItems(X).HasTextFrame Then
Set txtRng = shp.GroupItems(X).TextFrame.TextRange
FindTextAddComment
End If
Next X
Else
If shp.HasTextFrame Then
Set txtRng = shp.TextFrame.TextRange
FindTextAddComment
End If
End If
Next
Next
End Sub
Sub FindTextAddComment()
For i = 0 To UBound(TargetList)
Set rngFound = txtRng.Find(TargetList(i))
Do While Not rngFound Is Nothing
n = rngFound.Start + 1
With sld.Comments.Add(12, 12, "found", "me", "'this is a test' has been found")
Set rngFound = txtRng.Find(TargetList(i), n)
End With
Loop
Next
End Sub
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.
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
I have a procedure which updates all fields in a document.
However I would like to skip the wdFieldDocVariable, the item index should be Type.
Public Sub MyApplicationUpdate()
hdWriteInfoLog ("BEGIN MACRO: MyApplicationUpdate")
Dim oTOC As TableOfContents
Dim oField As Field
' Update Fields in all document StoryRanges
Dim oStory As Range
For Each oStory In ActiveDocument.StoryRanges
oStory.Fields.Update
If oStory.StoryType <> wdMainTextStory Then
While Not (oStory.NextStoryRange Is Nothing)
Set oStory = oStory.NextStoryRange
oStory.Fields.Update
Wend
End If
Next oStory
Set oStory = Nothing
' Update all TablesOfContents
For Each oTOC In ActiveDocument.TablesOfContents
oTOC.Update
Next oTOC
hdWriteInfoLog ("END MACRO: MyApplicationUpdate")
End Sub
I think, I have found the answer, I believe there is a more efficient way of doing this, but at least it works...
' Test procedure
Public Sub MyApplicationUpdate()
hdWriteInfoLog ("BEGIN MACRO: MyApplicationUpdate")
Dim oTOC As TableOfContents
Dim oField As Field
Dim oField2 As Field
' Update Fields in all document StoryRanges
Dim oStory As Range
For Each oStory In ActiveDocument.StoryRanges
For Each oField2 In oStory.Fields
If Not oField2.Type = wdFieldDocVariable Then
oField2.Update
End If
Next oField2
If oStory.StoryType <> wdMainTextStory Then
While Not (oStory.NextStoryRange Is Nothing)
Set oStory = oStory.NextStoryRange
' oStory.Fields.Update
For Each oField2 In oStory.Fields
If Not oField2.Type = wdFieldDocVariable Then
oField2.Update
End If
Next oField2
Wend
End If
Next oStory
Set oStory = Nothing
' Update all TablesOfContents
For Each oTOC In ActiveDocument.TablesOfContents
oTOC.Update
Next oTOC
hdWriteInfoLog ("END MACRO: MyApplicationUpdate")
End Sub