Inserting .png files from a folder into PowerPoint with a Labeled Object - excel

I had a question earlier about how to import data into PowerPoint using PowerPoint VBA and ended up finding a solution from Excel VBA. That being said I haven't found a solution that works for Excel because it gives me errors despite copying and pasting the exact code.
strPic ="Picture Name"
Set shp = ws.Shapes(strPic)
'Capture properties of exisitng picture such as location and size
With shp
t = .Top
l = .Left
h = .Height
w = .Width
End With
ws.Shapes(strPic).Delete
Set shp = ws.Shapes.AddPicture("Y:\our\Picture\Path\And\File.Name", msoFalse, msoTrue, l, t, w, h)
shp.Name = strPic
shp.ScaleHeight Factor:=1, RelativeToOriginalSize:=msoTrue
shp.ScaleWidth Factor:=1, RelativeToOriginalSize:=msoTrue
This did NOT work for me because it said the method is not found.
The solution I am looking for can be on either PowerPoint VBA or Excel VBA, I am not picky. Even if it is 1 line of code that does it one time, and doesn't use fancy looping I am ok with that as well because I would rather iterate 100 lines of code and change the slide number than beat my head against the wall trying to find answers to this issue!
TL:DR
VBA Code in Excel or PowerPoint that will allow me to select a named shape in a PowerPoint Slide and then insert a .png image from a folder.
Literally I want this line of code to work, but it doesn't
Set shp = ws.Shapes("Named Shape").AddPicture("Y:\our\Picture\Path\And\File.Name", msoFalse, msoTrue, l, t, w, h)
I have tried this For Excel VBA:
oPPTFile.Slides(100).Shapes("Name").Fill.UserPicture("D:\Pictures\Picture.png")
but it didn't work even though that was the exact same code style I used to replace text in differently named shapes...
oPPTFile.Slides(100).Shapes("Different Name").TextFrame.TextRange.Text = "Some Text"
Maybe instead of oPPTFile it's something else and oPPTFile is meant for text? I don't know, this is where I am stuck!!!

