Excel VBA On Error Resume Next Returns Value Out Of Position - vba

I am placing picture in my worksheet using a URL. The code works great except "on error resume next" places the previous cell's (good) value in the cell where the error occurred instead of the cell it should (one row up). It then continues placing values where they belong until there is another error.
I have tried placing the "on error resume next" in different areas of the code, but haven't been able to fix the issue. Is it a matter of where the error handling is placed, or do I need to have a better error handler?
Thank you,
Andy
Sub InsertPic()
On Error Resume Next
Dim pic As String
Dim myPicture As Picture
Dim rng As Range
Dim cl As Range
Set rng = Range("F2:F1131")
For Each cl In rng
pic = cl.Offset(0, -1)
Set myPicture = ActiveSheet.Pictures.Insert(pic)
With myPicture
.ShapeRange.LockAspectRatio = msoFalse
.Width = cl.Width
.Height = cl.Height
.Top = Rows(cl.Row).Top
.Left = Columns(cl.Column).Left
End With
Next
End Sub

If you need to check if the URL exists then maybe a helper function will suffice?
Sub InsertPic()
Dim pic As String
Dim myPicture As Picture
Dim rng As Range 'E3:E1132
Dim cl As Range 'iterator
Set rng = Range("F2:F1131")
For Each cl In rng
pic = cl.Offset(0, -1)
if URLExists(pic) then
Set myPicture = ActiveSheet.Pictures.Insert(pic)
With myPicture
.ShapeRange.LockAspectRatio = msoFalse
.Width = cl.Width
.Height = cl.Height
.Top = Rows(cl.Row).Top
.Left = Columns(cl.Column).Left
End With
end if
Next
End Sub
'ref: http://www.mrexcel.com/forum/excel-questions/567315-check-if-url-exists-so-then-return-true.html
Function URLExists(url As String) As Boolean
Dim Request As Object
Dim ff As Integer
Dim rc As Variant
On Error GoTo EndNow
Set Request = CreateObject("WinHttp.WinHttpRequest.5.1")
With Request
.Open "GET", url, False
.Send
rc = .StatusText
End With
Set Request = Nothing
If rc = "OK" Then URLExists = True
Exit Function
EndNow:
End Function

Related

How to add multiple pictures in Word from vb.net

I'm trying to add multiple pictures in a word document using vb.net but on the second picture, trhows the following error: System.Runtime.InteropServices.COMException: 'Error HRESULT E_FAIL has been returned from a call to a COM component.', I think I might dispose some variable but I don't know which.
this is my code:
Sub LoadPics()
Dim wdWrapFront As Integer = 3
Dim wdRelativeVerticalPositionPage As Integer = 1
Dim objWordApp As Word.Application
objWordApp = New Word.Application
Dim objDoc As Word.Document
Dim objSelection
objDoc = objWordApp.Documents.Open("Document.doc")
Dim objShapes As Word.InlineShapes
objShapes = objDoc.InlineShapes
Dim oShape As Word.Shape
objWordApp.Visible = False
objSelection = objWordApp.Selection
Dim FL As string = ""
For c As Integer = 0 to 10
FL = "file.png"
If IO.File.Exists(FL) Then
oShape = objShapes.AddPicture(FL).ConvertToShape()'<<<---here is the problem
With oShape
.WrapFormat.Type = wdWrapFront
.LockAspectRatio = False
.Height = objWordApp.CentimetersToPoints(5.08)
.Width = objWordApp.CentimetersToPoints(10.16)
.RelativeVerticalPosition = wdRelativeVerticalPositionPage
.Top = objWordApp.CentimetersToPoints(TopValue)
.Left = objWordApp.CentimetersToPoints(LeftValue)
End With
Else
MsgBox("File doesn't exist" & vbCrLf & FL)
End If
Next
objWordApp.Visible = True
End Sub
I was able to solve the problem by simply changing this line
objWordApp.Visible = True
I don't know which was the problem with that line but it works now

Putting images onto an excel sheet via URL links

