VBA Error Handling in QueryTables Loop - vba

I am importing multiple csv files from Google Finance and saving the data to a single worksheet. Whenever a URL is not valid I would like it to go to an error handler where it essentially says "this info could not be found" and then continue back to grab the next csv file from the web.
The code works fine UNTIL it gets to an invalid url, and executes the error handler. The error handler does its job the first time, but then when the loop continues with a new URL, it errors again even when the url is valid.
Once the querytable .Refresh errors once, each url after will also error even if it is a valid url. Is there a way to clear the error and move on to the next URL?
Code:
Sub getQuotes()
For i = 1 To 3775
sym = Worksheets("2").Range("C" & i)
lookup = "TEXT;http://www.google.com/finance/historical?q=" + sym + "&startdate=Jun+1%2C+2016&enddate=Aug+5%2C+2016&num=30&authuser=1&output=csv"
With Worksheets("Raw Data").QueryTables.Add(Connection:=lookup, Destination:=Worksheets("Raw Data").Range("A2"))
.Name = _
" "
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 775
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileDecimalSeparator = ","
.TextFileTrailingMinusNumbers = True
On Error GoTo Err1:
.Refresh BackgroundQuery:=True
End With
Next
Err1:
Worksheets("Raw Data").Range("A:F").EntireColumn.Insert
Worksheets("Raw Data").Range("A2") = sym + " data could not be extracted"
Resume Next
End Sub

Although I was not able to reproduce the specific problem you've referenced, you're missing Exit Sub before your Error handling section. Without it, the code under Err1: gets executed after your For loop finishes, regardless of whether there was an error.
Simply add Exit Sub on the line above your Err1: and let 'er rip. My code worked with an error in the middle of my sym list with this change.

Related

Exception while trying to get data from a URL

