I'm trying to copy all inline shapes from a word document to excel sheet.
The Word Document has multiple pages, with multiple tables with images in them.
The code I'm using is:
Sub imageExtract()
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Dim shpCurr As InlineShape
Dim i As Long
Set wrdApp = CreateObject("Word.Application")
Set wrdDoc = wrdApp.Documents.Open("C:\Temp\01.docx")
For Each shpCurr In wrdDoc.InlineShapes
shpCurr.Range.CopyAsPicture
Sheet10.Range("A" & i).PasteSpecial
i = i + 1
Next shpCurr
End Sub
Can someone explain to me why it is working for all the shapes in the first page of the Word document, and doesn't work for the shapes from another pages?
wrdDoc.InlineShapes.Count shows the real number of the shapes in the doc, so the loop is compleate
I've tried to cut and paste each shape to the first page before .CopyAsImage, with no sucsess.
I also tried to loop through each table and reference to the table's inline shapes ( "wrdDoc.tbl.InlineShapes"), with no sucsess.
If I manualy move a picture from (let's say) Page2 to Page1 and run the code again, this picture is copied.
If the problem is not the initial setting of the variable i, as I have mentioned in my comment above, then maybe you should try this code because not all shapes in a Word document are necessarily InlineShapes. The definition of InlineShapes in Word is they reside on their own paragraph. The other possibility for Shapes in a Word document are they have wrapping text and are anchored to some other place in the document. The significance here for InlineShapes and Floating Shapes is they each have to be referenced separately.
Of course you have mentioned that the InlineShapes count matches to what you expect but ... who knows ... maybe try this:
Sub imageExtract()
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Dim iShp As Word.InlineShape, shp As Word.Shape
Dim i As Long
Set wrdApp = CreateObject("Word.Application")
Set wrdDoc = wrdApp.Documents.Open("C:\Temp\01.docx")
If wrdDoc.Shapes.Count > 0 Then
For i = 1 To wrdDoc.Shapes.Count
Set shp = wrdDoc.Shapes(i)
shp.ConvertToInlineShape
Next
End If
If wrdDoc.InlineShapes.Count > 0 Then
For i = 1 To wrdDoc.InlineShapes.Count
Set iShp = wrdDoc.InlineShapes(i)
iShp.Range.CopyAsPicture
Sheet10.Range("A" & i).PasteSpecial
Next
End If
End Sub
UPDATE
After you sent me the files I was able to figure out that the problem is with Excel's PasteSpecial and if executed too many times an error 1004 PasteSpecial method of Range class failed because for some unknown reason something clears the clipboard and attempting to paste an empty clipboard generates the error.
I altered your code to use Word's Selection method to copy the images versus a Range method that was in your original code and that took care of the problem ... strange but it works. I also added some other code so that Word is properly closed out when the routine ends.
Sub imageExtract()
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Dim shpCurr As Word.InlineShape
Dim i As Long
On Error GoTo errHandler
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
Set wrdDoc = wrdApp.Documents.Open(ThisWorkbook.Path & "\01.docx")
i = 1
wrdDoc.Activate
Debug.Print wrdDoc.InlineShapes.Count
'On Error Resume Next
For Each shpCurr In wrdDoc.InlineShapes
shpCurr.Select
wrdApp.Selection.CopyAsPicture
Sheet10.Range("A" & i).PasteSpecial xlPasteAll
i = i + 1
Next
'the following is copying only one character which will clear the clipboard
'and prevent the message about wanting to save the last thing copied
wrdApp.Selection.EndKey wdStory
wrdApp.Selection.MoveStart wdCharacter, -1
wrdApp.Selection.Copy
wrdDoc.Close SaveChanges:=wdDoNotSaveChanges
Set wrdDoc = Nothing
wrdApp.Quit
Set wrdApp = Nothing
MsgBox "Complete"
Exit Sub
errHandler:
MsgBox Err.Number & Chr(32) & Err.Description, vbCritical
wrdDoc.Close SaveChanges:=wdDoNotSaveChanges
wrdApp.Quit
Set wrdApp = Nothing
End Sub
Related
Hi I have a code (see below) that is working like a charm to find and copy text from a specific style and paste it in another document. It is in an excel file because I preferred this option to share with friends that would only need to click in the button, chose the input file and save as their preferred output file name.
Now I'm trying without success to perform the same task with text highlighted in a specific color (e. Turquoise). Please find below the code that is working with a specific word or style, I made some experiences with code I found here and there, but all I could get was to copy all highlighted text instead of my choice of color. See below. Any help is much appreciated.
Note on Edit: The code below is the closer I get to the desired result. It was a little chaotic due to my try and error attempts.
' Objects
Dim wrdApp, objWord As Object
Dim wrdDoc, newwrdDoc As Object
Dim myPath As String, myPath1 As String
Dim folderPath As String
Dim myFile As String
Dim numberStart As Long
Dim Rng, srchRng As Excel.Range
'Dim objDoc As Document, objDocAdd As Document
Dim objRange As Range
Dim strFindColor As String
Dim highliteColor As Variant
Dim i As Long
' Close MS Word if it's already opened
On Error Resume Next
Set objWord = GetObject(, "Word.Application")
If Not objWord Is Nothing Then
objWord.Quit SaveChanges:=0
Set objWord = Nothing
End If
'Defining input file name
myFile = Application.GetOpenFilename()
'Open MS Word
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
' Folder Location
myPath = Application.ThisWorkbook.Path & "\"
' Input File
Set wrdDoc = wrdApp.Documents.Open(myFile)
' Output File
Set newwrdDoc = wrdApp.Documents.Add
myPath1 = Application.GetSaveAsFilename(FileFilter:="Word files(*.docx),*.docx")
' Text you want to search
'Dim FindWord As String
'Dim result As String
'FindWord = ""
highliteColor = Array(wdTurquoise)
'Style
'mystyle = wdTurquoise
'Defines selection for Word's find function
wrdDoc.SelectAllEditableRanges
' Find Functionality in MS Word
For i = LBound(wdTurquoise) To UBound(wdTurquoise)
objDoc.Activate
Selection.HomeKey Unit:=wdStory
objRange.Collapse wdCollapseEnd
With wrdDoc.ActiveWindow.Selection.Find
.HighlightColorIndex = wdTurquoise
.Highlight = True
.Forward = True
.Wrap = wdFindStop
objRange = Selection.Range
objDocAdd.Range.InsertAfter objRange & vbCr
Selection.Collapse wdCollapseEnd
End With
Next
' Execute find method
wrdDoc.ActiveWindow.Selection.Find.Execute
' Store Selected text
result = wrdDoc.ActiveWindow.Selection.Text
' Check if result contains non-blank text
If Len(result) > 1 Then
' -------------------------------------------------------------
' Loop through multiple find content (Find All functionality)
' -------------------------------------------------------------
While wrdDoc.ActiveWindow.Selection.Find.Found
wrdDoc.ActiveWindow.Selection.Copy
'Activate the new document
newwrdDoc.Activate
'New Word Doc
Set Rng = newwrdDoc.Content
Rng.Collapse Direction:=wdCollapseEnd
Rng.Paste
'Word Document
wrdDoc.Activate
wrdDoc.ActiveWindow.Selection.Find.Execute
Wend
' If style not found
Else
MsgBox "Text Not Found"
End If
'Close and don't save application
wrdDoc.Close SaveChanges:=False
'Save As New Word Document
newwrdDoc.SaveAs myPath1
newwrdDoc.Close SaveChanges:=True
'Close all word documents
wrdApp.Quit SaveChanges:=0
'Message when done
MsgBox "Task Accomplished"
End Sub
Hello stackoverflow community.
What I'm doing until now, is I manually copy a price from the word document, which I previously open, and paste it into an Excel sheet.
It is the only .docx file opened at the time on computer, so we just need to find the price in currently opened word file.
I'd like U to help me automate this task.
This picture shows the part of the document from where I copy the price.
In this example it's 605.000. But I don't know the price before I check it in the word file.
The word file is a place where I learn what the price is.
The selected text occurs only once in the whole document therefore I need VBA to copy what's after "brutto w kwocie " and up to the first coma.
Yes - only the amount of money without decimal values, because they're always ,00.
But not only seven signs, because if I had apartment price 1.250.000 then the macro that copies only 7 signs wouldn't work.
Sub Find_Price()
'Variables declaration
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
Dim TextToFind As String
Dim ApartmentPrice As String
Dim Rng As Word.Range
Application.ScreenUpdating = False
'This is the text I'm looking for in .ActiveDocument
TextToFind = "brutto w kwocie "
'Start Word and create an object
'Set WordApp = CreateObject("Word.Application")
'Reference already opened Word document from excel VBA console
Set WordApp = GetObject(, "Word.Application")
WordApp.Application.Visible = True
Set Rng = WordApp.ActiveDocument.Content
'Set WordDoc = WordApp.ActiveDocument 'I don't know how to finish this line
Rng.Find.Execute FindText:=TextToFind, Forward:=True
'what this "Forward:=True" means??
If Rng.Find.Found Then
If Rng.Information(wdWithInTable) Then
'I don't know how to write this part of the code.
'Please don't remove my question again - I've researched 16h for this info.
MsgBox "Price is " & ApartmentPrice & " pln."
End If
Else
MsgBox "Apartment price was not found!"
End If
Set ws = ActiveSheet 'currently opened sheet on currently opened.xlsm file
ws.Range("E27").Activate
ws.Paste
End Sub
Then I need to strip the number from this ridiculous dot in the middle of the amount, so please help me clear 605.000 into 60500 or 1.250.000 into 1250000.
When I have this number (the price) in my clipboard, I need to paste it into currently opened excel file, into .activesheet (because the name of the excel file and excel sheet will change many times a day).
But the destination cell will always be E27 - it will never change.
Thank you guys for all the help.
EDIT 24.01.2020
This is the above mentioned code amended by me to my best abilities.
Sub Find_Corrected()
'Variables declaration
'Dim WordApp As Object
Dim WordApp As Word.Application
'Dim WordDoc As Object
Dim WordDoc As Word.Document
Dim TextToFind As String
Dim ApartmentPrice As String
Dim Rng As Word.Range
Application.ScreenUpdating = False
'This is the text I'm looking for in .ActiveDocument
TextToFind = "brutto w kwocie "
'Start Word and create an object
'Set WordApp = CreateObject("Word.Application")
'Reference already opened Word document from excel VBA console
Set WordApp = GetObject(, "Word.Application")
Set WordDoc = WordApp.ActiveDocument
Set Rng = WordApp.ActiveDocument.Content
WordApp.Application.Visible = True
'Set WordDoc = WordApp.Documents.Open(FilePath & "Form1.docx")
'Set WordDoc = WordApp.ActiveDocument 'I don't know how to finish this line :-(
Rng.Find.Execute FindText:=TextToFind, Forward:=True
'what this "Forward:=True" means??
With Rng.Find
.Text = "brutto w kwocie "
.Execute
If .Found = True Then
Rng.MoveEnd wdWord, 3
Rng.Copy
MsgBox "Copied value equals " & Rng.Value & " Roesler conquers."
Else
MsgBox "Requested range was not found!"
End If
End With
'Set ws = ActiveSheet ' currently opened sheet on currently opened.xlsm file
'ws.Range("E27").Activate
'ws.Paste
End Sub
And this is the error it returns.
You can use the same method that I used in an answer to another of your questions.
Create a range, set it equal to the whole document, search along the range, move until your desired stop range, then move the start of the range up to your numbers.
Dim srchRng as Range
Set srchRng = ActiveDocument.Content
With srchRng.Find
.Text = "brutto w kwocie "
.Execute
If .Found = True Then
Dim numberStart as Long
numberStart = Len(srchRng.Text) + 1
srchRng.MoveEndUntil Cset:=","
Dim myNum as String
myNum = Mid(srchRng.Text, numberStart)
End If
End With
I have an excel file which composed of data and on a separate sheet, i create a graphs(bar, line, and doughnut). I used paste special from my created graphs in excel into my powerpoint so that it will be linked. Can someone tell me what will be the syntax to update those other slides?Thanks
This is my code and it is working only on the first slide of my presentation.
Sub Refresh(ParamArray var() As Variant)
Dim pApp As Object
Dim pPreso As Object
Dim pSlide As Object
Dim sPreso As String
sPreso = "/Users/USER/Desktop/company/Presentation1.pptx"
On Error Resume Next
Set pApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set pApp = CreateObject("PowerPoint.Application")
pApp.Visible = True
End If
On Error Resume Next
Set pPreso = pApp.Presentations(sPreso)
If Err.Number <> 0 Then
Set pPreso = pApp.Presentations.Open(Filename:=sPreso)
End If
Dim varSize As Integer
Dim i As Integer
varSize = UBound(var) - LBound(var) + 1
For i = 0 To (varSize - 1)
pPreso.Slides(1).Shapes(var(i)).LinkFormat.Update
Next i
End Sub
When I close the application for both excel and ppt, and then reopen it again, when I try to edit on my excel file,only the first slide in the ppt is automatically updated, I want to update all the slides in my powerpoint presentation.
I think You should run through all slides, maybe like this:
Dim sld
For Each sld In pPreso.Slides
For i = 0 To (varSize - 1)
sld.Shapes(Var(i)).LinkFormat.Update
Next i
Next sld
I have very minimal knowledge about VBA but still learning as it goes.
I've been using bookmarks in the word in order to populate data from excel. However, due to the content that some data need to repeat in a document, I tried using Text Form Field/Bookmark and REF Field to duplicate the same data.
The problem came in when once I populated data to the word, the text form field/bookmark disappear which causes REF Field unable to track the data that was referred to, hence, the "Error! Reference source not found."
In conclusion, what I'm trying to do is to populate data from excel to a locked word document and at the same time to retain Text Field Form/Bookmark in order to let REF field to track and duplicate the same data.
Is there any way to retain the Text Field Form/Bookmark placeholder after data is populated to the word? Here's my code that I am unable to solve in excel VBA.
Appreciate your help in advance!
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim objWord As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open "C:\Users\" & Environ("username") & "\Desktop\XXX\XXX"
objWord.ActiveDocument.Unprotect Password:="xxx"
With objWord.ActiveDocument
Dim objBMRange As Range
Set objBMRange = .Bookmarks("pr1").Range.Text = ws.Range("C28").Value
objBMRange.Text = pr1
.Bookmarks.Add "pr1", BMRange
.Fields.Update
objWord.ActiveDocument.Protect Password:="xxx", NoReset:=False, Type:=wdAllowOnlyFormFields
End With
Set objWord = Nothing
End Sub
You were almost there. Very near, but you didn't get the Range object sorted out. Please try this code (only partially tested).
Private Sub CommandButton1_Click()
Dim Ws As Worksheet
Dim objWord As Object
Dim Mark As String
Dim Txt As String
Dim BmkStart As Long
Mark = "pr1"
Set Ws = ThisWorkbook.Sheets("Sheet1")
Txt = Ws.Range("C28").Value
Set objWord = CreateObject("Word.Application")
With objWord
.Visible = True
.Documents.Open "C:\Users\" & Environ("username") & "\Desktop\XXX\XXX"
With .ActiveDocument
.Unprotect Password:="xxx"
If .Bookmarks.Exists(Mark) Then
With .Bookmarks(Mark).Range
BmkStart = .Start
.Text = Txt
End With
.Bookmarks.Add Mark, .Range(BmkStart, BmkStart + Len(Txt))
End If
.Fields.Update
.Protect Password:="xxx", NoReset:=False, Type:=wdAllowOnlyFormFields
End With
End With
Set objWord = Nothing
End Sub
One point is that the Bookmark defines a Word.Range (different from an Excel.Range which you get when you specify no application while working in Excel). The other, that Bookmark defines a range but isn't a range itself, not even a Word.Range. Therefore you get or set its text by modifying it's range's Text property.
I am trying to loop through Excel rows, where column A holds text that I want to find in Word. Column B holds what I want to paste in Word after the end of the paragraph in which the text is found.
When working in Word VBA, the find text is working and moving to the end of the paragraph works. But when I move to Excel VBA, the find method doesn't seem to be doing anything.
Sub UpdateWordDoc1()
Dim mywb As Excel.Worksheet
Set mywb = ActiveWorkbook.ActiveSheet
Dim wdDoc As Object, wdApp As Object
Dim questiontext As String
Dim oSearchRange
On Error Resume Next
Set wdDoc = CreateObject("C:\mydoc.docx")
Set wdApp = wdDoc.Application
Set oSearchRange = wdDoc.Content
With mywb
For i = 2 To .Range("A6000").End(xlUp).Row
questiontext = .Range("A" & i).Value
.Range("B" & i).Copy
Set blabla = oSearchRange.Find.Execute.Text = questiontext
blabla.Select
Selection.movedown unit:=wdparagraph
Selection.moveleft unit:=wdcharacter
Selection.PasteAndFormat (wdFormatOriginalFormatting)
Next i
End With
'wdDoc.Close savechanges:=True
Set wdDoc = Nothing
Set wdApp = Nothing
End Sub
I think this code does what you're after. I made a number of small changes to the code in the original post, some important, some not so much. Hopefully the comments help explain why I did what I did:
Sub UpdateWordDoc1()
' REQUIRES A REFERENCE TO:
' Microsoft Word ##.# Object Library
Dim myws As Excel.Worksheet ' Changed wb to ws to better abbreviate worksheet
Dim wdDoc As Word.Document ' No longer a generic object
Dim wdApp As Word.Application ' No longer a generic object
Dim questiontext As String
Dim oSearchRange As Word.Range ' Word range is what will be searched
Dim i As Long ' Loop through rows by count (Long)
Set myws = ActiveWorkbook.ActiveSheet
' On Error Resume Next ' Can't find bugs if they're supressed!!!
Set wdApp = CreateObject("Word.Application") ' Create app before opening doc
' Need to explore what happens
' if Word is already running
wdApp.Visible = True ' Make it visible so we can watch it work
Set wdDoc = wdApp.Documents.Open("C:\mydoc.docx") ' Open the doc
With myws
For i = 2 To .Range("A6000").End(xlUp).Row
' Word's Find function is tricky to program, because
' when Find succeeds, the range is moved! (Find has many
' other odd behaviors). Assuming you want to search the entire doc
' for each search term, we reset the range every time through the
' loop.
Set oSearchRange = wdDoc.Content
questiontext = .Range("A" & i).Value
.Range("B" & i).Copy
' Set blabla = oSearchRange.Find.Execute.Text = questiontext
With oSearchRange.Find
' Note that Word's Find settings are "sticky". For example, if
' you were previously searching for (say) italic text before
' running this Sub, Word may still search for italic, and your
' search could fail. To kill such bugs, explicitly set all of
' Word's Find parameters, not just .Text
.Text = questiontext ' This is what you're searching for
If .Execute Then ' Found it.
' NOTE: This is only gonna make a change
' at the first occurence of questiontext
' When find is successful, oSearchRange will move
' to the found text. But not the selection, so do Select.
oSearchRange.Select
' Now move to where the new text is to be pasted
wdDoc.ActiveWindow.Selection.movedown unit:=wdparagraph
wdDoc.ActiveWindow.Selection.moveleft unit:=wdcharacter
' While debugging, the next statement through me out of single
' step mode (don't know why) but execution continued
' and the remaining words in my list we're found and text
' pasted in as expected.
wdDoc.ActiveWindow.Selection.PasteAndFormat (wdFormatOriginalFormatting)
End If
End With
Next i
End With
' Clean up and close down
wdDoc.Close savechanges:=True
Set oSearchRange = Nothing
Set wdDoc = Nothing
wdApp.Quit
Set wdApp = Nothing
Set myws = Nothing
End Sub
Hope that helps