Way to tell if ActiveSheet.Pictures.Insert(Filename).Select Fails? - excel

I have made an excel macro for my company that mass inserts images in a picture folder by their cell value.
The cell.Value contains the SKU number, so I add the rest of the file path in a for each loop and then use ActiveSheet.Pictures.Insert(Filename).Select.
Everything works great, but when files are not found within the picture folder, the filepath is left in the cell. I would like to change all cells that don't find an image to say "No Image" rather than the filepath.
Is there anyway to test if ActiveSheet.Pictures.Insert(Filename).Select failed to find an image, then I could rewrite the cell.Value if it failed?
I've tried to add another For each loop to see if the cell.Value has contents in it. This is because the insert image portion runs a cell.ClearContents once it's done so all the cells with images inserted don't have their SKU numbers behind the image. I'm having trouble with this process as well and would like to avoid for eaching through the selection twice.
Option Explicit
Dim rng As Range
Dim cell As Range
Dim Filename As String
Sub PictureImport()
Set rng = ActiveSheet.Range("A2:A3000")
For Each cell In Selection '<-- *For Each cell In rng* For Hard Coded selection
If cell.Value <> "" Then cell.Value = "\\Pictures\" & cell.Value & ".jpg" '<---NEEDS TO SKIP HEADER
Next
Dim theShape As Shape
Dim xRg As Range
Dim xCol As Long
On Error Resume Next
Application.ScreenUpdating = False
Set rng = ActiveSheet.Range("A2:A3000") ' <---- CHANGE TO START AT A2 TO SKIP HEADER
For Each cell In Selection
Filename = cell
If InStr(UCase(Filename), "JPG") > 0 Then '<--- ONLY USES JPG'S
ActiveSheet.Pictures.Insert(Filename).Select
Set theShape = Selection.ShapeRange.Item(1)
If theShape Is Nothing Then GoTo isnill
xCol = cell.Column
Set xRg = Cells(cell.Row, xCol)
With theShape
.LockAspectRatio = msoFalse
' Shape position and sizes stuck to cell shape
.Top = cell.Top + 1
.Left = cell.Left + 1
.Height = cell.Height - 2
.Width = cell.Width - 2
' Move with the cell (and size, though that is likely buggy)
.Placement = xlMoveAndSize
End With
cell.ClearContents
isnill:
Set theShape = Nothing
Range("A2").Select
End If
Next
Debug.Print "Done " & Now
Application.ScreenUpdating = True
End Sub
Actual Results as stands: Images in the pictures folder will be inserted to the size of the cell, but will leave the cells that could not find a picture with the file path still in the the cell value.

Related

Set cell width and hight to normal even though i copy a large text.file into it

I am trying to copy a text file into a cell, and everything works except that the cells AutoFit, which I don't want it to. I want it to stay the same width, but I am not sure how to do this. I guess it should be under Set SNRCode = Range("B2") but I have tried to both set the cell values and cancel autofit.
Dim arkNavne As Range
Dim cell As Range
Dim navn As String
Dim i As Long
Dim SNRCode As Range
Dim matchCell As Range
Dim targetSNR As String
Application.ScreenUpdating = False
Worksheets("Overview").Activate
Set arkNavne = Range("B4:B14")
For Each cell In arkNavne
navn = cell.Value
Worksheets(navn).Activate
Set SNRCode = Range("B2")
For i = 1 To 500
If SNRCode <> "" Then
targetSNR = "_" & SNRCode.Value & ".lic"
Set matchCell = Worksheets("FilesImport").Range("A1:A200").Find(targetSNR, Lookat:=xlPart)
If matchCell Is Nothing Then
SNRCode.Offset(0, 1).Value = "NO MATCH"
Else
SNRCode.Offset(0, 1).Value = matchCell.Value
With matchCell.Font
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0
End With
End If
Set SNRCode = SNRCode.Offset(0, 2)
Else
Set SNRCode = SNRCode.Offset(0, 1)
End If
Next i
Next cell
End Sub
This will likely be a handy site for you, explaining different ways to set column width
Columns("A").ColumnWidth=10 or Columns(1).ColumnWidth=10
Range("B2").EntireColumn.ColumnWidth=10 or Cells(2,2).EntireColumn.ColumnWidth=10
You can also capture multiple rows by using " : ", for example
Columns(A:Z).ColumnWidth=10

Clear specified range of contents and shapes