My sheet has three columns, "A" = Images, "B" = Image Names, and "C" = URL Links, with Rows 1 and 2 being used as headers and rows 3 to 1002 for user input. The Current working code will search for the image names in Column "B" in the folder you select, and inserts them into Column "A". This macro runs off of a commandbutton I have placed on a userform I have created.
Working code is as follows (this is a edited version of the accepted answer here):
Private Sub Add_Images_Click()
Const EXIT_TEXT As String = ""
Const NO_PICTURE_FOUND As String = "No picture found"
Dim picName As String
Dim picFullName As String
Dim rowIndex As Long
Dim lastRow As Long
Dim selectedFolder As String
Dim data() As Variant
Dim wks As Worksheet
Dim Cell As Range
Dim pic As Picture
On Error GoTo ErrorHandler
selectedFolder = GetFolder
If Len(selectedFolder) = 0 Then GoTo ExitRoutine
Application.ScreenUpdating = False
Set wks = ActiveSheet
lastRow = wks.Cells(2, "B").End(xlDown).Row
data = wks.Range(wks.Cells(3, "B"), wks.Cells(lastRow, "B")).Value2
For rowIndex = 3 To UBound(data, 1)
If StrComp(data(rowIndex, 1), EXIT_TEXT, vbTextCompare) = 0 Then GoTo ExitRoutine
picName = data(rowIndex, 1)
picFullName = selectedFolder & picName
If Len(Dir(picFullName)) > 0 Then
Set Cell = wks.Cells(rowIndex, "A")
Set pic = wks.Pictures.Insert(picFullName)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.Height = Cell.Height
.Width = Cell.Width
.Top = Cell.Top
.Left = Cell.Left
.Placement = xlMoveAndSize
End With
Else
wks.Cells(rowIndex, "A").Value = NO_PICTURE_FOUND
End If
Next rowIndex
ExitRoutine:
Set wks = Nothing
Set pic = Nothing
Application.ScreenUpdating = True
UserForm.Hide
Exit Sub
ErrorHandler:
MsgBox Prompt:="Unable to find photo", _
Title:="An error occured", _
Buttons:=vbExclamation
Resume ExitRoutine
End Sub
Private Function GetFolder() As String
Dim selectedFolder As String
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = Application.DefaultFilePath & "\"
.Title = "Select the folder containing the Image/PDF files."
.Show
If .SelectedItems.count > 0 Then
selectedFolder = .SelectedItems(1)
If Right$(selectedFolder, 1) <> Application.PathSeparator Then _
selectedFolder = selectedFolder & Application.PathSeparator
End If
End With
GetFolder = selectedFolder
End Function
I'm looking for a way to edit this macro so that it would be able to use the URL links for the images in Column "C" and find and insert the images into Column "A" that way. I found a working code (can't remember where, or I'd link it) that I tried to adapt with my current code to achieve the desired results.
The sample code I found online:
Sub Images_Via_URL()
Dim url_column As Range
Dim image_column As Range
Set url_column = Worksheets(1).UsedRange.Columns("A")
Set image_column = Worksheets(1).UsedRange.Columns("B")
Dim i As Long
For i = 2 To url_column.Cells.Count
With image_column.Worksheet.Pictures.Insert(url_column.Cells(i).Value)
.Left = image_column.Cells(i).Left
.Top = image_column.Cells(i).Top
.Height = 100
.Width = 100
End With
Next
End Sub
The following code is my failed attempt to edit it myself. It worked once for a list of 7 URL links, then I deleted one of the links in the middle to see if it would handle the blank cell correctly, and now it flat out wont work. It goes into the "ExitRoutine" every time.
Not Working Code:
Option Explicit
Private Sub URL_Images_Click()
Const EXIT_TEXT As String = ""
Const NO_PICTURE_FOUND As String = "No picture found"
Dim picURL As String
Dim rowIndex As Long
Dim lastRow As Long
Dim data() As Variant
Dim wks As Worksheet
Dim Cell As Range
Dim pic As Picture
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Set wks = ActiveSheet
lastRow = wks.Cells(2, "B").End(xlDown).Row
data = wks.Range(wks.Cells(3, "C"), wks.Cells(lastRow, "C")).Value2
For rowIndex = 3 To UBound(data, 1)
**If StrComp(data(rowIndex, 1), EXIT_TEXT, vbTextCompare) = 0 Then GoTo ExitRoutine**
picURL = data(rowIndex, 1)
If Len(picURL) > 0 Then
Set Cell = wks.Cells(rowIndex, "A")
Set pic = wks.Pictures.Insert(picURL)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.Height = Cell.Height
.Width = Cell.Width
.Top = Cell.Top
.Left = Cell.Left
.Placement = xlMoveAndSize
End With
Else
wks.Cells(rowIndex, "A").Value = NO_PICTURE_FOUND
End If
Next rowIndex
ExitRoutine:
Set wks = Nothing
Set pic = Nothing
Application.ScreenUpdating = True
UserForm.Hide
Exit Sub
ErrorHandler:
MsgBox Prompt:="Unable to find photo", _
Title:="An error occured", _
Buttons:=vbExclamation
Resume ExitRoutine
End Sub
I've bolded the line that is forcing it to the "ExitRoutine". I'm not sure how exactly that line works as I am not the one who originally wrote it. Any help would be great!
lastRow = wks.Cells(2, "B").End(xlDown).Row
data = wks.Range(wks.Cells(3, "C"), wks.Cells(lastRow, "C")).Value2
For rowIndex = 3 To UBound(data, 1)
'....
If you start at rowIndex = 3 then you're skipping the first two rows of your input data: a 2-D array from a range always has lower bounds of 1 for both dimensions, regardless of the location of the range.
In this case data(1,1) will correspond to C3, whereas data(3,1) is C5

