FindNext within a For Each loop - excel

I need to know how to get FindNext working in my code. It finds the photo inserts it into the column where the code matches, however it does not find the next code in the worksheet, so it keeps overwriting the photos in the first find. Where I have put the comment find next photo1 is where it should be going?
Private Sub cmdInsertPhoto1_Click()
'insert the photo1 from the folder into each worksheet
Dim ws As Worksheet
Dim fso As FileSystemObject
Dim folder As folder
Dim rng As Range, cell As Range
Dim strFile As String
Dim imgFile As String
Dim localFilename As String
Dim pic As Picture
Dim findit As String
Dim finditfirst As String
Application.ScreenUpdating = True
'delete the two sheets if they still exist
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "PDFPrint" Then
Application.DisplayAlerts = False
Sheets("PDFPrint").Delete
Application.DisplayAlerts = True
End If
Next
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "DataSheet" Then
Application.DisplayAlerts = False
Sheets("DataSheet").Delete
Application.DisplayAlerts = True
End If
Next
Set fso = New FileSystemObject
Set folder = fso.GetFolder(ActiveWorkbook.Path & "\Photos1\")
'Loop through all worksheets
For Each ws In ThisWorkbook.Worksheets
ws.Select
Set rng = Range("A:A")
For Each cell In rng
If cell = "CG Code" Then
'find the next adjacent cell value of CG Code
strFile = cell.Offset(0, 1).Value 'the cg code value
imgFile = strFile & ".png" 'the png imgFile name
localFilename = folder & "\" & imgFile 'the full location
'find Photo1 cell and select the adjacent cell to insert the image
findit = Range("A:A").Find(what:="Photo1", MatchCase:=True).Offset(0, 1).Select
ActiveCell.EntireRow.RowHeight = 200 'max row height is 409.5
Set pic = ws.Pictures.Insert(localFilename)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.ShapeRange.Width = 200
.ShapeRange.Height = ActiveCell.MergeArea.Height
.ShapeRange.Top = ActiveCell.MergeArea.Top
.ShapeRange.Left = ActiveCell.MergeArea.Left
.Placement = xlMoveAndSize
End With
'find next photo1
End If
'delete photo after insert
'Kill localFilename
Next cell
Next ws
Application.ScreenUpdating = True
' let user know its been completed
MsgBox ("Worksheets created")
End Sub

Scan column A for both "Photo1" and "CG Code" values to build collections for each. Then iterate the collections to insert the images.
Option Explicit
Private Sub cmdInsertPhoto1_Click()
Dim wb As Workbook, ws As Worksheet, fso As FileSystemObject
Dim rng As Range, cell As Range, pic As Picture
Dim folder As String, imgFile As String
Dim lastrow As Long, i As Long, n As Long
Dim colImages As Collection, colPhotos As Collection
Set colImages = New Collection
Set colPhotos = New Collection
Set fso = New FileSystemObject
Set wb = ActiveWorkbook
folder = wb.Path & "\Photos1\"
Application.ScreenUpdating = False
For Each ws In wb.Sheets
'delete the two sheets if they still exist
If ws.Name = "PDFPrint" Or ws.Name = "DataSheet" Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
Else
' find images and photos
lastrow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For Each cell In ws.Range("A1:A" & lastrow)
If cell = "CG Code" Then
imgFile = folder & cell.Offset(0, 1) & ".png"
' check exists
If fso.FileExists(imgFile) Then
colImages.Add imgFile
Else
MsgBox imgFile & " not found", vbCritical
Exit Sub
End If
ElseIf cell = "Photo1" Then
colPhotos.Add "'" & ws.Name & "'!" & cell.Offset(0, 1).Address
End If
Next
End If
Next
' copy images to sheets
For i = 1 To colImages.Count
imgFile = colImages(i)
If i <= colPhotos.Count Then
Set cell = Range(colPhotos(i))
cell.RowHeight = 200 'max row height is 409.5
Set pic = cell.Parent.Pictures.Insert(imgFile) ' ws
With pic.ShapeRange
.LockAspectRatio = msoFalse
.Width = 200
.Height = cell.MergeArea.Height
.Top = cell.MergeArea.Top
.Left = cell.MergeArea.Left
pic.Placement = xlMoveAndSize
End With
n = n + 1
Else
MsgBox "No location for " & imgFile, vbCritical, i
Exit Sub
End If
Next
Application.ScreenUpdating = True
' let user know its been completed
MsgBox n & " images inserted ", vbInformation
End Sub

Related

Get inserted image to adjust the row height in Excel

I am having an issue getting the row height to adjust in Excel to the inserted image. I have tried cell.EntireRow = pic.Height but it does not adjust the row to match image height. It loops through several worksheets to find the code then selects the next empty cell to it so the image gets inserted there. Also not sure if this is the correct way to go through the entire worksheet as the is usually more that one Photo1 in there. If I can get this figured out, I can do the photo2 and photo3 using whatever solution is found.
Here is my code
Private Sub cmdInsertPhoto1_Click()
'insert the photo1 from the folder into each worksheet
Dim ws As Worksheet
Dim fso As FileSystemObject
Dim folder As folder
Dim rng As Range, cell As Range
Dim strFile As String
Dim imgFile As String
Dim localFilename As String
Dim pic As Picture
Dim findit As String
Application.ScreenUpdating = True
'delete the two sheets if they still exist
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "PDFPrint" Then
Application.DisplayAlerts = False
Sheets("PDFPrint").Delete
Application.DisplayAlerts = True
End If
Next
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "DataSheet" Then
Application.DisplayAlerts = False
Sheets("DataSheet").Delete
Application.DisplayAlerts = True
End If
Next
Set fso = New FileSystemObject
Set folder = fso.GetFolder(ActiveWorkbook.Path & "\Photos1\")
'Loop through all worksheets
For Each ws In ThisWorkbook.Worksheets
ws.Select
Set rng = Range("A:A")
ws.Unprotect
For Each cell In rng
If cell = "CG Code" Then
'find the next adjacent cell value of CG Code
strFile = cell.Offset(0, 1).Value 'the cg code value
imgFile = strFile & ".png" 'the png imgFile name
localFilename = folder & "\" & imgFile 'the full location
'just find Photo1 cell and select the adjacent cell to insert the image
findit = Range("A:A").Find(what:="Photo1", MatchCase:=True).Offset(0, 1).Select
Set pic = ws.Pictures.Insert(localFilename)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.ShapeRange.Width = 200
.ShapeRange.Height = 200 'max row height is 409.5
.Placement = xlMoveAndSize
End With
cell.EntireRow = pic.Height
End If
'delete photo after insert
'Kill localFilename
Next cell
Next ws
Application.ScreenUpdating = True
' let user know its been completed
MsgBox ("Worksheets created")
End Sub
What it currently looks like
You have to use the rowheight property of the range object: cell.EntireRow.RowHeight= pic.Height
As you wrote it (cell.EntireRow = pic.Height) you implicitly used the default property of cell.EntireRow which is value)
Managed to solve it. for anyone else its cell was selected so, this works for me:
'just find Photo1 cell and select the adjacent cell to insert the image
findit = Range("A:A").Find(what:="Photo1", MatchCase:=True).Offset(0, 1).Select
ActiveCell.EntireRow.RowHeight = 200 'max row height is 409.5
Set pic = ws.Pictures.Insert(localFilename)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.ShapeRange.Width = 200
'.ShapeRange.Height = 200 'max row height is 409.5
.ShapeRange.Height = ActiveCell.MergeArea.Height
.ShapeRange.Top = ActiveCell.MergeArea.Top
.ShapeRange.Left = ActiveCell.MergeArea.Left
.Placement = xlMoveAndSize
End With

For Each two times or?

I try to get a number copied from one list in one sheet to a new created sheet in specific cell. The code first check if there already exist a sheet with this name, if not it creates a new sheet and then add it and paste in a table from another sheet. After this is done I also want a number to be filled in from the list but I dont get it to work with FOR EACH as i did with first one. I really don't know how i shall do it? Im trying to get the inum to be written in each new sheet.
`Sub Sample()
Dim ws As Worksheet
Dim Row As Long
Dim inu As Long
Dim i As Long
'~~> Set this to the relevant worksheet
Set ws = Sheets("Röd")
Set wsi = Sheets("Röd")
With ws
'~~> Find last row in Column A
Row = .Range("A" & .Rows.Count).End(xlUp).Row
With wsi
inu = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Loop through the range
For i = 3 To Row
'~~> Check if cell is not empty
If Len(Trim(.Range("A" & i).Value2)) <> 0 Then
'~~> Whatever this fuction does. I am guessing it
'~~> checks if the sheet already doesn't exist
If SheetCheck(.Range("A" & i)) = False Then
With ThisWorkbook
'~~> Add the sheet
.Sheets.Add After:=.Sheets(.Sheets.Count)
'~~> Color the tab
.Sheets(.Sheets.Count).Tab.Color = RGB(255, 0, 0)
'~~> Name the tab
.Sheets(.Sheets.Count).Name = Left(ws.Range("A" & i).Value2, 30)
Sheets("Utredningsmall").Range("A1:B22").Copy Destination:=Sheets(Sheets.Count).Range("A1")
.Sheets(.Sheets.Count).Range("B4").Value = ws.Range("A" & i).Value
Columns("A:B").AutoFit
Rows("1:25").AutoFit
For j = 3 To inu
'If Len(Trim(Range("B" & inu).Value2)) <> 0 Then
Sheets(Sheets.Count).Range("B3").Value2 = wsi.Range("B" & j).Value2
'End If
Next j
End With
End If
End If
Next i
End With
End With
End Sub`
Create Worksheets from List
Option Explicit
Sub createWorksheets()
Dim wb As Workbook: Set wb = ThisWorkbook ' Workbook containing this code.
Dim MyRange As Range
With wb.Worksheets("Röd").Range("A3")
Set MyRange = .Resize(.Worksheet.Cells(.Worksheet.Rows.Count, .Column) _
.End(xlUp).Row - .Row + 1)
End With
Application.ScreenUpdating = False
Dim MyCell As Range
For Each MyCell In MyRange.Cells
If Len(MyCell) > 0 Then
If Not SheetCheck(wb, MyCell.Value) Then
With wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
' Data
wb.Worksheets("Utredningsmall").Range("A1:B22").Copy _
Destination:=.Range("A1")
.Range("B3").Value = MyCell.Offset(, 1).Value
.Range("B4").Value = MyCell.Value
.Name = Left(MyCell.Value, 30)
' Formats
.Tab.Color = RGB(255, 0, 0)
.Columns("A:B").AutoFit
.Rows("1:25").AutoFit
End With
End If
End If
Next MyCell
Application.ScreenUpdating = True
End Sub
Function SheetCheck( _
wb As Workbook, _
ByVal SheetName As String) _
As Boolean
On Error Resume Next
Dim sh As Object: Set sh = wb.Sheets(SheetName)
On Error GoTo 0
SheetCheck = Not sh Is Nothing
End Function
Sub Röd()
Dim MyCell As Range, MyRange As Range
Dim ws As Worksheets
Dim inum As Range, Myinum As Range
'This Macro will create separate tabs based on a list in Distribution Tab A3, B3 down
Set MyRange = Sheets("Röd").Range("A3")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
Application.DisplayAlerts = False
For Each MyCell In MyRange
If SheetCheck(MyCell) = False And MyCell <> "" Then
Sheets.Add After:=Sheets(Sheets.Count) 'creates a new worksheet
Sheets(Sheets.Count).Tab.Color = RGB(255, 0, 0)
Sheets(Sheets.Count).Name = Left(MyCell.Value2, 30) ' renames the new worksheet
Sheets("Utredningsmall").Range("A1:B22").Copy Destination:=Sheets(Sheets.Count).Range("A1")
Sheets(Sheets.Count).Range("B4").Value = MyCell.Value2
Sheets(Sheets.Count).Range("B3").Value = MyCell.Offset(, 1).Value
Columns("A:B").AutoFit
Rows("1:25").AutoFit
End If
Next
Application.DisplayAlerts = True
End Sub
OR
Sub Röd()
Dim MyCell As Range, MyRange As Range
Dim ws As Worksheets
Dim inum As Range, Myinum As Range
'This Macro will create separate tabs based on a list in Distribution Tab A3, B3 down
Set MyRange = Sheets("Röd").Range("A3")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
Application.DisplayAlerts = False
For Each MyCell In MyRange
If SheetCheck(MyCell) = False And MyCell <> "" Then
Sheets.Add After:=Sheets(Sheets.Count) 'creates a new worksheet
Sheets(Sheets.Count).Tab.Color = RGB(255, 0, 0)
Sheets(Sheets.Count).Name = Left(MyCell.Value2, 30) ' renames the new worksheet
Sheets("Utredningsmall").Range("A1:B22").Copy Destination:=Sheets(Sheets.Count).Range("A1")
Sheets(Sheets.Count).Range("B4").Value = MyCell.Value2
Sheets(Sheets.Count).Range("B3").Value = MyCell.Offset(, 1).Value
Columns("A:B").AutoFit
Rows("1:25").AutoFit
End If
Next
Application.DisplayAlerts = True
End Sub
Function:
Function SheetCheck(MyCell As Range) As Boolean
Dim ws As Worksheet
SheetCheck = False
For Each ws In ThisWorkbook.Worksheets
If ws.Name = Left(MyCell.Value, 30) Then
SheetCheck = True
End If
Next
End Function
Both these codes works now. They go through a list and create a new sheet for each cell in the list.

How to copy a picture from another worksheet and paste inside a cell comment

So I came around the net to find answers for this but found none, what I want my code to do is open a worksheet from a folder get the photo from that worksheet and finally paste to a comment inside a cell in my current workbook. here's my code
Dim folder As String
Private Sub Workbook_Open()
folder = ThisWorkbook.path
End Sub
Sub populatePDA()
'Application.ScreenUpdating = False
Dim wb As Workbook
Dim ws As Variant
Dim path As String
Dim fileName As String
Dim p As Picture
Dim img As Variant
Dim cb As Comment
Set ws = ThisWorkbook.Sheets("PDA")
path = folder & "\PDA\"
fileCount = 0
fileName = Dir(path & "*.xlsm")
Do While fileName <> ""
Set wb = Workbooks.Open(path & fileName) 'Open Workbook
ws.Range("A3:F3").Insert (xlShiftDown)
ws.Range("A3") = wb.Sheets(1).Range("B16").Value 'Item Name
ws.Range("B3") = wb.Sheets(1).Range("B17").Value 'S/N
ws.Range("C3") = wb.Sheets(1).Range("G7").Value 'Description
ws.Range("D3") = wb.Sheets(1).Range("H12").Value 'Calibration
ws.Range("E3") = wb.Sheets(1).Range("H13").Value 'Expiration
For Each p In wb.Sheets(1).Pictures
p.CopyPicture
Set img = ws.Paste
Set cb = ws.Range("F3").AddComment
cb.Text Text:=""
cb.Shape.Fill.UserPicture (img)
Next p
wb.Close
fileName = Dir
Loop
'Application.ScreenUpdating = True
End Sub
You do not say anything and I finished something...
I modified a little your code making it to add a new insertion in the working sheet, for a new open file, and process them as (I understood) you need. Please, test the next code:
Sub populatePDA()
Dim fileName As String, path As String
Dim ws As Worksheet, wb As Workbook, p As Shape, fileCount As Long
Dim cb As Comment, i As Long, arrCol As Variant, k As Long
arrCol = Split("A,B,C,D,E", ",")
Set ws = ThisWorkbook.Sheets("PDA")
path = ThisWorkbook.path & "\PDA\"
fileCount = 0
fileName = Dir(path & "*.xlsm")
k = 2
Application.ScreenUpdating = False
Do While fileName <> ""
Set wb = Workbooks.Open(path & fileName) 'Open Workbook
k = k + 1
ws.Range("A" & k & ":E" & k).Insert (xlShiftDown)
ws.Range("A" & k) = wb.Sheets(1).Range("B16").Value 'Item Name
ws.Range("B" & k) = wb.Sheets(1).Range("B17").Value 'S/N
ws.Range("C" & k) = wb.Sheets(1).Range("G7").Value 'Description
ws.Range("D" & k) = wb.Sheets(1).Range("H12").Value 'Calibration
ws.Range("E" & k) = wb.Sheets(1).Range("H13").Value 'Expiration
i = 2
For Each p In wb.Sheets(1).Shapes
If p.Type = msoPicture Then
i = i + 1
ws.Activate
If Not ws.Range(arrCol(i - 3) & k).Comment Is Nothing Then _
ws.Range(arrCol(i - 3) & k).Comment.Delete
Set cb = ws.Range(arrCol(i - 3) & k).AddComment
cb.text text:=""
With cb.Shape
.width = p.width: .height = p.height
End With
cb.Shape.Fill.UserPicture (SelImPathCh(p, wb))
End If
Next p
ws.Activate
wb.Close False
fileName = Dir
Loop
ws.UsedRange.EntireColumn.AutoFit
Application.ScreenUpdating = False
End Sub
The function able to make the picture insertion is the next (it is called by the main above code):
Private Function SelImPathCh(img As Shape, Optional wb As Workbook) As String
Dim ch As ChartObject, sh As Worksheet, sFile As String
If Not wb Is Nothing Then Set sh = wb.Sheets(1)
sFile = ThisWorkbook.path & "\Pict1.jpg"
Set ch = sh.ChartObjects.Add(left:=1, _
top:=1, width:=img.width, _
height:=img.height)
If Not wb Is Nothing Then wb.Activate: sh.Activate
img.Copy: ch.Activate: ActiveChart.Paste
ch.Chart.Export sFile
ch.Delete
SelImPathCh = sFile
End Function
The wb variable is Optional only for my testing need. I used a sheet of the existing working workbook and I skipped it when called the function...
UserPicture works with file path. Try below method, it should work.
Set cb = Worksheets(2).Range("F3").AddComment
cb.Text Text:=""
cb.Shape.Fill.UserPicture ("FILE_PATH")
And if you want to copy picture from worksheet only, then you can export the pictures in tmp folder using the following code and then give the same path in UserPicture.
Sub SaveImages()
Dim shpName As Variant
Dim shp As Shape
Dim ppt As Object, ps As Variant, slide As Variant
Set ppt = CreateObject("PowerPoint.application")
Set ps = ppt.presentations.Add
Set slide = ps.slides.Add(1, 1)
For Each shp In ActiveSheet.Shapes
shpName = "D:\\tmp.jpg"
shp.Copy
With slide
.Shapes.Paste
.Shapes(.Shapes.Count).Export shpName, 2
.Shapes(.Shapes.Count).Delete
End With
Next shp
With ps
.Saved = True
.Close
End With
ppt.Quit
Set ppt = Nothing
End Sub

How can I keep a cell's hyperlink after replacing its text with a picture?

I am trying to replace some hyperlinked text in cells but keep the hyperlink there. In other words, instead of clicking the text to take you to the website that the hyperlink leads to, you would click the picture to go to that website.
Option Explicit
Sub test()
Dim MyPath As String
Dim CurrCell As Range
Dim Cell As Range
Dim LastRow As Long
Dim i As Long
Application.ScreenUpdating = False
MyPath = "C:\Users\xxx\Pictures"
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
Set CurrCell = ActiveCell
LastRow = Cells(Rows.Count, "B").End(xlUp).Row
For i = 1 To LastRow
Set Cell = Cells(i, "B")
If Cell.Value <> "" Then
If Dir(MyPath & Cell.Value & ".png") <> "" Then
ActiveSheet.Pictures.Insert(MyPath & Cell.Value & ".png").Select
With Selection.ShapeRange
.LockAspectRatio = msoFalse
.Left = Cell.Left
.Top = Cell.Top
.Width = Cell.Width
.Height = Cell.Height
End With
Else
Cell.Value = "N/A"
End If
End If
Next i
CurrCell.Select
Application.ScreenUpdating = True
End Sub
A Picture is a seperate object from the Cell. Your code is placing the picture over a cell, it's not actually "In" the cell.
You could move the hyperlink from the cell, to the Picture, like this
Sub test()
Dim MyPath As String
Dim Cell As Range
Dim shp As ShapeRange
Dim ws As Worksheet
Dim rng As Range
Dim ext As String
Dim HyperLinkAddr As String
Application.ScreenUpdating = False
Set ws = ActiveSheet
MyPath = "C:\Users\" & Environ$("UserName") & "\Pictures"
ext = ".png"
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
With ws
Set rng = .Range(.Cells(1, 2), .Cells(.Rows.Count, "B").End(xlUp))
End With
For Each Cell In rng
If Cell.Value <> vbNullString Then
If Dir(MyPath & Cell.Value2 & ext) <> "" Then
' Get a reference to the inserted shape, rather than relying on Selection
Set shp = ws.Pictures.Insert(MyPath & Cell.Value2 & ext).ShapeRange
With shp
.LockAspectRatio = msoFalse
.Left = Cell.Left
.Top = Cell.Top
.Width = Cell.Width
.Height = Cell.Height
If Cell.Hyperlinks.Count > 0 Then
HyperLinkAddr = Cell.Hyperlinks(1).Address
Cell.Hyperlinks.Delete
ws.Hyperlinks.Add _
Anchor:=.Item(1), _
Address:=HyperLinkAddr
End If
End With
Else
Cell.Value = "N/A"
End If
End If
Next
Application.ScreenUpdating = True
End Sub

Create a new sheet and coping data

I have the below code which will create a new worksheet on selecting A2 which works fine, but what I am also trying to do is to also copy the data in the row 2 and copy this across into the new sheet. Along with this if I click on A3 to create another worksheet, I want to copy the data in row 3 across to that sheet, and so on.
Any ideas??
Private Sub Worksheet_SelectionChange()
Dim cTab As Integer
cTab = ActiveCell.Row - 1
If Selection.Count = 1 Then
If Not Intersect(Target, Range("A2:A201")) Is Nothing Then
Dim WS1 As Worksheet
On Error Resume Next
Set WS1 = Worksheets(cTab & ".")
If WS1 Is Nothing Then
Application.ScreenUpdating = False
ActiveCell = cTab & "."
Sheets("Template").Visible = True
Sheets("Template").Select
Sheets("Template").Copy After:=Sheets(Worksheets.Count)
ActiveSheet.Name = cTab & "."
'Sheets("Template").Visible = False
Application.ScreenUpdating = True
Else
Sheets(cTab & ".").Select
End If
End If
End If
End Sub
You could modify your code to something like the below, which should copy the rows as you described.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cTab As Integer
Dim BaseSht As Worksheet
Dim NewSht As Worksheet
Set BaseSht = ActiveSheet
cTab = ActiveCell.Row - 1
If Selection.Count = 1 Then
If Not Intersect(Target, Range("A2:A201")) Is Nothing Then
Dim WS1 As Worksheet
On Error Resume Next
Set WS1 = Worksheets(cTab & ".")
If WS1 Is Nothing Then
Application.ScreenUpdating = False
ActiveCell = cTab & "."
Sheets("Template").Visible = True
Sheets("Template").Copy After:=Sheets(Worksheets.Count)
ActiveSheet.Name = cTab & "."
Set NewSht = ActiveSheet
BaseSht.Select
'Copy row to new sheet
BaseSht.Range(ActiveCell.Address & ":" & BaseSht.Cells(ActiveCell.Row, Columns.Count).End(xlToLeft).Address).Copy NewSht.Range("A" & cTab + 1)
'Sheets("Template").Visible = False
Application.ScreenUpdating = True
Else
Sheets(cTab & ".").Select
End If
End If
End If
End Sub

Resources