I need to remove all the content from a specific cell range (Y1:CZ100) in a worksheet (Drawing) and reset all cell's borders linestyles, fill color etc to none. The range can have different content but will always be populated with various group objects and autoshapes as well as text, merged cells and cell borders/fill colour etc. I've written the following macro to do this:
Option Explicit
Sub Remove_DOD() 'Remove Drive on Dock drawing, Product Count Table, reset formulae
Dim sh As Shape
Dim DrawRange As Range
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Remove DOD Drawing and Product Count table)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
With Worksheets("Drawing")
Application.ScreenUpdating = False
Set DrawRange = Range("Y1:CZ100")
With DrawRange
.UnMerge
.Interior.Color = xlNone
.Borders.LineStyle = xlNone
.ClearContents
End With
For Each sh In .Shapes
If Not Application.Intersect(sh.TopLeftCell, DrawRange) Is Nothing Then
If sh.Type = msoGroup Or sh.Type = msoAutoShape Then sh.Delete
End If
Next sh
Application.ScreenUpdating = True
End With
End Sub
It works most of the time but will sometimes fail with Run-time error '1004': Application-defined or object-defined error at the statement If Not Application.Intersect(sh.TopLeftCell, DrawRange) Is Nothing Then and I cannot figure out what causes it to happen. When the error does occur, the With loop to clearcontent, unmerge etc always completes but some group items are still present in the range and other times they are all cleared.
Any insights as to a solution would be most welcome.
Update:
I tried changing the method for selecting the shapes to be deleted and stopped testing for the type of shape (since all in the range need to be deleted). This is the code but it still sometimes fails with same Run-time error 1004 at s = .TopLeftCell.Address & ":" & .BottomRightCell.Address. The error seems to occur only after the contents of the Drawing range have been replaced with new shapes and the macro is run again. Sometimes it errors immediately and none of the new shapes are deleted but it can also be when and it has reached the end of deleting all these new shapes (i.e. on the last iteration of With sh). I think the error is because the value of sh is invalid but don't see why this happens. Perhaps I need to insert some way of testing the value of sh? Also, I have seen old posts on other forums with similar issues but solutions never provided.
Option Explicit
Sub Remove_DOD() 'Remove Drive on Dock drawing, Product Count Table, reset formulae
Dim sh As Shape
Dim S As String
Dim DrawRange As Range
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Remove DOD Drawing and Product Count table)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
With Worksheets("Drawing")
Application.ScreenUpdating = False
Set DrawRange = Range("Y1:CZ100")
With DrawRange
.UnMerge
.Interior.Color = xlNone
.Borders.LineStyle = xlNone
.ClearContents
End With
For Each sh In .Shapes
With sh
s = .TopLeftCell.Address & ":" & .BottomRightCell.Address
End With
If Not Intersect(DrawRange, .Range(s)) Is Nothing Then
sh.Delete
End If
Next
Application.ScreenUpdating = True
End With
End Sub
This fails the same way at Set shRange = Range(sh.TopLeftCell.Address & ":" & sh.BottomRightCell.Address) statement:
Option Explicit
Sub Remove_DOD() 'Remove Drive on Dock drawing, Product Count Table, reset formulae
Dim sh As Shape
Dim s As String
Dim DrawRange, shRange As Range
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Remove DOD Drawing and Product Count table)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
With Worksheets("Drawing")
Application.ScreenUpdating = False
Set DrawRange = Range("Y1:CZ100")
With DrawRange
.UnMerge
.Interior.Color = xlNone
.Borders.LineStyle = xlNone
.ClearContents
End With
For Each sh In .Shapes
Set shRange = Range(sh.TopLeftCell.Address & ":" & sh.BottomRightCell.Address)
If Not Intersect(shRange, DrawRange) Is Nothing Then sh.Delete
Next
Application.ScreenUpdating = True
End With
End Sub
Not very satisfactory but the following now works. Note the inclusion of On Error Resume Next in the For Each sploop. This forces the loop to exit when the error is encountered.
Option Explicit
Sub Remove_DODTest() 'Remove Drive on Dock drawing, Product Count Table, reset formulae
Dim sh As Shape
Dim DrawRange As Range
With Worksheets("Drawing")
Application.ScreenUpdating = False
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Remove DOD Drawing and Product Count table
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set DrawRange = .Range("Y1:CZ100")
With DrawRange
.UnMerge
.Interior.Color = xlNone
.Borders.LineStyle = xlNone
.ClearContents
End With
For Each sh In .Shapes
On Error Resume Next
If Not Application.Intersect(sh.TopLeftCell, DrawRange) Is Nothing Then sh.Delete
Next sh
End With
Application.ScreenUpdating = True
End Sub

Get cell formatting

