How to save/copy an embedded picture from Excel to Word - vba

What I have:
An Excel file where in a column (actually it is free formatted but aligned to be within a column) some elements are embedded bmp pictures that show the formula =EMBED("Paint.Picture","") when you click on them. When you look at the Excel sheet, only the icon representing the picture is displayed, not the picture itself.
What I want:
The embedded picture (not the icon) copied to a new Word document.
The Code I have thus far:
'Image Objects
Dim myObjs As Shapes
Dim myObj As Shape
Set myObjs = ActiveSheet.Shapes
'Traversing objects
Dim row As Integer
Dim myRange As Range
Dim myRange2 As Range
Dim isAddressMatch As Boolean
'Word Document Objects
Dim wordApp As New Word.Application
Dim myWord As Word.Document
'Prepare word for output
Set myWord = wordApp.Documents.Add
wordApp.Visible = True
'Initalize traversing objectts
Set myRange = Sheets("myWorksheet").Range("Q5")
Set myRange2 = Sheets("myWorksheet").Range("E5")
row = 0
'Loop through range values in the desired column
While (myRange2.Offset(row).Value <> "")
'Loop through all shape objects until address match is found.
For Each myObj In myObjs
On Error Resume Next
isAddressMatch = (myObj.TopLeftCell.Address = myRange.Offset(row).Address)
If Err.Number <> 0 Then
isAddressMatch = False
On Error GoTo 0
End If
'When match is found copy the bmp picture from Excel to Word
If (isAddressMatch) Then
myObj.Select
''''''''This copies the excel default picture,'''''''''''''''
''''''''not the picture that is embeded.'''''''''''''''''''''
myObj.CopyPicture 'What is the correct way to copy myObj
myWord.Range.Paste
'Rest of the code not yet implement
End If
Next
row = row + 1
Wend
What happens when I run my code:
My code goes through all "shapes" that are within the bounds of the column and copies that objects picture. However, when I paste it into word, it literally made a copy of the link image (icon), and not the underlying embedded image.
What I've found thus far:
This code which shows me how to create an embedded object, but not how to copy one.

Update: Simpler solution
As specified in the comments by jspek, the image can actually be copied by using the Copy method of the OLEObject, e.g.:
Dim obj As OLEObject
Set obj = ActiveSheet.OLEObjects(myObj.Name)
'Copy the OLE object representing a picture.
obj.Copy
'Paste the picture in Word.
myWord.Range.Paste
Old solution
I've found a suboptimal solution that involves both the clipboard and SendKeys - inspired by this link. I'm quite convinced that you can do this more elegantly by exploring ways to extract the OLEObject's properties. Extracting these is beyond the scope of my expertise at this time of writing :-)
It revolves around OLEObject. This code executes the OLE object's host application (which is Paint in this case) of your picture, sends keys to copy the picture and finally, pastes it into Word.
'Get the OLE object matching the shape name.
Dim obj As OLEObject
Set obj = ActiveSheet.OLEObjects(myObj.Name)
'Activate the OLE host application.
obj.Activate
'Send CTRL+A to select the picture in Paint and CTRL+C to copy it.
Application.SendKeys "^a"
Application.SendKeys "^c"
'Paste the picture in Word.
myWord.Range.Paste

I am not a coder, but I found that if you "Define Name" for a cell range, you can do all kinds of things with the defined names. For example:
Linking Excel Workbook rows to a Word document
1. Open your Excel work book go to Formulas -> Define NAME
2. Create a "NAME" for each of the cells or groups of cells that you would like to link.
For example, I hyper-linked a Question # in a Word document to my Excel document that is used for importing questions into our Learning Management System. Example NAME = Question_22 and refers to cell range =WBT16DS058!$A$90 (=worksheet!cellrange)
3. Save & close Excel workbook.
4. Open the Word document and create your text (Question 022) , highlight and insert a hyperlink.
5. Browse & Select your Excel document, append the end of the address to include #NAME. (i.e. - R312Test.xlsx#Question_22).
6. Select the new link, and your Excel document will open to the cell range.
Because you are defining a NAME for the range of cells, the link will stay active even when the cells are moved around.
I am wondering if you used "Define Name" for your cell range that includes the picture you are trying to embed, you will have luck.
My apologies if you have already defined the cell range's name and tried this.

Related

How to program a CATIA macro which searches a set of text through the drawing sheet and replace them

