Тип данных SQL Server Time не совместим с Excel? - PullRequest
0 голосов
/ 06 июля 2019

Проблема:

Импорт данных о времени из SQL Server (2014, 2016) с помощью метода VBA CopyFromRecordset() не распознается как время, но имеет тип Standard.

Пример:

SQL-запрос, который используется в Excel VBA

SELECT TOP 100
    [CreationDate],                                     -- Works as expected Datetime; data type of this field is DATETIME 
    CAST(CreationDate AS DATETIME) AS CreationDate2,    -- Works as expected Datetime
    CAST(CreationDate AS TIME(0)) AS CreationTime       -- In Excel the type is Standard and not Time as it should be.
FROM 
    [StackOverflow2013].[dbo].[Comments]

код VBA:

Sub TimeImport()
    Dim Conn As New ADODB.Connection
    Dim RS As New ADODB.Recordset
    Dim SQL As String

    Const ConnStr  As String = "Provider=SQLOLEDB; Data Source=PC\\MSSQLSERVER2014; Initial Catalog = StackOverflow2013; Integrated Security=SSPI;"

    'SQL see above
    Conn.Open ConnStr
    RS.Open SQL, Conn

    ActiveSheet.Cells(1, 1).CopyFromRecordset RS

    RS.Close
    Conn.Close

    Set RS = Nothing  
    Set Conn = Nothing
End Sub

После импорта, если я введу ячейку в столбце времени в Excel с помощью клавиши F2 и нажму клавишу ввода, он правильно изменит тип данных на время. Однако просто изменение формата ячейки во времени не работает.

Если я импортирую запись данных по записи и преобразую поле времени в дату, используя функцию CDate(), то это сработает. Однако это не вариант для меня из-за плохой производительности построчной обработки.

Кто-нибудь сталкивался с этой проблемой раньше и каково было решение?

Спасибо за любую подсказку.

1 Ответ

0 голосов
/ 06 июля 2019

Я нашел следующие обходные пути, которые работают:

  1. После импорта данных я копирую данные из диапазона данных, так сказать, в тот же диапазон.

Если данные находятся в A1:D100, код VBA будет выглядеть примерно так:

ActiveSheet.Range("A1:D100").Value = ActiveSheet.Range("A1:D100").Value 
  1. Вместо CopyFromRecordset() я сохраняю данные набора записей в массив, используя функцию GetRows объекта набора записей, а затем помещаю массив в электронную таблицу следующим образом:

    Sub TimeImport2()
    
        Dim Conn As New ADODB.Connection
        Dim RS As New ADODB.Recordset
        Dim SQL As String
    
        Dim myArr As Variant
        Dim RecCount As Long
    
        Const ConnStr  As String = "Provider=SQLOLEDB; Data Source=PC\\MSSQLSERVER2014; Initial Catalog = StackOverflow2013; Integrated Security=SSPI;"
    
        ' SQL see above
    
        Conn.Open ConnStr
        RS.Open SQL, Conn
    
        myArr = RS.GetRows
        myArr = Application.WorksheetFunction.Transpose(myArr)
        RecCount = UBound(myArr)
    
        ActiveSheet.Range("A1:D" & RecCount) = myArr
    
        RS.Close
        Conn.Close
    
        Set RS = Nothing  
        Set Conn = Nothing
    End Sub
    

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

.Range("A2:A" & RecCount) = Application.Index(myArr, , 4)

До сих пор остается загадкой, почему Excel не распознает тип данных времени SQL Server или получает тип данных, поврежденный методом CopyFromRecordset()?

...