Is there a function to get the activecell formatting? e.g. background color, font, font color, cell border, font size etc.
I want to update the format of an entire worksheet based on a formatted cell before action (i.e. the format I want to change) by another formatted cell (i.e. the format I want to apply).
Sub Rep_all_format()
Dim fmt_bef As CellFormat
Dim fmt_aft As CellFormat
Dim rngReplace As Boolean
Dim msg As String
Dim Sh As Worksheet
Dim Rg As Range
Dim ppos1 As Range
Dim ppos2 As Range
Dim Find As String
Dim Remplace As String
Set ppos1 = Application.InputBox(Prompt:="Select the cell format you wanna change", Title:="Remplace", Default:=ActiveCell.Address, Type:=8)
Set ppos2 = Application.InputBox(Prompt:="Select the cell format you wanna apply", Title:="Select", Type:=8)
Find = ppos1.FormatConditions 'this is theorical I do not know the function
Remplace = ppos2.FormatConditions 'this is theorical I do not know the function
Application.ScreenUpdating = False
Set fmt_bef = Application.FindFormat
Set fmt_aft = Application.ReplaceFormat
For Each Sh In ThisWorkbook.Worksheets
Set Rg = Sh.UsedRange
With fmt_bef
.Clear
.FormatConditions = Find
End With
With fmt_aft
.Clear
.FormatConditions = Remplace
End With
Rg.Replace What:="", Replacement:="", _
SearchFormat:=True, ReplaceFormat:=True
Next
fmt_bef.Clear
fmt_aft.Clear
Application.ScreenUpdating = True
MsgBox ("The desired format has been applied through all the workbook")
End Sub
Assuming, from the code that you have provided, that your cell has been formatted using Conditional Formatting, you need to access is the Range.DisplayFormat property.
Note that I showed only some of the formatting options for a cell. There is documentation online for other formatting options (eg other borders, numberformat, etc) but this should get you started.
For example:
Option Explicit
Sub foo()
Dim R As Range, C As Range
Dim fc As FormatCondition
Set R = Range(Cells(1, 1), Cells(5, 1))
For Each C In R
With C.DisplayFormat
Debug.Print .Interior.Color
Debug.Print .Font.Name
Debug.Print .Font.Color
Debug.Print .Borders(xlEdgeLeft).LineStyle ' etc
Debug.Print .Font.Size
End With
Stop
Next C
End Sub
If the cell has been formatted manually, or directly using code, then just access the various properties directly, not using the DisplayFormat property eg:
For Each C In R
With C
Debug.Print .Interior.Color
Debug.Print .Font.Name
Debug.Print .Font.Color
Debug.Print .Borders(xlEdgeLeft).LineStyle ' etc
Debug.Print .Font.Size
End With
Stop
Next C
What you are looking for are the Range.Interior and Range.Font properties etc.
You can see some examples in the links below:
https://learn.microsoft.com/en-us/office/vba/api/excel.font(object)
https://learn.microsoft.com/en-us/office/vba/api/excel.interior(object)
https://learn.microsoft.com/en-us/office/vba/api/excel.border(object)

Using Len(Dir) to check for picture file and insert into file

I am trying to insert pictures into a column F. Links for picture files are listed in column C.
I researched on-line, and found a way.
If the file is there it works, if cell in column C is left blank it leaves the corresponding cell in column F blank, but if the link contains a file name does not exist it stops.
If the filename is corrupt = stated but not existing, I want to leave the cell blank and move on to the next cell.
Sub Insertpicture()
Dim myPict As Picture
Dim curWks As Worksheet
Dim myRng As Range
Dim myCell As Range
Set curWks = Sheets(1)
curWks.Pictures.Delete
With curWks
Set myRng = .Range("c2", .Cells(.Rows.Count, "c").End(xlUp))
End With
For Each myCell In myRng.Cells
If Trim(myCell.Value) = "" Then
‘do nothing, move on
ElseIf Len(Dir(myCell.Value)) = 0 Then
’here I want to leave the cell empty and just move on to check next cell
Else
With myCell.Offset(0, 3)
Set myPict = myCell.Parent.Pictures.Insert(myCell.Value)
myPict.Top = .Top
myPict.Width = .Width
myPict.Height = .Height
myPict.Left = .Left
myPict.Placement = xlMoveAndSize
End With
End If
Next myCell
End Sub
If the cell is empty, Dir(myCell.Value) will be the same thing as Dir(vbNullString), which will return the next result from your last Dir command. Since Dir holds state this way, it isn't the ideal way to determine if a file (or lack of a file) exists. I'd use the Scripting.FileSystemObject instead:
'Add a reference to Microsoft Scripting Runtime
Sub Insertpicture()
Dim myPict As Picture
Dim curWks As Worksheet
Dim myRng As Range
Dim myCell As Range
Set curWks = Sheets(1)
With curWks
.Pictures.Delete
Set myRng = .Range("c2", .Cells(.Rows.Count, "c").End(xlUp))
End With
With New Scripting.FileSystemObject
For Each myCell In myRng.Cells
If IsError(myCell.Value) Then
'do nothing, move on
ElseIf Not .FileExists(myCell.Value) Then
'leave the cell empty
myCell.Value = vbNullString
Else
With myCell.Offset(0, 3)
'You need to test to see if it's an image file here.
Set myPict = myCell.Parent.Pictures.Insert(myCell.Value)
myPict.Top = .Top
myPict.Width = .Width
myPict.Height = .Height
myPict.Left = .Left
myPict.Placement = xlMoveAndSize
End With
End If
Next myCell
End With
End Sub
Note that you also need to test for errors in the cells before you use the values and you should also either add error handling or test to see if the file you found was a valid image file.