I have a vba, that gets a URL. The URL (if inserts into a browser) downloads a .csv file.
The vba should get the data of that .csv file from the URL, and it adds the data to a new sheet.
This is the code that have to connect to the URL and get the data:
With Sheets(currentSymbol).QueryTables.Add(Connection:= _
"TEXT;" & URL _
, Destination:=Sheets(currentSymbol).Range(dataAddress))
.Name = ""
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 2
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(2, 2, 2, 2, 2, 2, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
If I use the following URL (that returns a .csv file), it works fine:
http://www.google.com/finance/historical?q=SPY&startdate=Jan+1%2C+2000&enddate=Dec+31%2C+2017&num=30&ei=WLQtWaAfiMOxAbeYutgE&output=csv
But if I use the following URL (which also returns a .csv file), I get an exception:
https://query1.finance.yahoo.com/v7/finance/download/SPY?period1=1476219600&period2=1508533200&interval=1d&events=history&crumb=uqY5qLCvV0S
CurrentSymbol and dataAddress in both cases is the same.
URL holds the url.
The second URL does exists and does return a .csv file.
I have a pre-check for the URL that completes fine (for both the URLs):
Function HttpExists(sURL As String) As Boolean
Dim oXHTTP As Object
Set oXHTTP = CreateObject("MSXML2.ServerXMLHTTP")
On Error GoTo haveError
oXHTTP.Open "HEAD", sURL, False
oXHTTP.send
HttpExists = IIf(oXHTTP.status = 200, True, False)
Exit Function
The exception that I get from the second URL says:
Error 1004: Microsoft excel cannot access the file "https://.........."
There are several posible reasons:
* The file name of path does not exist
* The file is being used by another program
* The workbook you are trying to save the same name as a currently open workbook
What can be the problem with the second URL?
Why do I get the exception for the second URL?
Thanks
The second URL only returns a .csv file when your browser has the right cookie. Excel probably can't provide cookie, so it gets a warning in JSON.

Excel VBA: message box error in connection

There is a website, that can create thousands of .csv files that contain tables. The CSV files are based on the information the user asks.
I created an excel file with VBA script. The user enters the data to the excel file, then the VBA script generates the correct URL, and tries to get the required data from the .csv in that URL.
In my excel file, the user can ask for hundreds of .csv tables, and I want the user to be able to enter the hundreds of information kinds he wants, then run the VBA script and leave the computer to work on it.
I first do URL check, and if it is ok, I try to get the data in the .csv file in that URL.
most of the times, it works completely fine. Works fine for a case when HttpExists returns TRUE, and also works fine for a case that HttpExists returns FALSE (it just skips the current active cell and goes to the next one).
But there are a few times, that the URL check answers that the URL is fine (HttpExists returns TRUE), but when it tried to get the data, it opens a message box that says "sorry, we couldn't open 'url address' ". (message box for Run Time Error 1004) and then the VBA scripts terminates.
I would like to know how can I fix it. How can I just skip the current URL in case of error, instead of showing a message box that terminates the script run?
Sub my_method()
On Error GoTo handleCancel
Dim errorFlag As Boolean
.......
Do Until ActiveCell.Value = ""
errorFlag = True
URLstring= ....
........
If Not HttpExists(URLstring) Then
symbolStatus = "Data unavailable"
logAddress = updateLog("invalid URL " & ActiveCell.Value, logAddress, debugString)
Application.DisplayAlerts = False
Sheets(currentSymbol).Delete
Application.DisplayAlerts = True
Else
With Sheets(currentSymbol).QueryTables.Add(Connection:= _
"TEXT;" & URLstring _
, Destination:=Sheets(currentSymbol).Range(dataAddress))
.Name = ""
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 2
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(2, 2, 2, 2, 2, 2, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
.......
errorFlag = False
handleCancel:
ActiveCell.Offset(1, 0).Select
If errorFlag = True Then
symbolStatus = "Data unavailable"
logAddress = updateLog("invalid URL " & ActiveCell.Value,
logAddress, debugString)
Application.DisplayAlerts = False
Sheets(currentSymbol).Delete
Application.DisplayAlerts = True
End If
Loop
End Sub
Function HttpExists(sURL As String) As Boolean
Dim oXHTTP As Object
Set oXHTTP = CreateObject("MSXML2.ServerXMLHTTP")
If Not UCase(sURL) Like "HTTP:*" Then
sURL = "http://" & sURL
End If
On Error GoTo haveError
oXHTTP.Open "HEAD", sURL, False
oXHTTP.send
HttpExists = IIf(oXHTTP.status = 200, True, False)
Exit Function
haveError:
HttpExists = False
End Function
It sometimes goes out with a messagebox of Run Time Error 1004, and it happens in the line of:
With Sheets(currentSymbol).QueryTables.Add(Connection:= _
"TEXT;" & URL _
I would like it just to skip the current cell in a case of error, and go on with the next cell, without any messagebox and without crashing.
How can I fix it?
Thanks
See if this error handling structure works better. I eliminated parts that are unnecessary and adjusted to what should work, but I am not sure what code is in the ..... sections. Anyway, this should at least give you a general understanding. I commented a few things to explain more clearly in code.
Option Explicit
Sub my_method()
Do Until ActiveCell.Value = ""
'URLstring= ....
If Not HttpExists(URLstring) Then
LogError 'create sub since you do same thing twice
Else
On Error GoTo handleBadURL 'now is only time you need to move to actual error handling
With Sheets(currentSymbol).QueryTables.Add(Connection:= _
"TEXT;" & URLstring _
, Destination:=Sheets(currentSymbol).Range(dataAddress))
.Name = ""
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 2
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(2, 2, 2, 2, 2, 2, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
On Error Go To 0 'reset error handling (doesn't matter so much here, but good practice to always reset when not needed
End If
ActiveCell.Offset(1, 0).Select
Loop
Exit Sub 'leave sub when all is done (so it doesn't move to error handling code below
handleBadURL:
LogError 'created sub since you do same thing twice
Resume Next 'this statement will allow code to continue from point of error onward (the loop will keep going
End Sub
Sub LogError()
symbolStatus = "Data unavailable"
logAddress = updateLog("invalid URL " & ActiveCell.Value, logAddress, debugString)
Application.DisplayAlerts = False
Sheets(currentSymbol).Delete
Application.DisplayAlerts = True
End Sub
You need to add error handling to your code. Server timeout notices doesn't reflect an issue with your coding, but an issue with the server (which is out of your control, unless of course, you entered an incorrect URL).
In your code, you need to place On Error GoTo ErrHandler, make sure you have the error number, and since you are wanting to just resume to the next cell you can do something like this:
Sub Test()
On Error GoTo ErrHandler
'Your code
Exit Sub
ErrHandler:
If Err.Number = 123456 Then
'Get the code ready for the next cell, if necessary
Resume Next
Else
'Other Errs
End If
End Sub

How to load CSV in a workbook replacing existing sheet?

I have the following Macro which imports a CSV-file as a new sheet which is called "Tickets". When this file aready exists, I get a runtime-error. Is there a way to just overwrite the existing file if it already exists?
Sub GetCSVList()
Dim dlgOpen As FileDialog
Set dlgOpen = Application.FileDialog(msoFileDialogFilePicker)
With dlgOpen
.AllowMultiSelect = False
''Start in
.InitialFileName = "C:\test"
.Show
End With
For Each fname In dlgOpen.SelectedItems
ImportCSV fname
Next
End Sub
Sub ImportCSV(fname)
Set ws = Worksheets.Add(after:=Worksheets(Worksheets.Count))
ws.Name = "Tickets"
With ws.QueryTables.Add( _
Connection:="TEXT;" & fname, _
Destination:=Range("A1"))
.Name = "Test" & Worksheets.Count + 1
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.TextFilePromptOnRefresh = False
.TextFilePlatform = 65001
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.Refresh BackgroundQuery:=False
'.UseListObject = False
End With
End Sub
After adding a new worksheet at the end, try to delete any existing worksheet named "Tickets" before renaming the new worksheet to "Tickets":
Application.DisplayAlerts = False
On Error Resume Next
Worksheets("Tickets").Delete
On Error GoTo 0
Application.DisplayAlerts = True
On Error Resume Next will ignore the error that would arise if there aren't any existing worksheets named "Tickets". This is a little lazy, but that's pretty much the only error that will arise from the Worksheet.Delete method, so you can get away it.
Do not "On Error Resume Next" to just ignore other types of errors in programming!

VBA type mismatch error in QueryTables

I'm getting a type mismatch range error at line 8. Can anyone please so kindly explain what I'm doing wrong?
Thanks
Set objExcel = CreateObject("Excel.application")
Set objWorkbook = objExcel.Workbooks.Add()
Set objSheet = objWorkbook.Worksheets.Add
objExcel.Visible = True
objExcel.DisplayAlerts = True
objExcel.Workbooks.Add(1)
With objExcel.ActiveSheet.QueryTables.Add(Connection="TEXT;C:\temp\file.csv", Destination=Range("$A$1"))
'.CommandType = 0
.Name = "test_ITS_ExtractX"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(2, 2)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery=False
End With
objExcel.ActiveWorkbook.SaveAs Filename="c:/temp/file.xlsx", FileFormat=xlOpenXMLWorkbook, CreateBackup=False
objExcel.DisplayAlerts = True
objExcel.Quit
If your code actually is written in one of the VBA variants, the named parameters should be specified using := instead of just =. This generates a "Type mismatch" error when I run your code.
You also have an unqualified Range object (see answer by Domenic), which will cause problems once you correct the syntax errors.
So the correct line should be:
With objExcel.ActiveSheet.QueryTables.Add(Connection:="TEXT;C:\temp\file.csv", _
Destination:=objExcel.ActiveSheet.Range("$A$1"))
and one of your later lines should be
objExcel.ActiveWorkbook.SaveAs Filename:="c:\temp\file.xlsx", _
FileFormat:=xlOpenXMLWorkbook, _
CreateBackup:=False
and I just noticed
.Refresh BackgroundQuery:=False
(Note: Please ensure that the xlOpenXMLWorkbook constant is available in whichever application you are running this in. If not, you will need to assign the correct value to it yourself. The same will apply for xlInsertDeleteCells, etc.)
Try...
With objExcel.ActiveSheet.QueryTables.Add(Connection:="TEXT;C:\temp\file.csv", Destination:=objExcel.ActiveSheet.Range("$A$1"))
Hope this helps!

Import Data from Text File into Master File (changing target directories)- Excel

I know that this post is going to seem very similar to many other posts to those who understand it. I have learned C++ and C#, both only well enough to do minor work, and I just cannot understand VBA well enough to make this macro happen.
I have just under 100 files that need to be imported to a master file. I cannot modify the source files but the master file needs only select columns.
This macro works almost perfectly I just need the ability to select new file paths for each instance of the macro being used. I have found many posts that seem to use something like this:
https://social.msdn.microsoft.com/Forums/office/en-US/231cbfc5-95ad-4673-a20c-f87355c6bc5e/prompt-user-for-file-name-to-import-as-fixed-width-text-file?forum=exceldev
in order to first make a filepath into a variable and then pass it to the ActiveSheet.QueryTables.Add command. I might just be missing something but there are a lot of variables between all of the examples that I just don't understand. It seems like the msdn page for vba is much less intuitive than those for C#. Either that or I am simply unable to understand them having not taken the babysteps that I need.
Using the macro tool I made the large majority of the code below. About an hour of working allowed me to replace the hardcoded cell with the active cell.
Sub InputDataFromTextFile()
'
' InputDataFromTextFile Macro
'
' Keyboard Shortcut: Ctrl+t
'
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;E:\Dropbox\College 2016-2017\Research\Buffered Solutions\pH10\With PDADMAC\30.CSV" _
, Destination:=ActiveCell)
.Name = "30"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1252
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(9, 1, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
I would appreciate any and all help that could be given. Thank you all so much for your time regardless.
So immediately after posting, I hadn't figured it out in the comments I tried something and got it to work. Here is the code as it stands.
Sub InputDataFromTextFile()
Dim Filt As String
Dim FilterIndex As Integer
Dim Title As String
Dim FileName As Variant
' Set up list of file filters
Filt = "All Files (*.*),*.*"
' Display Text Files by default
FilterIndex = 1
' Set the dialog box caption
Title = "Select a File to Import"
' Get the file name
FileName = Application.GetOpenFilename _
(FileFilter:=Filt, _
FilterIndex:=FilterIndex, _
Title:=Title)
' Exit if dialog box is canceled
If FileName = False Then
MsgBox "No file was selected."
Exit Sub
End If
'
' InputDataFromTextFile Macro
'
' Keyboard Shortcut: Ctrl+t
'
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;" & FileName, _
Destination:=ActiveCell)
.Name = "30"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 1252
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(9, 1, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
One of my largest issues was honestly that once excel was restarted the Ctrl+T that I had hotkeyed to the command reverted to making a table. I couldn't figure out where it was coming from! Thank you for your help. This saves me a great deal of time.
While the comment made by Parfait about cycling through the files and having them auto import is the next step and a very obviously desired trait in the code, it seems like a lot for me right now. I'm already saving upwards of an hour per mastersheet which is just amazing. Thank you all so much again.