刷新QueryTable抛出"常规ODBC错误" - 适用于Mac的VBA Excel 2011

时间:2016-01-28 09:20:41

标签: excel vba excel-vba excel-vba-mac

编辑:发现新错误?

我可能刚刚发现为什么我的剧本不再适用了。最近有一个办公室更新,似乎他们已经实现了微软查询,摆脱了我安装和配置为我需要的ODBC管理器。现在实际的问题可能是这个微软查询没有UNICODE库,我不知道我可以把它们放在哪里,以便微软查询可以读取/获取它们。或者更确切地说,我不知道如何让微软查询到UNICODE库的路径,因为在管理器中没有可能改变它,或者可能有,我只是没有找到它?除此之外,我无法打开microsoft查询管理器,除非我直接从excel工作簿中打开它。

原始问题

此代码已有一段时间了。现在使用完全相同的代码我得到运行时错误。 Here我已经在这个案子中寻求帮助并让它发挥作用。

以下是代码:

Sub ConnectSQL()

    Dim connstring As String
    Dim sLogin As String
    Dim qt As QueryTable

    sLogin = "Uid=*;Pwd=*;"
    sqlstringFirma = "select * from gi_kunden.tbl_Firma"
    sqlstringPerson = "select * from gi_kunden.tbl_Person"
    connstring = "ODBC;DSN=KundeDB;" & sLogin

    ActiveWorkbook.Sheets("Firma").Select
    ActiveSheet.Range("A1:T2000").Clear

    For Each qt In ActiveSheet.QueryTables
        qt.Delete
    Next qt

    With ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Range("A1"), Sql:=sqlstringFirma)
        .BackgroundQuery = False
        .RefreshStyle = xlOverwriteCells
        .Refresh '"General ODBC error" hereeee
    End With

    ActiveWorkbook.Sheets("Person").Select
    ActiveSheet.Range("A1:T2000").Clear

    For Each qt In ActiveSheet.QueryTables
        qt.Delete
    Next qt

    With ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Range("A1"), Sql:=sqlstringPerson)
        .BackgroundQuery = False
        .RefreshStyle = xlOverwriteCells
        .Refresh 'And hereee again
    End With


    Call Replace
    ActiveWorkbook.Sheets("Firma").Select

End Sub

我确实使用过。在这里选择两次,我知道我应该改变它。

我在Mac上使用Excel 2011,因此请注意,并非所有可在Windows上运行的内容都能正常工作。

*编辑*

首先:即使我激活了所有对象库,这仍然无效。

其次,我在打开对象浏览器时意识到了一些事情:

  1. " ODBCConnection"是一个声明的类("类的ODBCConnection成员的Excel")。但是当我在对象浏览器中点击Excel" ODBCConnection"无处可寻。如果我输入代码" Excel.ODBCConnection.Refresh"它会抛出错误"方法或数据成员未找到"突出显示单词" ODBCConnection"。当我只使用ODBCConnection.Refresh(根据对象浏览器刷新是ODBCConnection的方法)时,会显示相同的错误。

  2. 我对" QueryTable(1).Refresh"有完全相同的问题,这就是抛出错误:"变量未定义"即使它已在对象浏览器中列出并声明(" Excel的Class QueryTable成员")。

  3. 我相信我会为与此相关的所有事情得到这些错误。

    修改

    这会抛出相同的"常规ODBC错误"在线ActiveWorkbook.RefreshAll:

    Dim strConn As String
    Dim strLoginData As String
    Dim QT As QueryTable
    
    Dim strFirmSQL As String
    Dim strPersSQL As String
    
    strConn = "ODBC;DSN=KundeDB;" & strLoginData
    strLoginData = "Uid=*myUid*;Pwd=*myPwd*"
    
    strFirmSQL = "Select * From gi_kunden.tbl_firma"
    strPersSQL = "Select * From gi_kunden.tbl_person"
    
    Dim WSFirm As Worksheet
    Set WSFirm = ActiveWorkbook.Sheets("Firma")
    
    WSFirm.Range("A1:T1000").Clear
    
    For Each QT In WSFirm.QueryTables
        QT.Delete
    Next QT
    
    With WSFirm.QueryTables.Add(strConn, WSFirm.Range("A1"), strFirmSQL)
        .SaveData = True
        .BackgroundQuery = True
        '.Refresh
    End With
    
    
    Dim WSPers As Worksheet
    Set WSPers = ActiveWorkbook.Sheets("Person")
    
    For Each QT In WSPers.QueryTables
        QT.Delete
    Next QT
    
    With WSPers.QueryTables.Add(strConn, WSPers.Range("A1"), strPersSQL)
        .SaveData = True
        .BackgroundQuery = True
        '.Refresh
    End With
    
    ActiveWorkbook.RefreshAll 'FAILS here
    
    Call Replace
    
    WSFirm.Activate
    

1 个答案:

答案 0 :(得分:5)

我无法解决您的问题,但我可以帮您调试。

第一个问题是:该错误消息是什么意思?它是否告诉您,您在数据上运行的查询或命令出现错误,或者是否阻止您连接到数据库?

实际上可以编写信息性错误消息,并且Redmond的任何误导天才实现了查询表选择不会传递数据库服务器和连接库发出的详细错误信息。

幸运的是,我们自己做了一些工作。

QueryTable对象具有连接属性 - 它是一个字符串,而不是一个功能齐全的连接对象,但您可以更详细地检查它并根据ADODB连接对象对其进行测试。尝试使用此函数测试连接字符串,看看是否有任何有用的信息:


