Excel VBA to replace image, create PDF, move to next image in folder and repeat - vba

I have an Excel worksheet that i use as a printable single page PDF report that contains an image with some text. In a column to the side I have a list of all the images in a specific folder and i would like to use VBA to cycle through the list replacing the image in the worksheet and creating a PDF to be stored in the same folder. I currently do this manually which is a pain and would like to automate it with VBA.
Any help would be greatly appreciated.
Thanks in advance.
The code i use manualy by changing the full path of the image to be replaced is as follows>
Sub AddPicturesFULL()
Dim myPic As Picture
Dim wkSheet As Worksheet
Dim myRng As Range
Dim myCell As Range
Dim rowCount As Long
Dim rowCount2 As Long
Dim Pic As Object
Set wkSheet = Sheets("REPORT(FULL)") ' -- Change to your sheet
For Each Pic In wkSheet.Pictures
Pic.Delete
Next Pic
'-- The usual way of finding used row count for specific column
rowCount2 = wkSheet.Cells(wkSheet.Rows.Count, "N").End(xlUp).Row
If rowCount2 <> 0 Then
Set myRng = wkSheet.Range("N2", wkSheet.Cells(wkSheet.Rows.Count, "N").End(xlUp))
For Each myCell In myRng.Cells
If Trim(myCell.Value) = "" Then
'MsgBox "No file path"
ElseIf Dir(CStr(myCell.Value)) = "" Then
MsgBox myCell.Value & " Doesn't exist!"
Else
'myCell.Offset(0, 1).Parent.Pictures.Insert (myCell.Value)
Set myPic = myCell.Parent.Pictures.Insert(myCell.Value)
With myCell.Offset(0, -13) '1 columns to the right of C ( is D)
'-- resize image here to fit into the size of your cell
myPic.Top = .Top
myPic.Width = .Width
myPic.Height = 640
myPic.Left = .Left
myPic.Placement = xlMoveAndSize
myPic.SendToBack
End With
End If
Next myCell
Else
MsgBox "There is no file paths in your column"
End If
End Sub

Create an ActiveX Image on the Sheet instead of using drawing Pictures
Then you can use
Dim i As Integer
For i = 1 To 20 Step 1
imgTest.Picture = LoadPicture(Sheets("Sheet1").Cells(i, COLUMN).Value)
Sheets("Sheets1").ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\test" & i & ".pdf", Quality:=xlQualityStandard
Next i
To loop through the column with imagepaths and set the image for each of them. Then just export it as a PDF.
Of course you have to adjust the i values and COLUMN to your needs.

Related

VBA macro does not iterate over all cells when inserting pictures

I'm currently trying to write a VBA macro for MS Word. The job is to iterate over selected cells of a table and to replace the filepath written there with the picture it points to.
The macro works fine when only one cell is selected or if all selected cells are in the same column. However, when cells from more than one columns are selected, only the left most column gets processed.
Here is the code:
Dim photoCells As Cells
Set photoCells = Selection.Cells
For Each photoCell In photoCells
Dim filePath As String
filePath = photoCell.Range.Text
filePath = Left(filePath, Len(filePath) - 2)
photoCell.Range.Text = ""
Dim shape
Set shape = photoCell.Range.InlineShapes.AddPicture(filePath)
With shape
.LockAspectRatio = msoTrue
.Width = photoCell.PreferredWidth
End With
Next
MsgBox "Completed."
End Sub
Interesting: When I do that:
For Each mCell in Selection.Cells
MsgBox mCell.Range.Text
Next
... it iterates over every cell in the selection.
Can anyone tell me where I messed things up? :-D
Thanks in advance!
Please, try the next way:
Sub InsertPictures()
Dim photoCells As Cells, photoCell, arrPh() As Cell, i As Long
Dim filePath As String, shape As InlineShape
Set photoCells = Selection.Cells
ReDim arrPh(1 To photoCells.Count)
For i = 1 To photoCells.Count 'place selected cells in a cells array
Set arrPh(i) = photoCells(i)
Next
For i = 1 To UBound(arrPh) 'iterate between the array cell elements
filePath = arrPh(i).Range.Text
filePath = Left(filePath, Len(filePath) - 2)
If Dir(filePath) <> "" Then 'check if file path exists
arrPh(i).Range.Text = ""
With arrPh(i).Range.InlineShapes.AddPicture(filePath)
.LockAspectRatio = msoTrue
.Width = arrPh(i).PreferredWidth
End With
End If
Next i
MsgBox "Completed."
End Sub

VBA dynamic pictures

I am trying to insert a picture into excel based off a cell value. The Cell value is in the image path. I am new, what I have is partially based on recording the macro and part from looking stuff up. This is what I tried...
I keep getting an error on the ActiveSheet.Pictures.Insert line
Sub Part_Picture()
'
' Part_Picture Macro
'
Dim imageName As String
Dim imageFolder As String
Dim imagePath As String
For Each Cell In Range("B7")
imageName = Cell.Value
imageFolder = "Q:\New Project Part Folders\Elizabeth Delgado\Database pictures\Part\" & imageName
imagePath = imageFolder & ".jpg"
Range("B11").Select
'
ActiveSheet.Pictures.Insert(imagePath).Select
Next Cell
End Sub
"Unable to get the insert property of the Pictures class" is a generic error message which you may as well just translate as "Something went wrong with what you're trying to do and I can't give you more information". It's likely though that the path to the image file has not been build correctly.
1) Remove the .Select from your insert statement. Syntactically it makes no sense. Just use ActiveSheet.Pictures.Insert(imagePath)
2) Check the value in cell B7 is the file name only, not including the extension. Since your code adds ".jpg" you dont need that in B7.
3) Check the file is actually a jpg, not for instance a png
4) Check the file / folder actually exists
FYI For Each Cell In Range("B7") is only going to iterate one cell - B7 - and is unnecessary. If you only intended for one cell to be read you should use imageName = Range("B7").Value, or better yet since you need a string use imageName = Range("B7").Text
Consider this option.
Sub InsertPics()
Dim fPath As String, fName As String
Dim r As Range, rng As Range
Application.ScreenUpdating = False
fPath = "C:\your_path_here\"
Set rng = Range("A1:A" & Cells(Rows.Count, 1).End(xlUp).Row)
i = 1
For Each r In rng
fName = Dir(fPath)
Do While fName <> ""
If fName = r.Value Then
With ActiveSheet.Pictures.Insert(fPath & fName)
.ShapeRange.LockAspectRatio = msoTrue
Set px = .ShapeRange
If .ShapeRange.Width > Rows(i).Columns(2).Width Then .ShapeRange.Width = Columns(2).Width
With Cells(i, 2)
px.Top = .Top
px.Left = .Left
.RowHeight = px.Height
End With
End With
End If
fName = Dir
Loop
i = i + 1
Next r
Application.ScreenUpdating = True
End Sub
' Note: you need the file extension, such as ',jpg', or whatever you are using, so you can match on that.
Whatever picture name you put in Column A, will be imported into the adjacent cell in, Column B
The .Pictures.Insert("c:\fixedfile.png") asked a fix file name as its parameter. However you may use FileCopy "desiredfile.png", "fixedfile.png" to replace the content of fixedfile.png which then meet your needs.

Unable to set if statement between my code to make it error-free

I've written a code to set pictures next to it's link in an excel sheet after it's done downloading. It is working smoothly but the problem is that every time i run the code it gets downloaded again and settled there. So if i delete one picture i see another one in that place. I hope there is a solution in if statement so that, if applied, it will omit downloading and go for the next loop if the cell is already filled in. I can't make it. If anybody helps me accomplish this, i would be very grateful. Thanks in advance.
Note: Links are in B column and pictures to get settled in C column.
Sub SetPics()
Dim pics As String
Dim myPic As Picture
Dim rng As Range
Dim cel As Range
Set rng = Range("C2", Range("B2").End(xlDown).Offset(0, 1))
For Each cel In rng
pics = cel.Offset(0, -1)
Set myPic = ActiveSheet.Pictures.Insert(pics)
With myPic
.ShapeRange.LockAspectRatio = msoFalse
.Width = cel.Width
.Height = cel.Height
.Top = Rows(cel.Row).Top
.Left = Columns(cel.Column).Left
End With
Next cel
End Sub
You need to scan the ActiveSheet (try not to use this, and replace it with Worksheets("YourSheetName")) for all Shapes.
For each Shape found, check it's TopLeftCell.Row property, if it equals the
cel.Row then the current picture already exists (from previous runs of this code), and you don't "re-insert" the picture.
Code
Sub SetPics()
Dim pics As String
Dim myPics As Shape
Dim PicExists As Boolean
Dim myPic As Picture
Dim rng As Range
Dim cel As Range
Set rng = Range("C2", Range("B2").End(xlDown).Offset(0, 1))
For Each cel In rng
PicExists = False ' reset flag
pics = cel.Offset(0, -1)
' loop through all shapes in ActiveSheet
For Each myPics In ActiveSheet.Shapes
If myPics.TopLeftCell.Row = cel.Row Then ' check if current shape's row equale the current cell's row
PicExists = True ' raise flag >> picture exists
Exit For
End If
Next myPics
If Not PicExists Then '<-- add new picture only if doesn't exist
Set myPic = ActiveSheet.Pictures.Insert(pics)
With myPic
.ShapeRange.LockAspectRatio = msoFalse
.WIDTH = cel.WIDTH
.HEIGHT = cel.HEIGHT
.Top = Rows(cel.Row).Top
.Left = Columns(cel.Column).Left
End With
End If
Next cel
End Sub

click shape or button (preview/close) that displays an image

