Обновление запроса 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, будет работать.
* РЕДАКТИРОВАТЬ *
Прежде всего: даже если у меня активированы все библиотеки объектов, это все равно не работает.
Во-вторых, я только что понял некоторые вещи, когда открыл браузер объектов:
"ODBCConnection" является объявленным классом ("Class ODBCConnection Member of Excel"). Но когда я нажимаю на Excel в Object-Browser, "ODBCConnection" нигде не найти. Если я введу код "Excel.ODBCConnection.Refresh", он выдаст ошибку "Метод или элемент данных не найден", выделив только слово "ODBCConnection". Та же ошибка отображается, когда я использую только ODBCConnection.Refresh (Refresh является методом ODBCConnection в соответствии с Обозревателем объектов).
У меня точно такая же проблема с "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: но вполне возможно, что у вас есть:
- Создал соединение, увидел, что оно работает, и исключил вероятность того, что ваша строка соединения или DSN является источником проблемы...
- ... Или обнаружил ошибку в параметрах соединения, которую можно исправить.
Если соединение работает, вероятно, источником проблемы является запрос или команда, которую вы выполняете в базе данных, и сообщения об ошибках, которые я видел в вашем вопросе, указывают в этом направлении - поэтому нам нужно немного углубиться,
К сожалению, у меня нет возможности узнать, сработают ли для вас инструменты, которые я использую для этого: это код отладки разработчиков, и вам придется поработать с ним, чтобы заставить его работать.
Причина, по которой это так странно, заключается в том, что команда 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
... И снова опросить сбор ошибок.
Это в значительной степени относится к инструментам отладки, которые я могу использовать для решения этой проблемы: надеюсь, другой "укладчик" может предложить другие подходы.