Public Sub ConnectionTest(ConnectionString As String)
' Late-binding: requires less effort, but he correct aproach is ' to create a reference to 'Microsoft ActiveX Data Objects' -
'Dim conADO As ADODB.Connection 'Set conADO = New ADODB.Connection
Dim conADO As Object Set conADO = CreateObject("ADODB.Connection")
Dim i As Integer
conADO.ConnectionTimeout = 30 conADO.ConnectionString = ConnectionString
On Error Resume Next
conADO.Open
If conADO.State = 1 Then Debug.Print "Connection string is valid" Else Debug.Print "Connection failed:"

For i = 0 To conADO.Errors.Count With conADO.Errors(i) Debug.Print "ADODB connection returned error " & .Number & " (native error '" & .NativeError & "') from '" & .Source & "': " & .Description End With Next i

End If
Debug.Print "Connection String: " Debug.Print vbTab & Replace(.Connection, ";", ";" & vbCrLf & vbTab) Debug.Print

Set conADO = Nothing

End Sub

...并将其插入您的代码中:


Dim objQueryTable As Excel.QueryTable
Dim strConnect as String
set objQueryTable = ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Range("A1"), Sql:=sqlstringFirma)
With objQueryTable strConnect = .Connection .BackgroundQuery = False .RefreshStyle = xlOverwriteCells .Refresh ' "General ODBC error" hereeee End With
ConnectionTest strConnect ' view the output in the debug window/immediate pane

如果您可以看到错误,可能只是我的ADODB连接实现在您的Mac Office环境中无效:但您完全有可能:

  1. 创建一个连接,看到它工作,并消除了 您的连接字符串或DSN是其来源的可能性 问题...
  2. ...或者您可以在连接参数中发现错误 固定。
  3. 如果连接有效,则可能是您在数据库中运行的查询或命令是问题的根源 - 以及错误消息I'在你的问题中看到的确指向了那个方向 - 所以我们需要深入研究一下。

    不幸的是,我无法知道我使用的工具是否适用于您:这是开发人员和#39;调试代码,你需要修改它才能使它工作。

    它如此繁琐的原因是实施QueryTable的Office团队做出了一些有趣的决定:'连接'和'记录集' QueryTable公开的属性不是全功能的对象 - 我认为它们是允许QueryTable使用对象称为' connection'和'记录集'来自各种不同的提供者,并公开一组共同的属性和方法。它是跨平台可用性的一个很好的决定,但这意味着需要询问这些对象的开发人员不能依赖于运行时存在的任何给定方法 - 所以这是针对反编译代码的'调试'仅限模式。

    您还需要在IDE中注册Microsoft DAO和ADO引用:后期绑定' CreateObject'当您需要能够在“本地人”中查看这些对象时,这是错误的工具。窗口:

    
    Public Sub ConnectionDetails(objQueryTable As Excel.QueryTable)
    Dim rstADO As ADODB.Recordset Dim conADO As ADODB.Connection
    Dim rstDAO As DAO.Recordset Dim conDAO As DAO.Connection
    Dim i As Integer

    Set objQueryTable = Sheet1.ListObjects(1).QueryTable
    With objQueryTable

    Debug.Print "Connection String: " Debug.Print vbTab & Replace(.Connection, ";", ";" & vbCrLf & vbTab) Debug.Print

    Debug.Print "Query Type: " & .QueryType ' Documented here: https://msdn.microsoft.com/en-us/library/office/ff835313.aspx Debug.Print "Query: " & .CommandText Debug.Print "Database request type: " & .CommandType ' XlCmdType documented here: https://msdn.microsoft.com/en-us/library/office/ff197456.aspx

    .MaintainConnection = True
    On Error Resume Next If TypeOf .Recordset Is DAO.Recordset Then

    On Error Resume Next Set rstDAO = .Recordset

    rstDAO.OpenRecordset For i = 0 To DAO.Errors.Count With DAO.Errors(i) Debug.Print "DAO Recordset '" & Left(rstDAO.Name, 24) & "' returned error " & .Number & " from '" & .Source & "': " & .Description End With Next i

    Set conADO = DAO.DBEngine.OpenConnection(.Connection) For i = 0 To DAO.Errors.Count With DAO.Errors(i) Debug.Print "DAO Connection '" & Left(conDAO.Name, 24) & "' returned error " & .Number & " from '" & .Source & "': " & .Description End With Next i

    ElseIf TypeOf .Recordset Is ADODB.Recordset Then

    On Error Resume Next Set rstADO = .Recordset

    If rstADO.State <> 0 Then rstADO.Close rstADO.Open Set conADO = rstADO.ActiveConnection For i = 0 To conADO.Errors.Count With conADO.Errors(i) Debug.Print "ADODB Recordset '" & Left(rstADO.Source, 24) & "' connection returned error " & .Number & " (native error '" & .NativeError & "') from '" & .Source & "': " & .Description End With Next i
    ElseIf Err.Number <> 0 Then

    Debug.Print Err.Source & " Error " & Err.Number & ":" & Err.Description

    Else

    Debug.Print "recordset type is: '" & TypeName(.Recordset) & "': for further information, place a breakpoint in the code and use the 'Locals' window."

    End If
    End With
    End Sub
    代码所做的 - 或尝试做的 - 非常简单:它询问数据库并检索详细的错误消息。

    他们可能会告诉您语法错误或SQL中缺少参数 - 如果数据库是MS-Access,可能会产生误导:&#39;缺少参数&#39;可能意味着字段名称或函数名称未知。这也可能意味着you can't run that SQL outside an MS-Access user session

    如果无效,请返回ConnectionTest代码并针对conADO连接对象运行命令文本: conADO.Execute strCommandText ......并再次询问错误集合。

    对于我可以对这个问题采取的调试工具来说,这几乎是很好的:希望另一个&#39; Stacker可以提出其他方法。