Pulling images from a FTP site to Excel

I have the following working codes.
Column B has image names, this pulls images in the selected folder that match the names in column B and inserts them into Column A (please note, first two rows are used for my header). I've noticed that the code errors if the header in B2 is missing, then the code errors out. I would like to fix this so it will only try to find images if there is a name in Range("B3:B1002").
Option Explicit
Private Sub Add_Images_Click()
Const EXIT_TEXT As String = ""
Const NO_PICTURE_FOUND As String = "No picture found"
Dim picName As String
Dim picFullName As String
Dim rowIndex As Long
Dim lastRow As Long
Dim selectedFolder As String
Dim data() As Variant
Dim wks As Worksheet
Dim Cell As Range
Dim pic As Picture
On Error GoTo ErrorHandler
selectedFolder = GetFolder
If Len(selectedFolder) = 0 Then GoTo ExitRoutine
Application.ScreenUpdating = False
Set wks = ActiveSheet
lastRow = wks.Cells(2, "B").End(xlDown).Row
data = wks.Range(wks.Cells(1, "B"), wks.Cells(lastRow, "B")).Value2
For rowIndex = 3 To UBound(data, 1)
If StrComp(data(rowIndex, 1), EXIT_TEXT, vbTextCompare) = 0 Then GoTo ExitRoutine
picName = data(rowIndex, 1)
picFullName = selectedFolder & picName
If Len(Dir(picFullName)) > 0 Then
Set Cell = wks.Cells(rowIndex, "A")
Set pic = wks.Pictures.Insert(picFullName)
With pic
.ShapeRange.LockAspectRatio = msoFalse
.Height = Cell.Height
.Width = Cell.Width
.Top = Cell.Top
.Left = Cell.Left
.Placement = xlMoveAndSize
End With
Else
wks.Cells(rowIndex, "A").Value = NO_PICTURE_FOUND
End If
Next rowIndex
ExitRoutine:
Set wks = Nothing
Set pic = Nothing
Application.ScreenUpdating = True
Exit Sub
ErrorHandler:
MsgBox Prompt:="Unable to find photo", _
Title:="An error occured", _
Buttons:=vbExclamation
Resume ExitRoutine
End Sub
This is the Function that has the user select the folder that contains the images when the above sub is ran. I would like to modify this if possible to also work with an URL like an FTP site. So if the images are in a folder on the users pc, it will run like below, but if the images are located in a FTP location, it will still be able to pull the images.
Private Function GetFolder() As String
Dim selectedFolder As String
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = Application.DefaultFilePath & "\"
.Title = "Select the folder containing the Image/PDF files."
.Show
If .SelectedItems.Count > 0 Then
selectedFolder = .SelectedItems(1)
If Right$(selectedFolder, 1) <> Application.PathSeparator Then _
selectedFolder = selectedFolder & Application.PathSeparator
End If
End With
GetFolder = selectedFolder
End Function
This Sub is meant to remove all images from column A. The problem is that this works too well. It is fine when used with a normal button, but when I try using a CommandButton to have my buttons on a user form, this Sub removes the CommandButton. It also removes all comments from the sheet. I would like to either limit this to only remove images, or to quarantine the code to only look at Range("A3:A1002").
Private Sub Remove_Images_Click()
'Remove Images
Dim wks As Worksheet
Dim shp As Shape
Dim picArray() As String
Dim index As Integer
On Error GoTo ErrorHandler
Columns(1).Replace What:="No Picture Found", Replacement:=vbNullString, LookAt:=xlPart
Set wks = ActiveSheet
index = 1
For Each shp In wks.Shapes
If shp.Type <> msoFormControl Then
ReDim Preserve picArray(1 To index)
picArray(index) = shp.Name
index = index + 1
End If
Next shp
wks.Shapes.Range(picArray).Delete
ExitRoutine:
Set wks = Nothing
Set shp = Nothing
Erase picArray
Exit Sub
ErrorHandler:
MsgBox Prompt:="Unable to find photo", _
Title:="An error occured", _
Buttons:=vbExclamation
Resume ExitRoutine
End Sub
I see three main questions, probably better to separate these into different questions but I'll give it a shot.
Ignore row 2 in the first code block.
Change 1 to 3 on this line: data = wks.Range(wks.Cells(3, "B"), wks.Cells(lastRow, "B")).Value2 This sets your data range starting at row 3 and ignores your two header rows.
FTP link
This is better suited for a separate question. Start by creating a new function that handles FTP links. Then identify which path is in the cell, i.e. does it start with http, c://, etc... Then call appropriate function and have it return the image to the main program.
Check if shape is in column A.
Use the TopLeftCell attribute and see if it intersects column A
For Each shp In wks.Shapes
If Not Intersect(shp.TopLeftCell, Columns(1)) Is Nothing Then '<-- New Line checks if in col A
If shp.Type <> msoFormControl Then
....

