Excel VBA ADODB RecordSet изменяет типы полей с SQL Сервер - PullRequest
0 голосов
/ 03 марта 2020

Я выполняю простой запрос к SQL таблице серверов:

SELECT * FROM MyTable

Таблица содержит три столбца с типами int, bit и datetime2(0). Я использую код в соответствии с:

Dim cnn As ADODB.Connection
Dim rst As ADODB RecordSet
Dim rngDest As Range
:
: ' etc
:
rst.Open "SELECT * FROM MyTable", cnn
rngDest.CopyFromRecordset rst

Это хорошо работает, , за исключением , что, кажется, неправильно понимает типы полей : в нем указано, что типами полей являются 3, 11, 202, которые, согласно документации, Integer (правильно), Boolean (правильно, я думаю) и NVarChar2 - неверно. Третье поле должно быть date , конечно (тип «Дата» равен 135).

В качестве фона: я перенес данные с Access на SQL Server используя SSMA. Эта таблица теперь имеет три типа столбцов, которые я упомянул. Кроме того, я понимаю, что это хорошо известная проблема, что CopyFromRecordset может неправильно указывать типы полей, и я сначала подумал, что именно поэтому третий столбец (дата) отображался в Excel в виде строки, но при ближайшем рассмотрении я вижу, что, когда VBA прочитал набор записей, он уже считает, что поле является текстом, перед строкой CopyFromRecordset. Я чувствую, что если бы я мог заставить VBA как-то распознать, что третье поле должно быть датой, тогда я мог бы преобразовать его внутри. Я бы предпочел не создавать решение для этой таблицы специально, потому что у меня много, много таблиц и представлений, которые необходимо обработать, поэтому я бы предпочел найти подход, который работает для всех них.

Если это важно Я использую строку подключения:

Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Data Source=[REDACTED];Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Use Encryption for Data=False;Tag with column collation when possible=False;Initial Catalog=[REDACTED];

Может кто-нибудь помочь, пожалуйста?

Ответы [ 3 ]

1 голос
/ 03 марта 2020

Обратно совместимый драйвер SQLOLEDB, который поставляется с Windows, не имеет понятия SQL Типы данных сервера, введенные за последние 20 лет, например date. Попробуйте последнюю версию SQL Серверный драйвер OLEDB, MSOLEDB SQL.

Я провел быстрый тест ADO, используя приведенный ниже VbScript, и столбец date возвратил тип ADO 133 (adDBDate).

Set connection = CreateObject("ADODB.Connection")
connection.Open "Provider=MSOLEDBSQL;Data Source=.;Integrated Security=SSPI"
Set recordset = connection.Execute("SELECT CAST(SYSDATETIME() AS date);")
MsgBox recordset.Fields(0).Type
connection.Close
0 голосов
/ 03 марта 2020

Вот решение, которое я нашел для работы (пока я жду, когда ребята из службы поддержки обновят драйвер): [TL; DR: чтение набора записей в вариант varOrig с использованием rst.GetRows; перенести, затем добавить в лист Excel; использование .Value2 = заставляет Excel преобразовать его в правильную дату. [Мы должны транспонировать, потому что .GetRows, несмотря на свое имя, возвращает столбцы данных.]]

Надеюсь, это будет полезно для всех, кто столкнется с подобной проблемой в будущем.

0 голосов
/ 03 марта 2020

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

20130604060133 -> 2013/06/04 06: 01: 33

select
  convert(datetime,SUBSTRING( '20130604060133',1,8),112) +
  convert(datetime,
   ( substring( '20130604060133',9,2) + ':' +
    substring( '20130604060133',11,2)  + ':' +
    substring( '20130604060133',13,2)  )
    ,120) as myDate

Проблема Кажется, где-то еще, но это не ясно. Но есть способ изменить данные. Смотри ниже.

Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim rngDest As Range
:
: ' etc
:
rst.Open "SELECT * FROM MyTable", cnn
rngDest.CopyFromRecordset rst

Dim vDB
Dim rngDB As Range
Set rngDB = rngDest.CurrentRegion
vDB = rngDB
rngDB.NumberFormat = "General"
rngDB = vDB
...