I'm currently trying to program a CATIA macro to search through a specific text:"DD/MM/YYY" on a 2D CATIA drawing sheet and replace that same text with a user inputted text. (Basically to update the text box)
I'm currently new to VBA scripting language and have zero to no experience in doing this. I've researched extensively on this but found no codes close to achieving the problems that I am trying to solve.
Textbox contents to be replaced by user
what I wanted the CATIA macro to do
I'm quite sure that your date text string has a specific name in the title block, so search for that specific text string name and assign another value.
If you have a lot of drawings to do this task, you can do it in batch mode, open one by one drawings in a folder, replace the date, save drawing, close document...no input from designer, just assign the new date value inside your new macro.
This short snippet will search all Texts entities and try to replace with a fixed string:
Sub Catmain()
Dim oDoc As Document
Dim oView as DrawingView
Dim oText As DrawingTexts
Dim txt_to_src As String
Dim txt_to_place As String
Dim n As Integer
n = 0
Set oDoc = CATIA.ActiveDocument
Set oSheets = oDoc.Sheets
Set oViews = oSheets.ActiveSheet.Views
Set oView = oViews.ActiveView
Set oTexts = oView.Texts
txt_to_src = "STACK OVERFLOW."
txt_to_place = "REPLACED"
For Each srcText In oTexts
If srcText.Text = txt_to_src Then
srcText.Text = txt_to_place
n = n + 1
End If
Next
MsgBox n & " text frames have been replaced"
End Sub
This only searches all texts in the active view of the active sheet of the opened document.
Consider to use a more specific check criteria such Instr (check if a string is contained into another string), the equality used is just a representative check.
You'll probably need to cycle all views of a Sheet (i.e. all Items of oViews collection), and all Sheets of a document (i.e. all items of oSheets collection). Then extend to cycle all opened DrawingDocuments if you want.
Remember that an empty document with a title block already has 2 Views (background and Main) so if your drawing has, say, just 1 Front View, the script has to cycle through 3 views.

Programmatically Update Linked Named Range of excel object in MS Word (2007)