on error resume next gives wrong result when inserting pictures

I created a code to insert pictures into a cell from a link (next to that cell). Sometimes a picture is deleted in the file it links to. I get an error 400, but when I put 'on error resume next' it leaves the last cell with a right link empty and puts that picture in the cell with a wrong link. Also the last cell with a right link is empty.
The position of 'on error resume next' does not matter (before loop, or at any place in the loop)
How can I avoid that? Just skip the wrong link and put pictures at the right positions?
Sub InsertPictures()
Call DeleteAllPicturesInRange
Dim pic As String
Dim myPicture As Picture
Dim rng As Range
Dim cl As Range
Set rng = Range("J5:J124")
For Each cl In rng
pic = cl.Offset(0, 1)
Set myPicture = ActiveSheet.Pictures.Insert(pic)
With myPicture
.ShapeRange.LockAspectRatio = msoFalse
.Width = cl.Width
.Height = cl.Height
.Top = Rows(cl.Row).Top
.Left = Columns(cl.Column).Left
End With
Next
End Sub
Adding one line of code empties the variables and ensures you are not using the variable across loops. basically you have two variables that you run the risk of using by default in the next loop if you use on error resume next and they are pic and mypicture a good practice is to clear these variables as soon as you are done with them and since they are by default used in the next loop as a new value is not set. Does that make sense?
Note - to clear a range variable you have to assign it to another range hence Cell(1,1) set it to anyother cell that matches your need
Set myPicture = Nothing
pic = Cell(1,1)
Sub InsertPictures()
Call DeleteAllPicturesInRange
Dim pic As String
Dim myPicture As Picture
Dim rng As Range
Dim cl As Range
Set rng = Range("J5:J124")
For Each cl In rng
pic = cl.Offset(0, 1)
Set myPicture = ActiveSheet.Pictures.Insert(pic)
With myPicture
.ShapeRange.LockAspectRatio = msoFalse
.Width = cl.Width
.Height = cl.Height
.Top = Rows(cl.Row).Top
.Left = Columns(cl.Column).Left
End With
Set myPicture = Nothing
pic = cell(1,1)
Next
End Sub
Thanks for the help. I added on error resume next in combination with Set mypicture = Nothing and it works!!!
Sub InsertPictures()
Call DeleteAllPictures
Dim Pic As String 'file path of pic
Dim myPicture As Picture 'embedded pic
Dim rng As Range 'range over which we will iterate
Dim cl As Range 'iterator
Set rng = Range("J5:J124")
For Each cl In rng
Pic = cl.Offset(0, 1)
On Error Resume Next
Set myPicture = ActiveSheet.Pictures.Insert(Pic)
With myPicture
.ShapeRange.LockAspectRatio = msoFalse
.Width = cl.Width
.Height = cl.Height
.Top = Rows(cl.Row).Top
.Left = Columns(cl.Column).Left
End With
Set myPicture = Nothing
Next
End Sub