Loop through all font colored cells in a range

I extracted the data according to ciriteria and marked them as blue. I'm looking for help with a Macro which would loop through all font colored cells (Blue) in a range.
I want to use only font colored cells in a range and mark in different color. And Msgbox show data that meet the criteria.
I had trouble finding information on looping through cells which contain only a specified colour. Anyone know how this could be done?
Dim i As Long
Dim LastRow As Integer
LastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Msg = "Data:"
For i = 1 To LastRow
If Cells(i + 1, 2).Value - Cells(i, 2).Value <> 0 Then
Cells(i, 2).Font.Color = vbBlue
Cells(i, 1).Font.Color = vbBlue
For Each Cell In Range("A:B")
If Cells(i, 1).Font.Color = vbBlue And Cells(i + 1, 1).Value - Cells(i, 1).Value > 4 Then
Cells(i, 2).Font.Color = vbGreen
Cells(i, 1).Font.Color = vbGreen
End If
Next
Msg = Msg & Chr(10) & i & " ) " & Cells(i, 2).Value & " : " & " --> " & Cells(i, 1).Value
End If
Next i
MsgBox Msg, vbInformation
There are multiple issues with your code:
Your loops are nested. You are searching through all the data every time you prepare one line. ==> Move the inner loop behind the loop you're coloring in.
The result message Msg = Msg & Chr(10) & i is constructed outside of the If Cells(i, 1).Font.Color = vbBlue And... condition, meaning that every line will be written into the result String. Move this part inside the 2nd loop, and the string should be contain only blue lines.
Also, please don't loop through For Each Cell In Range("A:B"). This will examine every cell in those columns, way beyond those who contain actual data. Use LastRow as in the first loop.
I believe you should be able to use the Find function to do this....
For example, select some cells on a sheet then execute:
Application.FindFormat.Interior.ColorIndex = 1
This will colour the cells black
Now execute something like:
Debug.Print ActiveCell.Parent.Cells.Find(What:="*", SearchFormat:=True).Address
This should find those cells. So you should be able to define your required Font with the FindFormat function.
BTW, make sure to test to see if the range returned is nothing for the case where it cant find any matches..
Hope that helps.
Edit:
The reason I would use the find method is because your code checks each cell in two columns. The Find method should be much quicker.
You will need to have a Do - While loop to find all cells in a range which is common with the Find function in VBA.
If you run this function, it should debug the address of any font matches that you are looking for - for a particular sheet. This should give you the idea...
Sub FindCells()
Dim rData As Range, rPtr As Range
Set rData = ActiveSheet.Range("A:B")
Application.FindFormat.Clear
Application.FindFormat.Font.Color = vbBlue
Set rPtr = rData.Find(What:="*", SearchFormat:=True)
If Not rPtr Is Nothing Then
Debug.Print rPtr.Address
End If
Application.FindFormat.Clear
Application.FindFormat.Font.Color = vbGreen
Set rPtr = rData.Find(What:="*", SearchFormat:=True)
If Not rPtr Is Nothing Then
Debug.Print rPtr.Address
End If
End Sub
Ok then - sorry keep getting distracted..
This code will search for cells with your fonts for a particular data range.
I believe you just need to implement your logic into the code...
Option Explicit
Public Sub Test()
Dim rData As Range
Set rData = Sheet1.Range("A:B")
Call EnumerateFontColours(rData, vbBlue)
Call EnumerateFontColours(rData, vbGreen)
End Sub
Public Sub EnumerateFontColours(ByVal DataRange As Range, ByVal FontColour As Long)
Dim rPtr As Range
Dim sStartAddress As String
Dim bCompleted As Boolean
Application.FindFormat.Clear
Application.FindFormat.Font.Color = FontColour
Set rPtr = DataRange.Find(What:="*", SearchFormat:=True)
If Not rPtr Is Nothing Then
sStartAddress = rPtr.Address
Do
'**********************
Call ProcessData(rPtr)
'**********************
Set rPtr = DataRange.Find(What:="*", After:=rPtr, SearchFormat:=True)
If Not rPtr Is Nothing Then
If rPtr.Address = sStartAddress Then bCompleted = True
Else
bCompleted = True
End If
Loop While bCompleted = False
End If
End Sub
Public Sub ProcessData(ByVal r As Range)
Debug.Print r.Address
End Sub

Resources