简体   繁体   中英

Run-time error in VBA when SQL table doesn't exist

I am trying to refresh some tables in excel that are in an SQL database. The SQL tables get created when there is data to put into them so sometimes those tables are not created. I believe I am getting the below error in VBA when it can't find the table in SQL. How can I avoid this error?

I thought about making the macro "check" if the table exists and if so, refresh it but I don't know how to do this and haven't found similar problems. Also, I was wondering if the "on error resume next" statement would work because I don't care if there is an error, I only want the macro to pass through every refresh instance (I am trying to refresh 3 tables).

Sub RefreshAll()
    Range("Duplicates").ListObject.QueryTable.Refresh BackgroundQuery:=False
    Range("Fatal_Error").ListObject.QueryTable.Refresh BackgroundQuery:=False
    Range("Wrong_MCN").ListObject.QueryTable.Refresh BackgroundQuery:=False

    MsgBox ("Tables have been refreshed")
End Sub

The error message I get is:

Run-time error 1004: Method Range of object _Global failed.

Please note that in my code, the first line runs with no problems and brings all the data. The second and third lines of "refresh" give the error because no tables with those names are in the SQL database.

It's not the database or its tables; method Refresh of QueryTable would have failed if that were the case.

It fails well before that; a call to method Range of (hidden) object _Global happens when you implicitly reference the ActiveSheet , and when the specified range/name doesn't exist on that sheet (whatever sheet is active at that time), it fails.

Start with the Worksheet you want to get the Range in:

Sheet1.Range("named range")...

If the sheet you need to work with exists in ThisWorkbook at compile-time, then you can give it a code name by setting its (Name) property; this code name identifier can then be used in code whenever you need to refer to that particular sheet.

If the names are actually table names, then use the sheet's ListObjects collection to retrieve it:

Sheet1.ListObjects("Duplicates").QueryTable.Refresh
Sheet2.ListObjects("Fatal_Error").QueryTable.Refresh
...

As for On Error Resume Next and "I don't care if there is an error"... don't do this. You DO care if there's an error. In this case the (Excel) table itself isn't even found: an error there means the refresh will never happen. OERN just shoves errors under the carpet and pretends they didn't happen: it won't magically make the refreshing work for a table that isn't even found. OERN makes debugging much harder than it needs to be, when there are too many reasons for something to fail.

The trick is to separate getting the table object from the act of refreshing it .

OERN is great when you need to run something that might fail, but you need to ignore that error (eg couldn't refresh QueryTable because SQL table doesn't exist) - pull the refresh call into its own scope, and leave it with only a single reason to fail:

Private Function TryRefresh(ByVal qt As QueryTable) As Boolean
    On Error Resume Next
    qt.Refresh BackgroundQuery:=False
    TryRefresh = Err.Number = 0
    On Error GoTo 0
End Function

Now you can invoke this specialized procedure whenever you have a valid object reference to a QueryTable object - for example:

If Not TryRefresh(Sheet1.ListObjects(1).QueryTable) Then Debug.Print "table 1 failed to refresh"
If Not TryRefresh(Sheet2.ListObjects(1).QueryTable) Then Debug.Print "table 2 failed to refresh"
If Not TryRefresh(Sheet3.ListObjects(1).QueryTable) Then Debug.Print "table 3 failed to refresh"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM