将SQL Server日期数据类型导入Excel日期格式的问题

时间:2013-04-17 13:54:32

标签: sql excel vba recordset

我正在从SQL Server 2012数据库将数据导入Excel。我遇到的问题是在Excel中无法一致地识别SQL Server 2012 Date数据类型列。

如果我使用ADO Recordsets从特定列导入数据,则将列数据类型为DateDatetime的数据作为VBA数据类型String复制到Recordset中(而不是Date }或Integer)。

在Excel中重现Recordset会生成格式为yyyy-mm-dd的字符串。即使我更改了格式,Excel也不会将这些单元格识别为日期/时间。

然而,当我从另一个单元格引用Excel单元格时,Date类型被识别(例如:A1包含我的SQL VBA Recordset查询的结果,例如“2013-04-17”。我进入单元格A2“= A1 + 1”,A2将其显示为41382。

但是,当我使用MS Query使用ListObjects和ODBC从同一个数据库中提取数据时,将返回来自同一数据库的相同数据,并且日期由Excel正确解释(即我导入一个名为“Transaction Date”的列, SQL数据类型Datetime通过MS查询结果将是MS Excel日期“整数”。

如何修改我的VBA Recordset代码,将yyyy-mm-dd格式的数据视为日期而不是字符串?

谢谢, 约翰

PS:我执行的SQL查询各不相同,有时我从数据类型为“date”的列中获取数据,有时候只是整数或Double数据类型。这意味着难以将“转换(INT,TransactionDate)”硬编入SELECT语句。但是,我是SQL的业余爱好者所以可能有一个超级简单的解决方案(例如,如果我访问数据类型为“DateTime”的列,则SQL应始终发送“CONVERT(DBL,XXX)”而不是XXX,其中XXX是数据类型为DATE的列。

Function GetSQL(strQuery As String) As Variant

Dim rst As ADODB.Recordset
Dim element As Variant
Dim i, j As Integer
Dim v As Variant
On Error GoTo aError


Call ConnecttoDB

cnt.Open
Set rst = New ADODB.Recordset
rst.Open strQuery, cnt, adOpenStatic
rst.MoveFirst
If rst.RecordCount = 0 Then   'i.e. if it's empty
    v = CVErr(xlErrNA)
    rst.Close
    cnt.Close
Else
End If
 v = rst.GetRows

For i = 0 To UBound(v, 1)
    For j = 0 To UBound(v, 2)
        If v(i, j) = -9999 Then
            v(i, j) = CVErr(xlErrNA)
        Else
        End If
    Next j
Next i
GetSQL = Application.WorksheetFunction.Transpose(v)
rst.Close
cnt.Close
Exit Function

aError:
MsgBox Err.Description
rst.Close
cnt.Close
End Function

2 个答案:

答案 0 :(得分:1)

问题产生于使用Excel函数Transpose而不是循环遍历Recordset结果对象的内容。

在通过Excel进行转置​​的过程中,Recordset中包含的一些信息(例如eample数据类型)似乎丢失了。这导致日期被Excel解释为字符串。

我猜你的意思是使用循环,而不是使用Excel Transpose函数,因为这样可以避免丢失上述信息。

答案 1 :(得分:0)

ado recodset中的字段类型无法更改,但您尝试过UDT吗?这是一个用户定义类型的简短示例,它将包装ado记录集。然后在您的代码中,您将使用自己的记录集,它将使用Date数据类型。

添加对Microsoft ActiveX数据对象库的引用。

标准模块vba代码:

Private Const CONNECTION_STRING As String = "Provider=sqloledb;Data Source=SQLSERVER2012;Initial Catalog=Test;Integrated Security=SSPI;"
Private Const SQL_QUERY As String = "select * from dbo.DateTest"

Public Type MyRecord
    Id As Long
    CreatedAt As Date
End Type

Public Sub test()
    Dim myRecodset() As MyRecord
    myRecodset = GetSQL
End Sub

Public Function GetSQL() As MyRecord()

    On Error GoTo aError

    Dim adodbConnection As ADODB.Connection
    Set adodbConnection = New ADODB.Connection
    With adodbConnection
        .ConnectionString = CONNECTION_STRING
        .CursorLocation = adUseServer
        .Open
    End With

    Dim newRecordset() As MyRecord
    Dim newRecord As MyRecord
    Dim rowIndex As Long
    Dim adodbRecordset As ADODB.Recordset

    Set adodbRecordset = New ADODB.Recordset
    With adodbRecordset
        .Open SQL_QUERY, adodbConnection, adOpenStatic
        .MoveFirst

        ReDim newRecordset(.RecordCount - 1)

        Do While Not .EOF
            newRecord.Id = .Fields("Id")
            newRecord.CreatedAt = .Fields("CreatedAt")
            newRecordset(rowIndex) = newRecord
            rowIndex = rowIndex + 1
            .MoveNext
        Loop

    End With

    GetSQL = newRecordset

aError:
    If (Err.Number <> 0) Then MsgBox Err.Description
    adodbRecordset.Close
    adodbConnection.Close
End Function

使用此表进行测试:

CREATE TABLE [dbo].[DateTest]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [CreatedAt] [date] NOT NULL
)