How to set picture aspect ratio?

Sub ExampleUsage()
Dim myPicture As String, myRange As Range
myPicture = Application.GetOpenFilename _
("Pictures (*.gif; *.jpg; *.bmp; *.tif),*.gif; *.jpg; *.bmp; *.tif", _
, "Select Picture to Import")
Set myRange = Selection
InsertAndSizePic myRange, myPicture
End Sub
Sub InsertAndSizePic(Target As Range, PicPath As String)
Dim p As Object
Application.ScreenUpdating = False
Set p = ActiveSheet.Pictures.Insert(PicPath)
If Target.Cells.Count = 1 Then Set Target = Target.MergeArea
With Target
p.Top = .Top
p.Left = .Left
p.Width = .Width
p.Height = .Height
End With
End Sub
This is my code for Microsoft Excel. I want to have the aspect ratio unlock so that I can fill the entire merged cell. Thanks in advance.
This is how you'll set the Aspect Ratio. It is a Property of the Shape Object. p is of Picture Object Type. You can use it's name to access it via Shapes which has the Aspect Ratio property:
Sub InsertAndSizePic(Target As Range, PicPath As String)
Dim p As Object
Application.ScreenUpdating = False
Dim sh As Worksheet: Set sh = ActiveSheet
Set p = sh.Pictures.Insert(PicPath)
sh.Shapes(p.Name).LockAspectRatio = False
If Target.Cells.Count = 1 Then Set Target = Target.MergeArea
With Target
p.Top = .Top
p.Left = .Left
p.Width = .Width
p.Height = .Height
End With
Application.ScreenUpdating = True
End Sub
I declared and set variable for Worksheet Object just to have Intellisense kick in to get the arguments.
Another way is to use Shape Object AddPicture Method like below.
Sub InsertAndSizePic(Target As Range, PicPath As String)
Dim s As Shape
Application.ScreenUpdating = False
Dim sh As Worksheet: Set sh = ActiveSheet
If Target.Cells.Count = 1 Then Set Target = Target.MergeArea
With Target
Set s = sh.Shapes.AddPicture(PicPath, True, True, .Left, .Top, .Width, .Height)
End With
Application.ScreenUpdating = True
End Sub
This code will also accomplish what the first code does. HTH.