I've been lurking for a while and found it very helpful, so thanks for the help already!
I'm trying to write a macro to embed images into a worksheet from individual files and resize them, whilst keeping the full resolution of the image intact should it need to be enlarged again. First of all I tried:
ActiveSheet.Pictures.Insert(imageName).Select
With Selection.ShapeRange
.Height = 100
.Width = 100
End With
This essentially inserted a link to the picture and if the image file was removed or the excel file moved to another computer, the link would be broken. Next I tried:
ActiveSheet.Shapes.AddPicture Filename:=imageName, _
linktofile:=msoFalse, _
savewithdocument:=msoCTrue, _
Width:=100, _
Height:=100
This code also works, but the image is resized to 100 * 100 pixels before insertion, so the original file resolution is lost.
Is there any way to insert image files and then scale them down in size, so that the original resolution is retained?
You first load and position the picture in its original size, and in a second step resize it as desired. You only specify EITHER width or heigth to retain the aspect ratio.
Sub Test()
Dim MySht As Worksheet
Dim MyPic As Shape
Dim MyLeft As Single, MyTop As Single
' position in Pixel relative to top/left of sheet
MyTop = 50
MyLeft = 50
' alternatively position to the top/left of [range] C3
MyTop = [C3].Top
MyLeft = [C3].Left
' alternatively position to top/left of actual scrolled position
MyTop = Cells(Windows(1).ScrollRow, Windows(1).ScrollColumn).Top
MyLeft = Cells(Windows(1).ScrollRow, Windows(1).ScrollColumn).Left
Set MySht = ActiveSheet
Set MyPic = MySht.Shapes.AddPicture("C:\Users\MikeD\Desktop\Untitled.png", _
msoFalse, msoTrue, MyLeft, MyTop, -1, -1)
' ^^^ LinkTo SaveWith -1 = keep size
' now resize pic
MyPic.Height = 100
End Sub
... and try to avoid .Select ... Dim the objects you need and use them.
Related
G'day all, I'm trying to create a button that opens the dialogue box, allows the user to
select a photo from their files,
embeds that file to the particular cell that the button exists in,
and allows it to move and size along with that cell, while maintaining aspect ratio (thanks for the pickup dbmitch)
I have successfully done that using the expression.Insert.Picture() method, but had a rude surprise when I sent the sheet out and all the pictures were replaced with "Photo has been moved, deleted or edited." It seems this method only links the file, which certainly won't work for me, so now I'm trying the much older method of expression.shapes.addPicture(). I think I am successfully adding the photo, but can't seem to get the sizing or locking to cell to work. Please see both attempts below-
Sub GetPic()
Dim fNameAndPath As Variant
Dim img As Picture
fNameAndPath = Application.GetOpenFilename(Title:="Select Picture To Be Imported")
If fNameAndPath = False Then Exit Sub
Set img = ActiveSheet.Pictures.Insert(fNameAndPath)
With img
'Resize Picture to fit in the range....
.Left = ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Left
.Top = ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Top
.Width = ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Width
.Height = ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Height
.Placement = 1
.PrintObject = True
End With
End Sub
Sub TestPic()
Dim ws As Worksheet, s As Shape
Set ws = ActiveSheet
' Insert the image.
Set s = ws.Shapes.AddPicture(Application.GetOpenFilename(Title:="Please work"), _
False, True, ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Left, _
ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Top, _
ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Width, _
ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Height)
' Use picture's height and width.
End Sub
I was able to get this code to run in Excel 2016 VBA. You don't say where you're running this from but I assume Application.Caller is not from a module? Maybe a Userform?
Here's what worked for me - hopefully you can use it
Sub TestPic()
Dim ws As Worksheet, s As Shape
Dim sngLeft As Single, sngRight As Single, sngTop As Single, sngWidth As Single
Set ws = ActiveSheet
' Insert the image.
With ActiveCell.Cells
sngLeft = .Left
sngTop = .Top
sngWidth = .Width
sngheight = .Height
End With
Set s = ws.Shapes.AddPicture(Application.GetOpenFilename(Title:="Please work"), _
msoFalse, msoTrue, sngLeft, sngTop, sngWidth, sngheight)
s.Placement = xlMoveAndSize ' move and resize when cell dimensions change
'ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Left, _
'ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Top, _
'ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Width, _
'ActiveSheet.Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address).Height)
' Use picture's height and width.
End Sub
I use a VBA code to insert an image from a folder to excel. When using excel on a other computer with other resolution or change zoom 100% to other value, when reloading the macro, the position of the image change. See vba code below, what has to change?
Thank you
100% zoom
150% zoom
Option Explicit
Public Function PictureLookupUDF(FilePath As String, Location As Range, Index As Integer)
Dim lookupPicture As Shape
Dim sheetName As String
Dim pictureName As String
pictureName = "PictureLookupUDF"
''Dim picTop As Double
''Dim picLeft As Double
sheetName = Location.Parent.Name
'Delete current picture with the same Index if exists
For Each lookupPicture In Sheets(sheetName).Shapes
If lookupPicture.Name = pictureName & Index Then
lookupPicture.Delete
End If
Next lookupPicture
'Add the picture in the right location
Set lookupPicture = Sheets(sheetName).Shapes.AddPicture _
(FilePath, msoFalse, msoTrue, Location.Left, Location.Top, -1, -1)
'Resize picture to best fit the range
If Location.Width / Location.Height > lookupPicture.Width / lookupPicture.Height Then
lookupPicture.Height = Location.Height
Else
lookupPicture.Width = Location.Width
End If
'change the picture name
lookupPicture.Name = pictureName & Index
PictureLookupUDF = "Picture Lookup: " & lookupPicture.Name
End Function
I'm working on a project using VBA with Excel. By clicking a button, we generate an array. One line refers to one product. The information is stored in each column (column A = reference, column B = name...). The generation is made with some code using VBA.
The problem concerns the pictures. I managed the shape of the pictures, so they are placed in the cell, with a certain height, width, placement...
When I generate the array from my computer, there's no problem, the pictures are placed perfectly.
When the array is generated from another computer, the pictures look stretched and shifted. That's it from the 12th line to the end (but the first 11 lines are okay). I don't understand why it starts from the 12th line because the code is exactly the same for every line of the array. And above all, I don't understand why the array isn't well generated on every computer.
The Excel version is the same and the pictures options too.
Have you heard about something like that?
Thanks a lot for your comments!
Here's the code:
Function SetImageViewer(Ref As String, Cell As Range) As String
Dim cmt As Comment
Dim sPicName As String
Dim ImageCell As Range
Dim OrderFormWS As Worksheet
sPicName = GetParameter("PicturesPath") & "\" & Ref & ".jpg"
Set ImageCell = Cell.MergeArea
Set OrderFormWS = ThisWorkbook.Sheets("OrderForm")
sPicFile = Dir(sPicName)
If sPicFile <> vbNullString Then
Set Pic = OrderFormWS.Shapes.AddPicture(sPicName, linktofile:=msoFalse, SaveWithDocument:=msoCTrue, Left:=0, Top:=0, Width:=0, Height:=0)
With Pic
.LockAspectRatio = msoTrue
.Left = ImageCell.Left + 5
.Top = ImageCell.Top + 5
.Width = 40
.Height = 40
.Placement = xlMoveAndSize
End With
Set cmt = Cell.Comment
If cmt Is Nothing Then Set cmt = Cell.AddComment()
cmt.Text " "
cmt.Shape.Fill.UserPicture sPicName
cmt.Shape.Height = 300
cmt.Shape.Width = 300
SetImageViewer = ChrW(&H25BA)
Else
Set cmt = Cell.Comment
If Not cmt Is Nothing Then cmt.Delete
SetImageViewer = "No picture"
End If
End Function
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.
I've used a small subroutine to insert a picture into my sheet by
ActiveSheet.Pictures.Insert(URL).Select
This works fine with Excel 2003 (Windows), but does not work with Excel 2011 (Mac) any more.
Therefore I modified my subroutine
(like proposed http://www.launchexcel.com/google-maps-excel-demo/),
but the subroutine stops at
theShape.Fill.UserPicture URL
with the error message
"-2147024894 (80070002) Fehler der Methode UserPicture des Objekts FillFormat"
The rectangle is green!
Sub Q1()
Dim wks As Worksheet
Dim URL As String
Dim i As Long
Dim lastRow As Long
Dim theShape As Shape
Dim pasteCell As Range
' Used Worksheet
Set wks = Worksheets("Blatt1")
' Delete already existing shapes
For Each theShape In wks.Shapes
theShape.Delete
Next theShape
' Check all existing rows in Column K
lastRow = Cells(Rows.Count, "K").End(xlUp).Row
For i = 2 To lastRow
' the URLs are already computed and stored in column K
URL = wks.Range("K" & i).Value
' try to put the images in column L
Set pasteCell = wks.Range("L" & i)
pasteCell.Select
' Create a Shape for putting the Image into
' ActiveSheet.Pictures.Insert(URL).Select is deprecated and does not work any more!!!
Set theShape = wks.Shapes.AddShape(msoShapeRectangle, pasteCell.Left, pasteCell.Top, 200, 200)
' fill the shape with the image after greening
theShape.Fill.BackColor.RGB = RGB(0, 255, 0)
theShape.Fill.UserPicture URL
Next i
End Sub
Any suggestions or hints? Probably I'm blind as a bat....
Have you tried syntax along the lines of this for setting a shape to a URL:
Sub Picadder()
Dim Pic As Shape
Set Pic = ActiveSheet.Shapes.AddPicture("http://stackoverflow.com/content/stackoverflow/img/apple-touch-icon.png", msoFalse, msoTrue, 0, 0, 100, 100)
End Sub
This code, when adapted to your efforts, might look something along the lines of this:
Sub Q1()
Dim wks As Worksheet
Dim URL As String
Dim i As Long
Dim lastRow As Long
Dim theShape As Shape
Dim pasteCell As Range
' Used Worksheet
Set wks = Worksheets("Blatt1")
' Delete already existing shapes
For Each theShape In wks.Shapes
theShape.Delete
Next theShape
' Check all existing rows in Column K
lastRow = Cells(Rows.Count, "K").End(xlUp).Row
For i = 2 To lastRow
' the URLs are already computed and stored in column K
URL = wks.Range("K" & i).Value
' try to put the images in column L
Set pasteCell = wks.Range("L" & i)
pasteCell.Select
' Create a Shape for putting the Image into
' ActiveSheet.Pictures.Insert(URL).Select is deprecated and does not work any more!!!
Set theShape = wks.Shapes.AddPicture(URL, pasteCell.Left, pasteCell.Top, 200, 200)
' Set shape image backcolor.
theShape.Fill.BackColor.RGB = RGB(0, 255, 0)
Next i
End Sub
Your urls will need to be properly formatted - I had to use quotations on my URL for the initial snippet to get it function effectively, but it may be a solution.
For Mac-Excel 2011, there is a workaround discussed by Michael McLaughlin on his blog. Evidently, it is not easy to tie images to cells in Mac-Excel 2011, if at all. Moreover, research reveals that the question of inserting images into an excel workbook has been asked many times. It also appears that it has not been readily solved through picture methods thus far in the research. Thus, a work-around may be the best solution.
The code snippet, which was very closely adapted and ported from Michael's blog, is as follows:
Function InsertImageCommentAsWorkAround(title As String, cellAddress As Range)
' Define variables used in the comment.
Dim ImageCommentContainer As comment
' Clear any existing comments before adding new ones.
Application.ActiveCell.ClearComments
' Define the comment as a local variable and assign the file name from the _
' _ cellAddress as an input parameter to the comment of a cell at its cellAddress.
' Add a comment.
Set ImageCommentContainer = Application.ActiveCell.AddComment
' With the comment, set parameters.
With ImageCommentContainer
.Text Text:=""
'With the shape overlaying the comment, set parameters.
With .Shape
.Fill.UserPicture (cellAddress.Value)
.ScaleHeight 3#, msoFalse, msoScaleFormTopLeft
.ScaleWidth 2.4, msoFalse, msoScaleFromTopLeft
End With
End With
InsertImageCommentAsWorkAround = title
End Function
I would advise adapting the comment sets into your loop, and use that to set your images into place, using the shape formatting in your loop to set the formatting of the comment shapes generated by the adapted code.