Insert multiple images in MS Word bookmarks via Excel - excel

I would want images to be inserted into bookmarks in MS Word document (.docx) with the use of Excel. I stumbled upon a Word VBA workaround that is almost perfect for the job EXCEPT that it is of course, a code that sits in Word (I just save it in the global template). The reason why I would need it to be in Excel is because I can't save the macro in the .docx file --- I can't afford to save it as a macro-enabled document as it will mess up with the existing VBA in Excel (Another person made it :). I did have exhausted all effort Googling but there is no exact solution for this. For reference, here is the 'modified' code that I was talking about. I copied it from user fumei in vbaexpress.com
Sub FillABookmark(strBM As String, strText As String)
Dim j As Long
With ActiveDocument
.Bookmarks(strBM).Range _
.InlineShapes _
.AddPicture FileName:=strText
j = ActiveDocument.InlineShapes.Count
.InlineShapes(j).Select
.Bookmarks.Add strBM, Range:=Selection.Range
End With
End Sub
Sub InsertScreenshots()
Call FillABookmark("Image_1", "C:\Users\Public\Documents\Image1.png")
Call FillABookmark("Image_2", "C:\Users\Public\Documents\Image_2.png")
Call FillABookmark("Image_3", "C:\Users\Public\Documents\Image_3.png")
End Sub
I would appreciate any kind of help :)
Update:
Shoutout to Imran :) Your code has been a great help, but I can't seem to work it off to work for multiple images,.. I can't even all of the things that my attempts did, but all of them sort of pastes the new images to one and the same bookmark. Plus a failing Office 365 to add to the dilemma,. I'm reinstalling it later and will on be available for comment tomorrow :( I'm out of my wits and tried to incorporate the looping feature in the original code that I posted. The following code is my failed attempt at it:
Sub FillABookmark(bookmarkname As String, imagepath As String)
Dim objWord As Object
Dim objDoc As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open "D:\test.docx"
Set objDoc = objWord.activedocument
With objDoc
.Bookmarks("test1").Select
.Shapes.AddPicture Filename:=imagepath
End With
With objDoc
.Bookmarks("test2").Select
.Shapes.AddPicture Filename:=imagepath
End With
With objDoc
.Bookmarks("test3").Select
.Shapes.AddPicture Filename:=imagepath
End With
End Sub
Sub InsertScreenshots()
Call FillABookmark("test1", "C:\Users\Public\Documents\image_1.png")
Call FillABookmark("test2", "C:\Users\Public\Documents\image_2.png")
Call FillABookmark("test3", "C:\Users\Public\Documents\iamge_3.png")
End Sub

If it's only the image that you want to add in a word document then use this,
Sub FillABookmark(bookmarkname As String, imagepath As String)
Dim objWord As Object
Dim objDoc As Object
On Error Resume Next
Set objWord = GetObject(, "Word.Application")
If objWord Is Nothing Then
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open "D:\imran.docx"
End If
Set objDoc = objWord.activedocument
With objDoc
.Bookmarks(bookmarkname).Select
.Shapes.AddPicture Filename:=imagepath
End With
With objDoc
.Bookmarks(bookmarkname).Select
.Shapes.AddPicture Filename:=imagepath
End With
With objDoc
.Bookmarks(bookmarkname).Select
.Shapes.AddPicture Filename:=imagepath
End With
End Sub
Sub InsertScreenshots()
Call FillABookmark("test", "C:\Users\Public\Documents\1.jpg")
End Sub

Related

How to create an EmptyField in MS Word from MS Excel using VBA

I need to insert in one excel report a QR code in which the source data is also on this excel. Due the policies of my company, I cannot use any external link or application, so Google Charts, QR code API and etc are not an option... My idea is, from the excel report make a call creating a MS Word document, add a field and using the {DISPLAYBARCODE...} controlled field, generate my QR code, returning as a picture to my Excel report. Right after the MS Word will be close without saving.
I am not a VBA master and I don't know my code is not working. I can create an open the MS Word file, paste a simple text but I can't create the field, always have the error 450 message.
Sub CopyToWord()
Dim doc As Object 'Word.Document
Set doc = CreateObject("Word.Document") 'New Word.Document
doc.Application.Visible = False 'Leave the Word document visible
With doc.ActiveWindow.Selection
doc.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:="DISPLAYBARCODE xxx", PreserveFormatting:=True
.Fields.ToggleShowCodes
End With
doc.Application.Activate
End Sub
When working across Office applications it is vital to qualify every object properly. For example: Selection.Range could refer to either Word or Excel. As the code is being run from Excel an unqualified reference to Selection will be interpreted as meaning Excel.Selection.
As Selection is a child of Application you also need to include an application object in your code.
Public Function GetWordApp(wdApp As Object) As Boolean
On Error Resume Next
GetWordApp = False
Set wdApp = GetObject(, "Word.Application")
If Err > 0 Or wdApp Is Nothing Then
'Word not yet open
Err.Clear
Set wdApp = CreateObject("Word.Application")
If Err = 0 Then GetWordApp = True
Else
GetWordApp = True
End If
On Error GoTo 0
End Function
Sub CopyToWord()
Dim wdApp As Word.Application, doc As Word.Document, fld As Word.Field
If GetWordApp(wdApp) Then
Set doc = wdApp.Documents.Add
'use this if you want to do something else with the field
Set fld = doc.Fields.Add(Range:=wdApp.Selection.Range, Type:=wdFieldEmpty, Text:="DISPLAYBARCODE xxx", PreserveFormatting:=True)
fld.ShowCodes = True
'alternative method
'doc.Fields.Add Range:=wdApp.Selection.Range, Type:=wdFieldEmpty, Text:="DISPLAYBARCODE xxx", PreserveFormatting:=True
'doc.Range.Fields.ToggleShowCodes
wdApp.Visible = True
wdApp.Activate
End If
End Sub

Print specific pages from word file from excel vba

I'm trying to print specific pages from a word file using Excel VBA, but I couldn't do that, I was only able to print the whole file and not the pages I wanted (changes according the value of LastPage). This is the code I used. Please help with that, thanks.
Sub PrintFile()
Dim objWord As Object
Dim objDoc As Object
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open("D:file.docx")
objWord.Visible = False
objDoc.PrintOut from:="1", To:="LastPage".value
objWord.Quit
End Sub
Assuming you are getting an error on the line starting objDoc.PrintOut then replace that line with
objDoc.PrintOut Range:=wdPrintFromTo, From:="1", To:=CStr(LastPage)

How to Copy ALL InlineShapes from Word to Excel?

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

Late Binding Vs Early Binding

I've been using late binding code by using excel 2016, however when the earlier versions tried opening my created excel file, missing reference will happen and i have to remove it every time.
I thought late binding not suppose to be happened that way? My code as below :
Private Sub NTStep2a_Click()
Dim ws As Object
Set ws = ThisWorkbook.Sheets("Data Entry (A)")
Dim objWord As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open "C:\Users\" & Environ("username") & "\Desktop\xxx"
objWord.ActiveDocument.Unprotect Password:="xxx"
With objWord.ActiveDocument
objWord.ActiveDocument.Protect Password:="xxx", NoReset:=False, Type:=wdAllowOnlyFormFields
End With
Set objWord = Nothing
End Sub
Kindly advise.
Maybe you refer to some version of library which is not available.
For example, you use createObject("word.application.11") to create word, but word version 11 is not available.
You could try omit the version number, e.g. createObject("word.application").

Excel VBA - Cross Referencing Bookmark/Form Field to Word

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.

Resources