Bug Fixing: Copied images in Excel 2016 VBA appear as blank images - excel

I am trying to export into my local file a defined Excel range as image (PNG) (it’s named: “ Print_Area” on tab “Summary” Range: P1:AI92 ) . The program runs well, however when I open the file all the imagines are blank
Here is the coding that I am using:
Sub _Daily_Mail()
Dim Rango7 As Range
Dim Archivo As String
Dim Imagen As Chart
Dim Result As Boolean
Set Rango7 = Sheets("Summary").Range("P2:AI92") ' Summary
Sheets("Summary").Select
With Rango7
.CopyPicture Appearance:=xlScreen, Format:=xlPicture
Set Imagen = Rango7.Parent.ChartObjects.Add(33, 39, .Width, .Height).Chart
End With
Imagen.Paste
Imagen.ChartArea.Border.LineStyle = 0
Imagen.ChartArea.Width = Imagen.ChartArea.Width * 3
Imagen.ChartArea.Height = Imagen.ChartArea.Height * 3
Imagen.export "C:\Users\mely\Documents\Imagenes_POS\Informe1.png", filtername:="PNG"
Imagen.Parent.Delete
Set Imagen = Nothing
When I open the file

In Excel 2016 you need to use .Activate command before Paste operation.
Example:
Set rng = Range("A1:C1")
With rng
.CopyPicture xlPrinter, xlPicture
Set oChart = ActiveSheet.ChartObjects.Add(.Left, .Top, 1920, 1080)
oChart.Activate
With oChart.Chart
.ChartArea.Border.LineStyle = 0
.Paste
.Export Filename:="C:\File.jpg", Filtername:="jpg"
.Parent.Delete
End With
End With

I am running into the same issue with office 2016. It appears to be a timing issue. When creating the Chart Object and being able to paste to it. If I step through the code it works as expected and generates my image.
I came up with a fix which appears to work:
For some reason selecting The chart's parent shape before calling the Paste corrects The issue.
Function CopyRangeToPNG(ByRef rngImage As Range) As String
Dim vFilePath As Variant
rngImage.CopyPicture Appearance:=xlScreen, Format:=xlPicture
With rngImage.Parent.ChartObjects.Add( _
Left:=rngImage.Left, Top:=rngImage.Top, _
Width:=rngImage.Width + 2, Height:=rngImage.Height + 2)
With .Chart
.Parent.Select
.ChartArea.Format.Line.Visible = msoFalse
.Paste
With .Pictures(1)
.Left = .Left + 2
.Top = .Top + 2
End With
' export
.Export CStr(ThisWorkbook.Path & "\ImageName.PNG")
End With
.Delete
End With
CopyRangeToPNG = ThisWorkbook.Path & "\ImageName.PNG"
End Function

Related

Troubles importing and formatting photos

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

Code Works When Using F8 but Not When Run Fully