First question, excuse me if this has already been solved, but I've searched thoroughly and cannot find an answer:
I have linked several named ranges into a word document. This word doc (and the related excel workbook with named ranges) is a template: it's for a coworker who will make many copies of these templates (of both the word doc and the excel workbook).
I would like to include a command button in the word doc that, when clicked, will update the sources for the linked named ranges. Specifically, I want it to set the workbook with the same name as the worddoc, as the source.
The issue is that it does not like the named range I have entered. I get the:
Run-time error '6083': Objects in this document contain links to files that cannot be found. The linked information will not be updated.`
However, I have quadrupled-checked my excel doc, the named range exists. AND, when I hit Alt+F9 in word, I clearly see the link contains the named range!
{LINK Excel.Sheet.8 C:\Users\Marc\Documents\WIP_SSS.xlsm CED \a \p}
Here is my code:
Public Sub ChangeSource()
Dim filename As Variant
Dim fieldcount As Integer
Dim x As Integer
filename = Left(Application.ActiveDocument.Name, Len(Application.ActiveDocument.Name) - 4) & "xlsm"
fieldcount = ActiveDocument.Fields.Count
For x = 1 To fieldcount
'Debug.Print ActiveDocument.Fields(x).Type
If ActiveDocument.Fields(x).Type = 56 Then
ActiveDocument.Fields(x).LinkFormat.SourceFullName = ActiveDocument.Path & "\" & _
filename & "!CED"
End If
Next x
End Sub
If I don't enter the named range at all, the macro works, but it embeds the entire excel worksheet (which I do not want it to do). Any ideas on how/ why it is not liking the named range?
Thanks,
Marc
UPDATE:
With help from Bibadia, I found a solution; in addition, I want to document some strange behavior exhibited by Word VBA:
First off, the solution code:
Public Sub ChangeSource()
Dim filename As Variant
Dim fieldcount As Integer
Dim x As Integer
filename = ThisDocument.Path & "\" & Left(Application.ActiveDocument.Name, Len(Application.ActiveDocument.Name) - 4) & "xlsm"
fieldcount = ActiveDocument.Fields.Count
For x = 1 To fieldcount
On Error Resume Next
If ActiveDocument.Fields(x).Type = 56 Then
ActiveDocument.Fields(x).Delete
End If
Next x
ActiveDocument.Bookmarks("R1").Range.InlineShapes.AddOLEObject filename:=filename & "!Range1", LinkToFile:=True
End Sub
I first deleted all type 56 fields (linked object, or more technically, "wdfieldlinked"). Then, I added OLEObjects at pre-set bookmark locations.
Interestingly, just as Bibadia noted, the key was to input the LinkToFile:=True code. It seems Word will not accept the object if it is embedded: if I remove that line, I get the error Word Cannot obtain the data for the C:\...\document!NamedRange link.
Finally, I found one other odd behavior: When trying to simply replace the link, using this code,
ActiveDocument.Fields(1).LinkFormat.SourceFullName = filepath+name & _
"!CED" 'that is the named range
it would work once, when I changed both the word document's and the excel workbook's filenames (see original message for context). So, when the new filepath+name DID NOT match the existing filepath+name, Word VBA accepted the change. However, once initially updated, if I tried to run the macro again, I would get:
run-time error '6083': Objects in this document contain links to files that cannot be found. The linked information will not be updated.
I would get this error even if I changed the named range to another named range in the same worksheet (and obviously same workbook). So it appears that Word VBA does not like "updating" filepath+name when the filepath+name does not change.
Just so anyone who didn't know (like me) now knows. Sorry for the long update, I just wanted to be thorough.
I am not completely sure of this, but it is a little too long for a comment.
As far as I know, you can only set LinkFormat.FullSourceName to the name of a file, not a fullname + subset name, which is what you are trying to do when appending the "!CED". Although you can read the subset name (CED) from OleFormat.Label, you can't modify it as it's a read-only property.
So if you actually need to modify the subset name (CED), AFAICS the only way to do it is to delete and reinsert the LINK field. If you reinsert using Fields.Add, you just specify the text of the field, so you can get the file name and Subset name right. What is slightly confusing is that if you insert a LINK using InlineShapes.AddOleObject, you can specify fullname+subset name in exactly the way that you are trying to do in your code.
However, I do not think you are trying to modify the Subset name. So let's assume that you already have a LINK field along the lines of
{ LINK Excel.SheetMacroEnabled.12 "the full pathname of a .xlsm file" CED \a f 0 \p }
Word will only be able to update that link if the path+filename is valid (i.e. there's a .xlsm at that location, the workbook has a Range Name called CED, and the Range Name is in the first Sheet. Otherwise, you have to specify a Sheet name as well, e.g.
{ LINK Excel.SheetMacroEnabled.12 "the full pathname of a .xlsm file" Sheet2!CED \a f 0 \p }
It's just a guess, but if your code is trying to connect to a Workbook where the range defined by CED is not in the first sheet, you would see the error you describe.
Further, the scope of the CED Range Name has to be either "workbook" or the name of the first sheet. Otherwise, if the scope is the first sheet but the range is actually in another sheet, or vice versa, I do not think Word can make the connection whatever subset name you provide (my guess is that Word never really caught up with Excel after Excel introduced multi-sheet workbooks).
If CED can reference sheets other than the first one, I think you will probably have to use the Excel object model to discover which sheet its Range is in, construct the appropriate Subset name, and delete/re-insert the LINK field.

Power point tables linked to excel - How to change source (VBA)?

I have big presentation (~300 slides) And i need to make few versions of it, each connected to diffrent excel file. I have code that changes links for all shapes inside prestations. Its all good for charts, but there is problem with linked tables. Source change is correct, but during this change range for table dissapires (range is set for 1st sheet cell A1).
Is there way to keep the range unchanged?
Additional question: changing chart source is very fast (<1s),whereas changing linked table source takes some time (~15s). This becomes a problem where there is a lot tables.
When i run code few times ~50 slides in one run it went well (took ~5-10min), but when i tried run it on all ~300 slides i waited for 30min and it didn't finish (there was no crush, it looked like procedure frozed). Im really curious why this problem occures.
Belowe code i use for link change:
Sub UpdateLinks()
Dim ExcelFile
Dim exl As Object
Set exl = CreateObject("Excel.Application")
'Open a dialog box to promt for the new source file.
ExcelFile = exl.Application.GetOpenFilename(, , "Select Excel File")
Dim i As Integer
Dim k As Integer
'Go through every slide
For i = 1 To ActivePresentation.Slides.Count
With ActivePresentation.Slides(i)
'Go through every shape on every slide
For k = 1 To .Shapes.Count
'Turn of error checking s that it doesn 't crash if the current shape doesn't already have a link
On Error Resume Next
'Set the source to be the same as teh file chosen in the opening dialog box
.Shapes(k).LinkFormat.SourceFullName = ExcelFile
If .Shapes(k).LinkFormat.SourceFullName = ExcelFile Then
'If the change was successful then also set it to update automatically
.Shapes(k).LinkFormat.AutoUpdate = ppUpdateOptionAutomatic 'other option is ppUpdateOptionManual/ppUpdateOptionAutomatic
End If
On Error GoTo 0
Next k
End With
Next i
End Sub
All tips are welcome! :)
Have you looked at what .SourceFullName returns? Usually it's not just the file name but also further code that indicates what sheet and range within the sheet the link points to. It looks like you're changing that to just the name of the replacement Excel file.
Instead, try using Replace to substitute the name of the new Excel file for the name of the old Excel file in .SourceFullName. That'll leave the rest of the link text intact.

how to create relative path in hyperlink excel ? (Word.Document.12)

I have two documents, one which has all the info and it is a word document, and another that is an excel document, that have just some highlights from the word document.
I want to create some links between some selected text in word and excel cells, so far the special past is doing a great job, and create link in this format
=Word.Document.12|'C:\Users\...\xxx.docx'!'!OLE_LINK9'
Now i want to copy both documents in my usb and past them in other computers, this where the problem is, i would have to do the special past all over again since the path is different now, what i though as a solution was to put the path to the word document in cell let say A1 and concatenate the formula above, something like
=Word.Document.12|A1!'!OLE_LINK9'
but it doesnt work, it throws an error message, can you please help me?
PS : I would like to avoid vba if possible
PS : I would like to avoid vba if possible
I have included both ways to do it since the question is tagged with Excel-VBA as well :)
Take your pick.
VBA Way
Is this what you are trying?
Sub Sample()
Dim objOle As OLEObject
'~~> Change this to the respective Sheet name
With ThisWorkbook.Sheets("Sheet1")
'~~> This is your embedded word object
Set objOle = .OLEObjects("Object 1")
'~~> Cell A1 has a path like C:\Temp\
objOle.SourceName = "Word.Document.12|" & .Range("A1").Value & "xxx.docx!'"
End With
End Sub
Non VBA Way
Create a named range and call it say Filepath. Set the formula to
="Word.Document.12|'" & Sheet1!$A$1 & "xxx.docx'!'"
Where Cell A1 will have the file path.
Next Select your word document and in the formula bar, type =Filepath and you are done.

Error 1004 with VBA code with bookmarks

I am using a macro to populate a word document with text from named ranges in excel. The word document has bookmarks that correspond with the named excel ranges. I did not write the code, but rather copied it from another source.
There is quite a bit more to this macro than the snippet I posted. I could post the rest if that is useful. I had about half of my word document bookmarked and the macro was working fine then it suddenly stopped working.
I am receiving a error 1004 in the line highlighted below. I am a newbie so I'm not even quite sure what I should be searching for to fix this issue. Any assistance you could provide would be appreciated! Thanks in advance!
P.S. In case it's relevant, I am using Word and Excel 2007
'PASTE TEXT STRINGS LOOP
n = 1
For Each temp In BkmTxt
p = p + 1
Prompt = "Please wait. Copying text. Carrying out operation " & p & " of " & pcount & "."
Application.StatusBar = Prompt
'If The Bkmtxt(n) is empty then go to the next one, once that has been found do next operation.
If BkmTxt(n) = Empty Then
n = n + 1
'should find match and work
Else
'You might want to use multiple copies of the same text string.
'In this case you need to call the bookmark as follows: "ARTextWhatever_01"
'You can use as many bookmarks as you want.
BkmTxtSplit = Split(BkmTxt(n), "_")
vValue = Range(BkmTxtSplit(0)).Text **<----- ERROR HERE**
Set wdRng = wdApp.ActiveDocument.Bookmarks(BkmTxt(n)).Range
If Len(sFormat) = 0 Then
'replace the bookmark text
wdRng.Text = vValue
Else
'replace the bookmark text with formatted text
wdRng.Text = Format(vValue, sFormat)
End If
'Re-add the Bookmark
wdRng.Bookmarks.Add BkmTxt(n), wdRng
n = n + 1
End If
Next
Step 1: Don't copy code from external sources. Use external sources as a learning tool and try to understand what they are actually doing.
Now if I understand you correctly, you simply have an Excel sheet with named ranges, I assume they have information already within them, and a word document with bookmarks that EXACTLY match the named ranges:
Step 2: Make sure you have the word object library reference within excel
Here:
sub KeepItDoin()
dim xlRange as Excel.Range
dim wdApp as new Word.Application
dim wdDoc as Word.Document
dim wdBkm as Word.Bookmark
set wdDoc = wdApp.Documents.Open( "Filepath" ) 'get filepath from where ever
for each wdBkm in wdDoc.Bookmarks
set xlRange = Application.Range(wdBkm.Name)
wdBkm.range.text = xlRange.Value
next wdBkm
end sub
That will get you close probably (didn't test, don't care if it works. Use it to learn). The idea is that if the bookmarks match up to the range, we can use their names to find the ranges in excel and then tell excel to move the data within it into the bookmarks range.
You will likely need to add some formatting or maybe create a table and then move cell by cell in the range and fill the table but this is as close as I'm willing to get since you like to copy pasta.
In case anyone is interested, I figured it out. There was an error with the bookmarks I inserted into my Word document. This macro returns Error 1004 if the word document contains a bookmark that does not correspond to a range in excel. Thank you for your help.