I am new to VBA and seeking help on a work project. I have done some research and got started but am now over my head.
My objectives are:
Create a click shape or button (preview/close) that displays an image from another location on computer.
The image displayed will be dependent on the data input (col A: patient name; same name of jpeg image) for each name that is entered in the same row.
Also I would like a new button/shape to be automatically created in the corresponding cell when a new name is added
Thanks Rick
Sub Macro1()
Dim Path As String
Set myDocument = Worksheets(1)
Path = "F:\CAD_CAM division\Unsorted Models\"
myDocument.Pictures.Insert (Path & ActiveCell.Value & ".jpg")
With ActiveSheet.Shapes("Rounded Rectangle 1").TextFrame2.TextRange.Characters
If .Text = "Close" Then
.Text = "Preview"
ActiveSheet.Pictures.Delete
Else
.Text = "Close"
With ActiveSheet.Shapes("Rounded Rectangle 1")
End With
End If
End With
End Sub
While your original code was actually working, I made a few slight adjustments to ensure that all (multiple) pictures are included / shown on the sheet and to align these picture below each other. Have a look at the comments in the code and let me know what you think:
Option Explicit
Sub Macro1()
Dim lngRow As Long
Dim strPath As String
Dim picItem As Picture
Dim shtPatient As Worksheet
'If there are multiple pictures then they should be shown
' underneath each other. dblLeft and dblTop will be used
' to place the next picture underneath the last one.
Dim dblTop As Double
Dim dblLeft As Double
Set shtPatient = ThisWorkbook.Worksheets(1)
strPath = "F:\CAD_CAM division\Unsorted Models\"
With shtPatient.Shapes("Rounded Rectangle 1").TextFrame2.TextRange.Characters
If .Text = "Close" Then
.Text = "Preview"
ActiveSheet.Pictures.Delete
Else
.Text = "Close"
For lngRow = 2 To shtPatient.Cells(shtPatient.Rows.Count, "A").End(xlUp).Row
'First check if the file actually exists / can be found and inserted
If Dir(strPath & shtPatient.Cells(lngRow, 1).Value2 & ".jpg") <> "" Then
Set picItem = shtPatient.Pictures.Insert(strPath & shtPatient.Cells(lngRow, 1).Value2 & ".jpg")
'Name the picture so it can be found afterwards again using VBA
picItem.Name = shtPatient.Cells(lngRow, 1).Value2 & ".jpg"
If lngRow = 2 Then
picItem.Top = shtPatient.Range("F2").Top
picItem.Left = shtPatient.Range("F2").Left
dblTop = picItem.Top + picItem.Height + 10
dblLeft = picItem.Left
Else
picItem.Top = dblTop
picItem.Left = dblLeft
dblTop = picItem.Top + picItem.Height + 10
End If
End If
Next lngRow
End If
End With
End Sub

Displaying only a determined range of data

I want to display to the user certain information that exists on a separated worksheet, whenever he clicks a button.
I can set Excel to "go" to this worksheet at the starting line of the range , but I could not find a way to hide everything else.
Is there some method for this, or do I have to hide all rows and columns?
Insert a UserForm in the Workbook's VB Project.
Add a ListBox control to the userform.
Then do something like this code in the UserForm_Activate event code:
Private Sub UserForm_Activate()
Dim tbl As Range
Set tbl = Range("B2:E7") '## Change this to capture the rang you need '
Me.Caption = "Displaying data from " & _
ActiveSheet.Name & "!" & tbl.Address
With ListBox1
.ColumnHeads = False
.ColumnCount = tbl.Columns.Count
.RowSource = tbl.Address
End With
End Sub
Which gives unformatted data from the range:
To export the range as an image, you could create an Image in the UserForm instead of a Listbox. Then this should be enough to get you started.
As you can see from this screenshot, the image might not always come out very clearly. Also, if you are working with a large range of cells, the image might not fit on your userform, etc. I will leave figuring that part out up to you :)
Private Sub UserForm_Activate()
Dim tbl As Range
Dim imgPath As String
Set tbl = Range("B2:E7") '## Change this to capture the rang you need '
imgPath = Export_Range_Images(tbl)
Caption = "Displaying data from " & _
ActiveSheet.Name & "!" & tbl.Address
With Image1
If Not imgPath = vbNullString Then
.Picture = LoadPicture(imgPath)
.PictureSizeMode = fmPictureSizeModeClip
.PictureAlignment = 2 'Center
.PictureTiling = False
.SpecialEffect = 2 'Sunken
End If
End With
End Sub
Function Export_Range_Images(rng As Range) As String
'## Modified by David Zemens with
' credit to: _
' http://vbadud.blogspot.com/2010/06/how-to-save-excel-range-as-image-using.html ##'
Dim ocht As Object
Dim srs As Series
rng.CopyPicture xlScreen, xlPicture
ActiveSheet.Paste
Set ocht = ActiveSheet.Shapes.AddChart
For Each srs In ocht.Chart.SeriesCollection
srs.Delete
Next
'## Modify this line as needed ##'
fname = "C:\users\david_zemens\desktop\picture.jpg"
On Error Resume Next
Kill fname
On Error GoTo 0
ocht.Width = rng.Width
ocht.Height = rng.Height
ocht.Chart.Paste
ocht.Chart.Export Filename:=fname, FilterName:="JPG"
Application.DisplayAlerts = False
ocht.Delete
Application.DisplayAlerts = True
Set ocht = Nothing
Export_Range_Images = fname
End Function
If you record a macro and hide some columns and rows manually, the code will be produced for you, and you will see how it's done.