刷新QueryTable引发“一般ODBC错误” – VBA Excel 2011 for Mac

编辑:发现新的错误?

我可能刚刚发现为什么我的脚本不能工作了。 最近有一个办公室更新,似乎他们已经实施了微软查询,摆脱了我安装和configuration我的需要的ODBC-Manager。 现在实际的问题可能是这个微软查询没有UNICODE库,我不知道我可以把它们放在哪里,以便微软的查询会读取/获取它们。 或者说,我不知道如何给微软查询的UNICODE库的path,因为在经理有没有可能改变它,也许有,我只是没有find它? 除此之外,我不能打开微软查询pipe理器,除非我直接从Excel工作簿中打开它。

原文问题

这段代码工作了一段时间。 现在使用完全相同的代码,我得到一个运行时错误。 在这里,我已经要求在这种情况下的帮助,并得到它的工作。

代码如下:

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”是一个声明的类(“Excel类ODBCConnection成员”)。 但是当我在对象浏览器中单击Excel时,“ODBCConnection”无处可寻。 如果我input代码“Excel.ODBCConnection.Refresh”,则会抛出错误“找不到方法或数据成员”,仅突出显示“ODBCConnection”一词。 当我仅使用ODBCConnection.Refresh(根据对象浏览器刷新为ODBCConnection的方法)时,会显示相同的错误。

  2. “QueryTable(1).Refresh”,即使在对象浏览器(“Excel的Excel类QueryTable成员”)中列出并声明错误:“variables未定义”,也有同样的问题。

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

编辑

这引发ActiveWorkbook.RefreshAll行上相同的“一般ODBC错误”:

 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 

我无法解决你的问题,但我可以帮你debugging它。

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

实际上可以编写信息错误消息,并且在Redmond实施查询表的任何错误的天才select不通过由数据库服务器和连接库发出的详细的错误信息。

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

QueryTable对象具有连接属性 – 它是一个string,而不是一个全function的连接对象,但您可以更详细地检查它,并根据ADODB连接对象进行testing。 试试这个函数来testing连接string,看看是否有任何有用的信息:

 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. 创build一个连接,看到它的工作,并消除了您的连接string或DSN是问题的根源的可能性…
  2. …或者在你可以修复的连接参数中发现一个错误。

如果连接正常工作,那么可能是您在数据库上运行的查询或命令是问题的根源 – 而且我在您的问题中看到的错误消息也指向了这个方向 – 所以我们需要深入研究一下。

不幸的是,我无法知道我使用的工具是否适用于您:这是开发人员的debugging代码,您需要修补它才能使其工作。

这么做的原因是,实现QueryTable的Office团队做了一些有趣的决定:QueryTable公开的“连接”和“logging集”属性不是全function的对象 – 我认为它们是允许QueryTable使用来自各种不同提供者的称为 “连接”和“logging集”的对象,并公开一组共同的属性和方法。 这对于跨平台可用性来说是一个很好的决定,但是这意味着需要查询这些对象的开发人员不能依赖运行时提供的任何给定的方法 – 所以这仅适用于以“debugging”模式进行反编译的代码。

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

 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中有语法错误或缺less参数 – 如果数据库是MS-Access,可能会引起误解。“缺less参数”可能意味着字段名称或函数名称未知。 这也可能意味着您不能在MS-Access用户会话之外运行该SQL 。

如果工作失败,请回到ConnectionTest代码,并针对conADO连接对象运行命令文本: conADO.Execute strCommandText …然后再次询问错误集合。

对于我可以用来解决这个问题的debugging工具来说,这很重要:希望另一个“堆栈器”能够提出其他方法。