First of all I'm not very good at Excel macro.
After going through multiple forums, I managed to come up with a code to Crop images in a folder using Excel VBA.
the code opens up each image in Excel, paste in a chart, crop the image, resize to match the height & width and then replace the original image with the edited image.
Macro is working fine with F8 but when I run the macro fully, Images are not getting replaced with the edited one, instead it's replacing with blank image.
After digging through multiple options, the only conclusion I came up with is the macro is running fine in Excel 2013 but it's not running properly with office 365.
Can anybody help me, how to resolve this or have any better code to run?
Option Explicit
Sub ImportData()
Dim XL As Object
Dim thisPath As String
Dim BooksPAth As String
BooksPAth = "C:\Images\"
thisPath = ActivePresentation.path
Set XL = CreateObject("Excel.Application")
Run "Crop_vis", BooksPAth
End Sub
Sub DeleteAllShapes()
Dim Shp As Shape
For Each Shp In ActiveSheet.Shapes
If Not (Shp.Type = msoOLEControlObject Or Shp.Type = msoFormControl) Then Shp.Delete
Next Shp
End Sub
Sub Crop_Vis(ByVal folderPath As String)
Dim Shp As Object, path As String, sht As Worksheet, s As Shape, TempChart As String
'Dim folderPath As String
Application.ScreenUpdating = True
If folderPath = "" Then Exit Sub
Set sht = Sheet1
sht.Activate
sht.Range("A10").Activate
path = Dir(folderPath & "\*.jpg")
Do While path <> ""
DeleteAllShapes
Set Shp = sht.Pictures.Insert(folderPath & "\" & path)
' Use picture's height and width.
Set s = sht.Shapes(sht.Shapes.Count)
s.PictureFormat.CropTop = 50
s.Width = 768
s.Height = 720
'Add a temporary chart in sheet1
Charts.Add
ActiveChart.Location Where:=xlLocationAsObject, Name:=sht.Name
Selection.Border.LineStyle = 0
TempChart = Selection.Name & " " & Split(ActiveChart.Name, " ")(2)
With sht
'Change the dimensions of the chart to suit your need
With .Shapes(TempChart)
.Width = s.Width
.Height = s.Height
End With
'Copy the picture
s.Copy
'Paste the picture in the chart
With ActiveChart
.ChartArea.Select
.Paste
End With
'Finally export the chart
.ChartObjects(1).Chart.Export fileName:=folderPath & "\" & path, FilterName:="jpg"
'Destroy the chart. You may want to delete it...
.Shapes(TempChart).Cut
End With
path = Dir
Loop
DeleteAllShapes
Application.DisplayAlerts = False
End Sub
Before
'Finally export the chart
insert something like this, to make sure that pasting of the image into the chart has finished:
Do
If ActiveChart.Shapes.Count > 0 Then
Exit Do
End If
Loop
The problem is with the pasting. When you tell it to paste the clipboard (image) into the chart, sometimes it ignores you. When you go to export the chart, you end up with an empty image.
It's not that you have to wait for it to paste, because it's not going to - it ignored you. I have no idea why it ignores you, or why it doesn't error out when it ignores you - it just ignores you with no warning. Maybe Windows is just too busy under the hood to paste.
Basically, what you have to do is check to see if it pasted, and if not, paste again....and again....until it finally sees fit to process your instruction.
I debugged, Googled, trialed and errored and banged my head on the wall for week on this and finally ended up with this:
Sub SavePictureFromExcel(shp As Shape, SavePath As String)
Dim Imagews As Worksheet
Dim tempChartObj As ChartObject
Dim ImageFullPath As String
Set Imagews = Sheets("Image Files")
Set tempChartObj = Imagews.ChartObjects.Add(0, 0, shp.Width, shp.Height)
shp.Copy
tempChartObj.Chart.ChartArea.Format.Line.Visible = msoFalse 'No Outline
tempChartObj.Chart.ChartArea.Format.Fill.Visible = msoFalse 'No Background
Do
DoEvents
tempChartObj.Chart.Paste
Loop While tempChartObj.Chart.Shapes.Count < 1
ImageFullPath = SavePath & "\" & shp.Name & ".png"
tempChartObj.Chart.Export ImageFullPath, Filtername:="png"
tempChartObj.Delete
End Sub

Excel VBA Resize picture in a certain range [duplicate]

This question already has answers here:
How to resize all images on a worksheet?
(2 answers)
Closed 3 years ago.
Ok i have an image that a 3rd part software is placing into an excel file. in order to get the resolution needed it has to be sized much larger than needed. It will always be placed in the same location and be a specific size. I need to resize it. Ideally it would be automatic when the excel file opens but i think any vba code would end up acting before the information is inserted, but if there was a small delay that would be cool too. Alternatively i could make do with a button that runs a bit of code. The code below works, but only when the picture is specifically named "Picture 179" which it won't be ever again or at least until the counter recycles.
The image is inserted at Cell A45 specifically but it extends through roughly cell AZ60.
Here is what i've got that doesn't work.
Private Sub Resize_Graph_Click()
ActiveSheet.Shapes.Range(Array("Picture 179")).Select
Selection.ShapeRange.Height = 104.4
Selection.ShapeRange.Width = 486.72
End Sub
You still need to work out when to resize the picture, but the example code below shows how you can specifically access a picture where the Top-Left corner of the picture is located within a given cell.
Option Explicit
Sub TestMe()
Dim thePicture As Shape
Set thePicture = GetPictureAt(Range("A45"))
If Not thePicture Is Nothing Then
Debug.Print "found it! (" & thePicture.Name & ")"
With thePicture
.Height = 75
.Width = 75
Debug.Print "resized to h=" & .Height & ", w=" & .Width
End With
Else
Debug.Print "couldn't find the picture!"
End If
End Sub
Private Function GetPictureAt(ByRef thisCell As Range) As Shape
Dim thisCellTop As Long
Dim thisCellBottom As Long
Dim thisCellLeft As Long
Dim thisCellRight As Long
With thisCell
thisCellTop = .Top
thisCellLeft = .Left
thisCellBottom = thisCellTop + .Height
thisCellRight = thisCellLeft + .Width
End With
Dim shp As Variant
With Sheet1
For Each shp In .Shapes
If shp.Type = msoPicture Then
If (shp.Top >= thisCellTop) And (shp.Top <= thisCellBottom) Then
If (shp.Left >= thisCellLeft) And (shp.Left <= thisCellRight) Then
Set GetPictureAt = shp
Exit Function
End If
End If
End If
Next shp
End With
End Function
Here is what i settled on.
Private Sub Resize_Graph_Click()
'resize all shapes
Dim s As Shape
Dim ws As Worksheet
Set ws = ActiveSheet
For Each s In ActiveSheet.Shapes
s.LockAspectRatio = msoFalse
s.Width = 491.72
s.Height = 106.56
Next s
'set header shapes and button back to original size
ActiveSheet.Shapes.Range(Array("Company Label")).Select
Selection.ShapeRange.Height = 43.92
Selection.ShapeRange.Width = 131.76
ActiveSheet.Shapes.Range(Array("Product Label")).Select
Selection.ShapeRange.Height = 49.68
Selection.ShapeRange.Width = 134.64
ActiveSheet.Shapes.Range(Array("Resize_Graph")).Select
ActiveSheet.Shapes("Resize_Graph").Height = 38.16
ActiveSheet.Shapes("Resize_Graph").Width = 105.12
'keep button from moving after changing shape back and forth
ActiveSheet.Shapes.Range(Array("Resize_Graph")).Select
ActiveSheet.Shapes("Resize_Graph").Left = 380
ActiveSheet.Shapes("Resize_Graph").Top = 5
ActiveWorkbook.Close Savechanges:=True
End Sub

Setting the font size in a shape

I have the following macro which is supposed to create a box linking to a certain worksheet in the workbook, on each sheet of the workbook:
Option Explicit
Sub gndhnkl()
Dim ws As Worksheet
Dim sh As Shape
For Each ws In ThisWorkbook.Worksheets
If InStr(1, ws.Name, "Summering", vbBinaryCompare) <= 0 Then
For Each sh In ws.Shapes
sh.Delete
Next sh
Call Macro1(ws)
End If
Next ws
End Sub
Sub Macro1(ws As Worksheet)
Dim venstre As Double, topp As Double, breidde As Double, høgde As Double
Dim sh As Shape
venstre = ws.Range("B16").Left
topp = ws.Range("B16").Top
breidde = 110
høgde = 68
Set sh = ws.Shapes.AddShape(msoShapeRoundedRectangle, venstre, topp, breidde, høgde)
With sh.TextFrame2.TextRange
.Characters.Text = "Til summering, person"
.Font.Size = 13
.ParagraphFormat.Alignment = msoAlignCenter
.Parent.VerticalAnchor = msoAnchorMiddle
End With
ws.Hyperlinks.Add Anchor:=sh, Address:="", SubAddress:=Replace(Summering_person.Range("A1").Address(external:=True), "[" & ThisWorkbook.Name & "]", "", 1, -1, vbBinaryCompare)
End Sub
For the most part it works just like I expect it too, but for some reason the font size in the added shape is not set to 13 as I expect, but remains 11.
I.e. it seems that the line .Font.Size = 13 (sh.TextFrame2.TextRange.Font.Size = 13) is not executed.
Where is my mistake here, and what do I need to do in order for the macro to set the font size for the shape?
You have to change the order, first set the font size (and any other font properties) before you write the text. Once the text is set, it's getting trickier to change the font - every character of the TextFrame may have it's own characteristics.
.Font.Size = 13
.Characters.Text = "Til summering, person"
Update The comment of SJR is right, when using the TextFrame rather than TextFrame2, you can set the font properties of the whole text as once after the text was written.

Excel image comments --> picture objects

I get an excel report each week with images in the comments.
I am trying to loop through all comments in the file, and paste all the comments to the worksheet as pictures
I have tried the method found on the "Ku Tools" website...
https://www.extendoffice.com/documents/excel/4328-excel-extract-image-from-comment.html
Here is the code from the website (that i use exactly)...
Sub CommentPictures()
'Updateby Extendoffcie 20161207
Dim cmt As Comment
Dim xRg As Range
Dim visBool As Boolean
Dim cmtTxt As String
Dim jpgPath As String
Dim shpHeight As Integer, shpWidth As Integer
Application.ScreenUpdating = False
For Each cmt In ActiveSheet.Comments
With cmt
cmtTxt = .Text
shpHeight = .Shape.Height
shpWidth = .Shape.Width
.Text Text:="" & Chr(10) & ""
visBool = .Visible
.Visible = True
On Error Resume Next
Set xRg = .Parent.Offset(0, 1)
.Shape.CopyPicture _
Appearance:=xlScreen, Format:=xlPicture
xRg.PasteSpecial
Selection.ShapeRange.LockAspectRatio = msoFalse
Selection.Width = xRg.Width
Selection.Height = xRg.Height
.Visible = visBool
.Text Text:=cmtTxt
End With
Next cmt
Application.ScreenUpdating = True
End Sub
When I use this code, it works sporadically
When it "doesn't work", the macro creates an invisible rectangle object
When it does work, it creates a visible rectangle image/object (rectangle shape that can be seen).
In the below screenshot, row 715 contains a visible image (when the macro works right) and row 755 contains an invisible image (when it doesn't work right)
Visible vs Non-Visible
I want to make all 700+ image comments actual images as easily as possible, if anyone has any ideas, they would be greatly appreciated.
My hypothesis is that there might be a size limit, because the macro worked perfectly when I ran it in a small batch of a couple dozen images
Thanks

Resources