Forum Discussion
save an image from a URL in excel
- Apr 25, 2020
drnick66 hello there!
I wouldn't qualify the question as "basic". It's a little advanced with VBA I'd say. Below is an example of how you can download a list of files via their URL. It will save the name with the same name it has on the web. Note there are no checks to see if the file exists and the destination folder is hard-coded (change to desired).
Option Explicit #If VBA7 Then Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As LongPtr, _ ByVal szURL As String, _ ByVal szFileName As String, _ ByVal dwReserved As Long, _ ByVal lpfnCB As LongPtr) As LongPtr #Else Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, _ ByVal szURL As String, _ ByVal szFileName As String, _ ByVal dwReserved As Long, _ ByVal lpfnCB As Long) As Long #End If Public Sub DownloadImages() Dim Downloaded As Boolean Dim Count As Long Dim Index As Long Dim FileName As String Dim NameParts As Variant Dim Values As Variant Const DownloadPath As String = "C:\Users\Zack\Desktop\" Values = ThisWorkbook.Worksheets("Sheet1").Range("A2:A6").Value For Index = LBound(Values, 1) To UBound(Values, 1) NameParts = Split(Values(Index, 1), "/") FileName = NameParts(UBound(NameParts)) Downloaded = URLDownloadToFile(0, Values(Index, 1), DownloadPath & FileName, 0, 0) = 0 If Downloaded Then Count = Count + 1 Next Index MsgBox Count & " files out of " & UBound(Values, 1) - LBound(Values, 1) + 1 & " downloaded." End Sub
HTH
bardukissnetiquette would have you start a new thread and then just put a link in here. However, after looking at your file, there's only a few tweaks you need to get it working for you. The structure is a little different and it only needs about 3 adjustments.
- Update the sheet name and range.
- Update the delimiter for Split() to be a semicolon and not a forward slash.
- Adjust the URL of the file, which would be found in the NameParts() array instead of the Values() array.
Those changes make it work just fine for me using the below code. I did save your file as XLSB instead of CSV to run the code. You don't have to, but you can't save the file in CSV and retain the code in it. Hope this helps.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As LongPtr, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As LongPtr) As LongPtr
#Else
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long
#End If
Public Sub DownloadImages_bardukiss()
Dim Downloaded As Boolean
Dim Count As Long
Dim Index As Long
Dim FileName As String
Dim NameParts As Variant
Dim Values As Variant
'// Change this path...
Const DownloadPath As String = "C:\Users\Zack\Desktop\"
'// Ensure this sheet name and range is correct. It's status right now.
Values = ThisWorkbook.Worksheets("Test3 2-10").Range("A2:A10").Value
For Index = LBound(Values, 1) To UBound(Values, 1)
NameParts = Split(Values(Index, 1), ";")
FileName = NameParts(LBound(NameParts))
Downloaded = URLDownloadToFile(0, NameParts(3), DownloadPath & FileName & ".jpg", 0, 0) = 0
If Downloaded Then Count = Count + 1
Next Index
MsgBox Count & " files out of " & UBound(Values, 1) - LBound(Values, 1) + 1 & " downloaded."
End Sub
You'll notice I had to manually append the ".jpg" to the file name in the API download, with the code portion:
DownloadPath & FileName & ".jpg"
This is because I am assuming the FileName variable should be using the PartNumber as the file name, which comes from the first column of your data (i.e. "A9V15463").
There is basically no error handling in this entire piece of code and it can certainly be improved upon, but it is the basics. Things I would think about if it were mine (I don't know your requisites):
- Making the download folder dynamic (user selects at run-time), or having it set in a cell somewhere, anything except being hard-coded.
- Making the sheet name dynamic. You would need to know how the file is being ingested in the overall process to know where it would fit.
- Making the range dynamic.
- Checking if the file already exists in the desired location prior to downloading (choose to remove and re-download or skip).
- Check data for duplicates. This depends on where the data actually comes from and may not be an issue.
Take care. 🙂
Zack Barresse I am unable to get this to run. I edited slightly to make the download path dynamic based on the user but I keep getting "Compile Error: Constant expression required". I have the Option Explicit in there just as you do. Any advice?? Thank you.
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As LongPtr, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As LongPtr) As LongPtr
#Else
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, _
ByVal szURL As String, _
ByVal szFileName As String, _
ByVal dwReserved As Long, _
ByVal lpfnCB As Long) As Long
#End If
Public Sub DownloadImages()
Dim Downloaded As Boolean
Dim Count As Long
Dim Index As Long
Dim FileName As String
Dim NameParts As Variant
Dim Values As Variant
'// Change this path...
Const DownloadPath As String = ("C:\Users\" & Environ("username") & "\Documents\RETS\")
'// Ensure this sheet name and range is correct. It's status right now.
Values = ThisWorkbook.Worksheets("Img URLs").Range("A2").Value
For Index = LBound(Values, 1) To UBound(Values, 1)
NameParts = Split(Values(Index, 1), ";")
FileName = NameParts(LBound(NameParts))
Downloaded = URLDownloadToFile(0, NameParts(3), DownloadPath & FileName, 0, 0) = 0
If Downloaded Then Count = Count + 1
Next Index
MsgBox Count & " files out of " & UBound(Values, 1) - LBound(Values, 1) + 1 & " downloaded."
End Sub
- Zack BarresseApr 10, 2022Iron Contributor
NickIzGr8FulYou can't use a function call (Environ) in a constant like you are trying. Just declare it as a variable instead, like this.
Dim DownloadPath As String DownloadPath = ("C:\Users\" & Environ("username") & "\Documents\RETS\")