Обновление запроса QueryTable "Общая ошибка ODBC" - VBA Excel 2011 для Mac

РЕДАКТИРОВАТЬ: Новая ошибка найдена?

Возможно, я только что узнал, почему мой сценарий больше не работает. Недавно было обновление для офиса, и, кажется, они реализовали запрос Microsoft, который избавляет от ODBC-менеджера, который я установил и настроил в соответствии со своими потребностями. Теперь реальная проблема может заключаться в том, что этот запрос Microsoft не имеет UNICODE-библиотеки, и я не знаю, где я мог бы разместить их, чтобы запрос Microsoft мог их прочитать / получить. Вернее, я не знаю, как указать в запросе Microsoft путь к UNICODE-библиотеке, так как в диспетчере нет возможности изменить его, или, может быть, я его просто не нашел? В дополнение к этому я не могу открыть диспетчер запросов Microsoft, если я не открою его непосредственно из книги 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

Я использовал. Выберите здесь дважды, и я знаю, что я должен изменить его.

Я работаю в Excel 2011 на Mac, поэтому знайте, что не все, что работает на Windows, будет работать.

* РЕДАКТИРОВАТЬ *

Прежде всего: даже если у меня активированы все библиотеки объектов, это все равно не работает.

Во-вторых, я только что понял некоторые вещи, когда открыл браузер объектов:

  1. "ODBCConnection" является объявленным классом ("Class ODBCConnection Member of Excel"). Но когда я нажимаю на Excel в Object-Browser, "ODBCConnection" нигде не найти. Если я введу код "Excel.ODBCConnection.Refresh", он выдаст ошибку "Метод или элемент данных не найден", выделив только слово "ODBCConnection". Та же ошибка отображается, когда я использую только ODBCConnection.Refresh (Refresh является методом ODBCConnection в соответствии с Обозревателем объектов).

  2. У меня точно такая же проблема с "QueryTable(1).Refresh", который выдает ошибку: "Переменная не определена", даже если она указана и объявлена ​​в обозревателе объектов ("Класс QueryTable Member of Excel").

Я верю, что получу подобные ошибки за все, что с этим связано.

РЕДАКТИРОВАТЬ

Это выдает ту же "Общую ошибку 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 ответ

Я не могу решить вашу проблему, но я могу помочь вам отладить ее.

Первый вопрос: что означает это сообщение об ошибке? Сообщает ли вам, что в запросе или команде, с которой вы выполняете данные, произошла ошибка, или что-то мешает вам подключиться к базе данных?

На самом деле можно написать информативные сообщения об ошибках, и какой бы ошибочный гений в Редмонде не внедрил Таблицу запросов, он решил не передавать детальную информацию об ошибках, генерируемую сервером базы данных и библиотеками соединений.

К счастью, мы делаем часть этой работы сами.

Объект 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. ... Или обнаружил ошибку в параметрах соединения, которую можно исправить.

Если соединение работает, вероятно, источником проблемы является запрос или команда, которую вы выполняете в базе данных, и сообщения об ошибках, которые я видел в вашем вопросе, указывают в этом направлении - поэтому нам нужно немного углубиться,

К сожалению, у меня нет возможности узнать, сработают ли для вас инструменты, которые я использую для этого: это код отладки разработчиков, и вам придется поработать с ним, чтобы заставить его работать.

Причина, по которой это так странно, заключается в том, что команда Office, которая внедрила QueryTable, приняла несколько интересных решений: свойства 'connection' и 'recordset', предоставляемые QueryTable, не являются полнофункциональными объектами - я думаю, что они являются интерфейсами, которые позволяют QueryTable использовать объекты, называемые "соединение" и "набор записей", от различных поставщиков и предоставлять общий набор свойств и методов. Это хорошее решение для кроссплатформенного удобства использования, но это означает, что разработчик, которому нужно опросить эти объекты, не может полагаться на какой-либо конкретный метод, присутствующий во время выполнения - так что это только для декомпилированного кода в режиме "отладки".

Вам также необходимо зарегистрировать ссылки Microsoft DAO и ADO в IDE: поздняя привязка с "CreateObject" - это неправильный инструмент, когда вам нужно иметь возможность просматривать эти объекты в окне "Locals":


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: "отсутствующий параметр" может означать, что имя поля или имя функции неизвестно. Это также может означать, что вы не можете запустить этот SQL вне сеанса пользователя MS-Access.

Если это не сработает, вернитесь к коду ConnectionTest и введите текст команды для объекта подключения conADO: conADO.Execute strCommandText... И снова опросить сбор ошибок.

Это в значительной степени относится к инструментам отладки, которые я могу использовать для решения этой проблемы: надеюсь, другой "укладчик" может предложить другие подходы.

Другие вопросы по тегам