1

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

如果我使用 ADO 记录集从特定列导入数据,则具有列数据类型Date或的数据将作为 VBA 数据类型(而不是或)Datetime复制到记录集中。StringDateInteger

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

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

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

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

谢谢,约翰

PS:我执行的 SQL 查询各不相同,因此有时我从数据类型为“日期”的列中获取数据,有时它只是整数或 Double 数据类型。这意味着实际上不可能将“Convert(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
4

2 回答 2

1

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

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

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

于 2013-04-24T15:04:43.830 回答
0

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

添加对 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
)
于 2013-04-17T17:53:36.033 回答