I finally found my answer:
Sub main()
Dim objPresentaion As Presentation
Dim objSlide As Slide
Dim objImageBox As Shape
Set objPresentaion = ActivePresentation
Set objSlide = objPresentaion.Slides.Item(1)
Set objImageBox = objSlide.Shapes.AddPicture("D:\Folder\Picture.png", msoCTrue, msoCTrue, 100, 100)
End Sub
The 100, 100 as near as I can tell ensures that whatever picture you import to the slide object fills the entire object. Key take aways: The shape has to be able to recieve images, and it has to be present on the slide already. Beyond that Item(#) refers to the Slide #, not the shape #. If I am wrong as to why this code works the way it does please correct me, but I have seen a LOT of questions about this subject and very few answers that were straightforward.
Now that being said this is NOT a loop, and I have no idea how to make this a loop process. You can iterate those Set lines as often as you like and it WILL work pretty quickly as well. 100 images maybe took a minute, probably less.
So hopefully this helps someone in the future!

Maybe that explains the problem I am having. I have the shape in the exact place I want the picture to show up. That being said, when it imports, and it does import correctly, when I try to use
With shp.Fill.PictureEffects
Dim eff As PictureEffect
Set eff = .Insert(msoEffectSharpenSoften)
eff.EffectParameters(1).Value = 1
End With
Only some of the pictures work???

Use this instead of the existing code in your example file. I changed the Value to -9 to make it more obvious; you can change that back to whatever you want. This now works with both pictures and pictures in placeholders.
Sub EsoteraCardInitialFormatting()
Dim currentSlide As Slide
Dim shp As Shape
Dim eff As PictureEffect
For Each currentSlide In ActivePresentation.Slides
For Each shp In currentSlide.Shapes
Select Case shp.Type
Case msoPicture
With shp.Fill.PictureEffects
Set eff = .Insert(msoEffectSharpenSoften)
eff.EffectParameters(1).Value = -9
End With
Case msoPlaceholder
If shp.PlaceholderFormat.ContainedType = msoPicture Then
With shp.Fill.PictureEffects
Set eff = .Insert(msoEffectSharpenSoften)
eff.EffectParameters(1).Value = -9
End With
End If
End Select
Next
Next
End Sub

Related

Excel VBA coping and pasting numerous shapes now erroring in Windows 10 but did not in 2016

I am a bit of a novice at VBA but have always found solutions from reading forums.
I now have an issue that I can't resolve, my company recently switched from Windows 2016 to Windows 10 (luckily at the moment I still have both laptops) but I am having issues with my code inconsistently erroring in a few Excel VBA tools I had developed in the old version.
My colleague also had this issue but managed to resolve his issue by disabling and enabling missing libraries.. I have tried this but not resolving.
The error..
Basically my tool "draws" a Gantt view of projects by copying and pasting shapes, resizing them and renaming them in specified cell locations.. previous version no issues at all took a few seconds.. Windows 10 is being completely inconsistent.. sometimes it will run with no issues (say 20% of the time) and then it will error at completely different areas of the code!
The error I get is "Run-time Error 1004 Paste method of Worksheet class failed"
I'm not sure why my code would run find in old Windows but not Windows 10.. but it maybe because my code is a bit rubbish and selecting the shapes and cells etc and it just can't cope sometimes?
Here is an example of the code I'm using, any advice would be appreciated:
Sub DrawDevelopment()
Dim rngData As Range
Set rngData = Sheets("Gantt Extract").Range("a4:a300")
For Each G In rngData
G_Address = G.Offset(0, 39).Value
G_size = G.Offset(0, 40).Value
G_Scheme = G.Offset(0, 1).Value
If G_Address <> "" Then
Sheets("Gantt").Shapes("Development").Select
Selection.Copy
Range(G_Address).Select
Sheets("Gantt").Paste
Selection.Name = "Delete" & (G_Scheme)
With Selection.ShapeRange
.Width = G_size
Selection.ShapeRange.IncrementTop 4
Selection.ShapeRange.ZOrder msoBringToFront
End With
End If
Next G
End Sub
Example of what overall code is drawing with shapes
While not specific to Windows 10, something might be causing an issue that is being exposed by the use of unqualified Select statements here.
I've tried re-writing it without the Select - but in order to test it I had to strip away the ShapeRange usage also before it would work with my shapes.
There might be a better way to reference the pasted shape, but I couldn't see one immediately so this does look a bit messy but works on my Win10 machine:
Sub DrawDevelopment()
Dim rngData As Range
Dim shtCopyFrom As Worksheet
Dim shtCopyTo As Worksheet
Set shtCopyFrom = Sheets("Gantt")
Set shtCopyTo = Sheets("Gantt Extract")
Set rngData = shtCopyTo.Range("a4:a300")
For Each g In rngData.Cells
G_Address = g.Offset(0, 39).Value
G_size = g.Offset(0, 40).Value
G_Scheme = g.Offset(0, 1).Value
If G_Address <> "" Then
shtCopyFrom.Shapes("Development").Copy
With shtCopyTo
.Paste
Set objShape = .Shapes(.Shapes.Count)
objShape.Name = "Delete" & (G_Scheme)
Set pasteCell = .Range(G_Address)
With objShape
.Width = G_size
.IncrementTop 4
.ZOrder msoBringToFront
.Left = pasteCell.Left
.Top = pasteCell.Top
End With
End With
End If
Next g
End Sub

Can't insert pictures in Excel with VBA

I am getting completely crazy about this issue, please help me.
I have made a shell script that writes in a text file the path of some images that are stored in a folder. Then I use an excel code to read each path and write it in an excel cell.
I have then made a code that should take that path and use it to insert the picture. I have tried with Pictures.insert(path) and shapes.addpictures "path", but I have the same issue every time, the picture can't be loaded.
What's weird, is that, if I manually insert the picture before and then delete it, the code will perfectly load the picture. But if it's the first time then no.
The paths that I'm using look like that: "/Users/theodorebedos/Documents/code_tilly/new_pict_tilly/IMG_9040.jpg"
I'm using a mac, maybe that matters?
Private Sub Convert_Img()
Dim myPict As Picture
Dim PictureLoc As String
Dim EndPictRow, i As Integer
Dim StartPath As String
If Worksheets("Main").Cells(3, 1).Value <> "" Then
EndPictRow = Worksheets("Main").Range("A2").End(xlDown).Row
For i = 3 To EndPictRow
PictureLoc = Worksheets("Main").Cells(i, 1).Value
Worksheets("Main").Cells(i, 1).ClearContents
Worksheets("Main").Cells(i, 1).ColumnWidth = 30
Worksheets("Main").Cells(i, 1).RowHeight = 150
ActiveSheet.Shapes.AddPicture PictureLoc, False, True, Worksheets("Main").Cells(i, 1).Left, Worksheets("Main").Cells(i, 1).Top, Worksheets("Main").Cells(i, 1).Width, Worksheets("Main").Cells(i, 1).Height
Next i
End If
End Sub
Edit:
When I use "Pictures.insert" or "shapes.addpicture path, true, true " I have no error message in VBA but I have in excel instead of my picture, a blank image with inside an error message like this:
image
If I use "shapes.addpicture path, FALSE, true" then I have an error message like this but no image at all is loaded: image 2
And then an error 1004 like that:
image3
And if I do the process to have image 1, then I save the document, reopen it, I'll have this directly: image 4
Thanks for you help. It will be much appreciated.
I streamlined your code so it becomes possible to see what it's doing. Note that I avoided reading values from the cell's properties which were just set or are obvious.
Once the column width has been set, the width of all cells in it are the same.
The Left property of all cells in a column is always the same.
If the column is column A, the Left is always 0.
Of course, what you tried to achieve is to enter a value only once. That is good practice but to read properties from the sheet is slow. The faster way - less code volume and better readable, too - is to declare a constant at the top and use that name in the code.
So you end up with this code.
Private Sub Convert_Img()
Const ClmWidth As Single = 30
Const RowHight As Single = 150
Dim EndPictRow As Long, R As Long
' sorry, I recommend i for arrays and R for rows (C for columns)
With Worksheets("Main")
' End(xlDown) will find the first blank cell below the base cell.
' There might be more filled cells further down.
' End(xlUp) will find the first used cell above the base cell
' disregarding more blanks above that one.
EndPictRow = .Cells(.Rows.Count, "A").End(xlUp).Row
' no need to set the column width multiple times in the loop
.Columns(1).ColumnWidth = ClmWidth
' this loop will never run if R < EndPicRow
For R = 3 To EndPictRow
With .Cells(R, 1)
.RowHeight = RowHight
' this will work only once:-
.Worksheet.Shapes.AddPicture CStr(.Value), False, True, 0, .Top, ClmWidth, RowHight
End With
Next R
End With
End Sub
The reason why it works only once becomes quite obvious. The new picture takes its source path from the cell's Value. Of course, once you insert a picture (image) in the cell that value can't be the path (string) anymore. If you run the code a second time it will fail. However, if that is your need, it should be possible to extract the path from the formula that defines the picture in the cell. Given that the picture itself isn't present at that location the formula should either hold the path or a reference to a location within the workbook's background data, depending upon how it was loaded.
Ok, so it's not perfect yet, but I put the loop off and I used Dir() as you said #Variatus.A pop-up window like this opened when I executed the command Dir(). It asked me the authorisation to access the file. I pressed yes and then it worked.
It worked but only for that file. So I guess, I am on the right way now and I need to find how to give access to all the files in that folder before running the code. I can't do it for all of them.
Thank you very much.
I hope someone will benefit from this old thread. As it turns out this is some sort of a permission issue also noted already in one of the comments, possibly only occurring with Excel 16 macros on OSX.
It seems like Excel is lacking the permissions to access the resources linked and is not asking for them. We need to grant permissions to all files in the folder. The following code demonstrates how to achieve this, given the identifier to build the paths is in Column A2:20. Run this macro (adjust the way the path is built), then grant access once the dialogue appears:
Sub GrantAccess()
Dim cName As Variant
Dim files() As Variant
Set xRange = ActiveSheet.Range("A2:A20")
For Each cell In xRange
ReDim Preserve files(1 To cell.Row - 1)
cName = "/Users/adjust-your-path/path" & Cells(cell.Row, "A") & "_thumb_600.png"
files(cell.Row - 1) = cName
Next
fileAccessGranted = GrantAccessToMultipleFiles(files)
End Sub
Code used:
Sub URLPICInsertMM()
Dim cShape As Shape
Dim cRange As Range
Dim cColumn As Long
Dim cName As String
Dim img As Picture
Application.ScreenUpdating = False
Set xRange = ActiveSheet.Range("B2:B10")
For Each cell In xRange
'cName = Application.GetOpenFilename(Title:="Select Picture To Be Imported")
' files are located in thumbs sub-directory
cName = "/Users/.../IonChannels/thumbs/" & Cells(cell.Row, "A") & "_thumb_300.png"
Set img = ActiveSheet.Pictures.Insert(cName)
img.Select
Set cShape = Selection.ShapeRange.Item(1)
If cShape Is Nothing Then GoTo line22
Cells(cell.Row, "C").Value = "file://" & cName
Set cRange = Cells(cell.Row, cell.Column)
With cShape
.LockAspectRatio = msoTrue
'If .Width > cRange.Width Then .Width = cRange.Width
If .Height > cRange.Height Then .Height = cRange.Height
.Top = cRange.Top + (cRange.Height - .Height)
.Left = cRange.Left + (cRange.Width - .Width)
End With
line22:
Set cShape = Nothing
Range("T2").Select
Next
Application.ScreenUpdating = True
End Sub
Edit:
Evidence:
I created a simple test sheet (the idea is to load some protein visualization thumbs into an excel sheet) with an identifier in Column A, image file descriptors are constructed from the identifier + path and file extension.
The image is inserted into Column B and the file descriptor as text into Column C.
When I ran the macro for the first time, only the first image was loaded. Excel formats the file descriptor as a hyperlink. When clicking the file:///... link, Excel opens a dialog that asks to grant permissions to that file (screenshot). If I grant access and accept warnings, then run the macro again, the image appears.
After running macro again, image is displayed:

How to change image of a Powerpoint shape?

This is my PowerPoint file:
https://www.dropbox.com/s/7my3ubmnv7rxv8y/temp.pptx?dl=0
This is my code to change image of shape:
Dim presentation As Object
Set ppt = CreateObject("PowerPoint.Application")
Set presentation = ppt.Presentations.Open2007("D:\2018\temp.pptx", MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue)
Dim oSlide As Object
Set oSlide = presentation.Slides(1)
oSlide.Shapes("Picture").Fill.UserPicture ("C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg")
How can I change the image of the Shape object?
What you are trying to do is to create a fill, which doesn't work because the shape in question is a picture. You can try it out yourself in PowerPoint. Setting a fill to a picture has no effect because the original image is still visible. That's why you see no result.
You can't change the picture itself, you have to delete it, and then replace. So you can amend the necessary section of your code as follows:
Set shp = oSlide.Shapes("Picture")
'Capture properties of the existing picture such as location and size
With shp
t = .Top
l = .Left
h = .Height
w = .Width
End With
shp.Delete 'Delete old shape
Set shp = oSlide.Shapes.AddPicture("C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg", msoFalse, msoTrue, l, t, w, h)
shp.Name = "Picture"
shp.ScaleHeight Factor:=1, RelativeToOriginalSize:=msoTrue
shp.ScaleWidth Factor:=1, RelativeToOriginalSize:=msoTrue
Of course, you can make your initial shape a rectangle (or other drawing objects) and then Fill it with a picture. In this case, you can always change the Fill and the picture used for it, something like this:
Dim link as String 'set this to the address of the picture you want to use to fill
oSlide.Shapes(shp).Fill.UserPicture(link)
But if the original shape is a Picture itself, you usually can't fill it with another picture.

Excel to update PowerPoint Presentation

I have a presentation and I have to update it every week. The information I update are a bunch of imagens I generate from a Excel pivot tables (copy from Excel and paste directly on PowerPoint).
Today I can do this doing this:
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
Set PPTPrez =
objPPT.Presentations.Open("\\network_folder\presentation.pptm")
Set pSlide = PPTPrez.Slides(2)
If pSlide.Shapes.Count <> 0 Then
ActiveWorkbook.Sheets("Pivot1").Range("A8:Z18").CopyPicture
pSlide.Shapes.Paste
EndIf
It work flawless... But I need a litle bit more control and precision...
I need to select the current image on slide, delete it and paste the new one in the same location... Some slides have 3 images or more...
I cann't figure it out how to properly tell to VBA what image are what and choose the pivot table with the correct info for that image... I don't even know if this is possible...
But another solution I have tried is how to specify the position and dimensions of the image on the slide... I can before update, delete all imagens... In this scenario, how to specify the dimensions and positioning?
Thanks!!!
Ps.: Sorry my bad english
This example (based on your code) may point you in the right direction. You need to know the powerpoint shape name (which you can get via VBA or via the ribbon Home-Select-Selection Pane.
Option Explicit
Public Sub UpdateShapes()
Dim vPowerPoint As PowerPoint.Application
Dim vPresentation As Presentation
Dim vSlide As Slide
Dim vShapeName As String
Dim vShape, vNewShape
Set vPowerPoint = New PowerPoint.Application
vPowerPoint.Visible = True
' Open the powerpoint presentation
Set vPresentation = vPowerPoint.Presentations.Open("\\network_folder\presentation.pptm")
' Set slide to be worked on
Set vSlide = vPresentation.Slides(2)
' Set shape to (for this example) "Picture 3"
vShapeName = "Picture 3"
Set vShape = vSlide.Shapes(vShapeName)
' Copy and paste new shape (picture) of range specified
ThisWorkbook.Sheets("Sheet1").Range("A6:B9").CopyPicture
Set vNewShape = vSlide.Shapes.Paste
' Align size and position of new shape to that of old shape
With vNewShape
.Width = vShape.Width
.Height = vShape.Height
.Left = vShape.Left
.Top = vShape.Top
End With
' Delete original shape, rename new shape to original so code works next replace cycle
vSlide.Shapes(vShapeName).Delete
vNewShape.Name = vShapeName
End Sub

How could I have image URLs in column "C" display their corresponding images in column "N" in Excel?

I've an Excel file with a bunch of columns, one of which is "ImageURL", which, of course, displays unique URLs as text.
How could I set it up such that those images are also depicted within another column?
I've used the following macro, but I get a "Invalid outside procedure" compile error.
Dim url_column As Range
Dim image_column As Range
Set url_column = Worksheets(1).UsedRange.Columns("C")
Set image_column = Worksheets(1).UsedRange.Columns("N")
Dim i As Long
For i = 1 To url_column.Cells.Count
With image_column.Worksheet.Pictures.Insert(url_column.Cells(i).Value)
.Left = image_column.Cells(i).Left
.Top = image_column.Cells(i).Top
image_column.Cells(i).EntireRow.RowHeight = .Height
End With
Next
I am, unfortunately, new to VBA, so perhaps, I've not set it up correctly?
Ok, this may sound pretty basic (no pun intended), but based on the limited information you made available, I think that the cause of your problem is that you just pasted those statements in your code module and didn't put them inside a procedure. That will certainly give you an "Invalid outside procedure" compile-time error.
You have to put stuff inside a procedure -- either a Sub or a Function. This case calls for a Sub. Try this:
Sub PlaceImageInCell()
Dim url_column As Range
Dim image_column As Range
Set url_column = Worksheets(1).UsedRange.Columns("A")
Set image_column = Worksheets(1).UsedRange.Columns("B")
Dim i As Long
For i = 1 To url_column.Cells.Count
With image_column.Worksheet.Pictures.Insert(url_column.Cells(i).Value)
.Left = image_column.Cells(i).Left
.Top = image_column.Cells(i).Top
image_column.Cells(i).EntireRow.RowHeight = .Height
End With
Next
End Sub
.Pictures.Insert(stuff) doesn't work in XL 2007 - and I've seen suggestions to use *.Shapes.AddPicture() instead.
Problem is that it requires a String for the filePath and I'm not familiar enough with VBA to make this work.
Sub InsertImage()
Dim urlColumn As Range
Dim imgColumn As Range
Dim fp as String
Set urlColumn = Worksheets(1).UsedRange.Columns("A")
Set imgColumn = Worksheets(1).UsedRange.Columns("B")
Dim i As Long
For i = 2 To urlColumn.Cells.Count
With imgColumn.Worksheet.Shapes.AddPicture(fp, msoTrue, msoTrue, 1, 1, 12, 12)
End With
Next
End Sub
The end result is the following Error:
Compile Error:
Object Required

Resources