【问题标题】:Excel-VBA transfers incorrect date values from SAS to Excel-sheetExcel-VBA 将不正确的日期值从 SAS 传输到 Excel 表
【发布时间】:2016-02-07 16:15:33
【问题描述】:

我的 VBA 代码通过 ADODB.Connection"SAS.LocalProvider.1" 将 SAS 表传输到 Excel 表。两个 SAS 列是YYYY-MM-DD 格式的日期,如2015-09-012015-09-30

我还使用format 来处理我的VBA 代码中的那些列,例如Sheet2.Range(Range("C2"), Range("C2").End(xlDown)).NumberFormat = "YYYY-MM-DD"。然后应该将整个列转换为正确的日期格式。

但是,最后,我在 Excel 工作表中获得日期值,例如 1955-08-311955-09-29,而不是 2015-09-012015-09-30

我检查了 SAS 表,两列均为 numeric,格式为 dateYYDDMM10.

我在 VBA 代码中写为 YYMMDDYY-MM-DD,因为它以 SAS 格式显示,但它没有帮助。它仍然给出了与 1955 年相同的年份(或仅 55 年)。

在代码中,您可以看到我尝试在“table-transer 之前”更改格式。但我也尝试过“在表转移之后”,但我得到了完全相同的结果。

Public Sub SASTransfer()
  Dim rTarget1 As Range: Set rTarget1 = Sheet2.Range("A2")
  Dim sSasTable1 As String: sSasTable1 = SASOutputPath & "\" & SASOutput1 & ".sas7bdat"

    Sheet2.Range(Range("C2"), Range("C2").End(xlDown)).NumberFormat = "YYYY-MM-DD" ' This should change the format of the whole C-column
    Sheet2.Range(Range("D2"), Range("D2").End(xlDown)).NumberFormat = "YYYY-MM-DD"

    Dim con1 As New ADODB.Connection
    Dim rs1 As New ADODB.Recordset
    con1.Provider = "SAS.LocalProvider.1"
    con1.Open
    rs1.Open sSasTable1, con1, adOpenForwardOnly, adLockReadOnly, ADODB.adCmdTableDirect
    rTarget1.CopyFromRecordset rs1
    rs1.Close
    Set rs1 = Nothing
    con1.Close
    Set con1 = Nothing

End Sub

【问题讨论】:

  • 仅供参考,您看到这一点的原因是 SAS 将日期存储为 1960 年 1 月 1 日到相关日期之间的天数,而 Excel 将它们存储为 31/12/ 之后的天数1899.
  • @Rory,不,不是。这是因为 excel 需要一种日期格式,而 sas 提供另一种。
  • @NickDewitt 所以,结果日期的天数差异完全可以用它来解释,这完全是巧合吗?多么奇怪。
  • @rory 哦,是的,公平点,抱歉在我下班时匆忙发表评论 - 1960 年基准日期和 1900 年基准日期在技术上是不同的格式 ;-)

标签: vba excel date sas


【解决方案1】:
  • SAS 使用 1/1/1960 作为第 0 天的参考日期。

  • Excel 使用 1/0/1900(即 12/31/1899)作为第 0 天的参考日期。

1960 年 1 月 1 日到 1899 年 12 月 31 日之间的天数为 21,916。

因为您要从 SAS 转到 Excel,所以将 21916 添加到 SAS 日期。

data excel_export;
     set have;
     Excel_Date = SAS_Date + 21916;
     format Excel_Date mmddyy10.;
run;

【讨论】:

  • 谢谢。这不是一个完美的解决方案,但至少它是一个解决方案。只有这种方法有效。
  • 21,916 是 Microsoft 认为介于 1899 年 12 月 31 日和 1960 年 1 月 1 日之间的天数(此处使用的正确数字也是如此)。它们包括 1900 年 2 月 29 日,但是这不是闰年,因此该日期不应该存在。多年前,当我使用 1900 日期系统从另一个包转换时,我就被这个发现了!另一个包将 1900 年 1 月 1 日设置为 0,所以我最终与 Microsoft 相差 2 天。
  • 出于某种原因,Excel 和 SAS 都会不时执行此操作。我无法确定它发生的原因,但偶尔我会导入/导出一些 Excel 数据并且需要执行类似的操作。我猜这与 Excel 中的列类型有关。
【解决方案2】:

在excel中设置显示格式不会改变它对单元格中值的识别方式。

您需要在 adodb 连接上设置日期格式,而不是在工作表中的单元格上。

http://support.sas.com/documentation/tools/oledb/ddh001.htm

您需要向记录集添加一个属性,告诉它如何在导入日期时对其进行格式化(将 datecolumnname 替换为您的日期列的名称,您可以通过用逗号分隔列表来定义多个列。

rst.Properties("SAS Formats") = "datecolumnname=ddmmyy8."

这将以 dd/mm/yyyy 格式导入日期。

您需要设置传入数据的格式以匹配您的区域设置,然后 excel 将正确解释日期并按照您在单元格格式中设置的方式显示它。

编辑 1

SAS 提供以下示例来提取格式化数据,他们建议在执行查询之前设置记录集的活动连接:

' obConnection is an open Connection object.
Dim obRecordset As New ADODB.Recordset

obRecordset.ActiveConnection = obConnection
obRecordset.Properties("SAS Formats") = "saledate=mmddyy8.,+price=dollar8.2."

' The second parameter on the Open method must remain empty.
obRecordset.Open "sales", , adOpenStatic, adLockReadOnly, adCmdTableDirect

【讨论】:

  • SAS 和 Excel 都使用整数作为日期,SAS 的 0 是 1960-01-01,Excel 是 1900-01-00。我推荐SI Format 用于接口,无论您的区域设置如何,Excel 都会识别它
  • 如果您的地区是英国,并且您将字符串日期设置为美国格式,根据日期数是否小于或等于 12,它有时会感到困惑。
  • 我试过你写的rs1.Properties("SAS Formats") = "PeriodFrom=ddmmyy8.",但它给出的错误就像它找不到对象(我不知道它对对象意味着什么)。 rs1 是记录集的名称,PeriodFrom 是日期列的名称。
  • @NickDewitt 抱歉,我不得不离开。错误消息是 Run Time Error 3265 - Item not found in this collectionrs1.Properties("SAS Formats") = "PeriodFrom=ddmmyy8."。正如我所写,rs1 是记录集的名称,PeriodFrom 是 SAS 列的名称。
  • 请耐心等待我尝试登录带有 sas 的服务器,以便我可以为您进行测试。 vpn 正在家里玩!
【解决方案3】:

来自About SAS Date, Time, and Datetime Values

SAS 日期值是表示 1960 年 1 月 1 日与指定日期之间的天数的值。 SAS 可以对从公元 1582 年到公元 19,900 年的日期进行计算。 1960 年 1 月 1 日之前的日期为负数;之后的日期是正数。

如果您找不到转换因子,您可能希望将基于数字的实际日期转换为本地计算机的 MDY 与 DMY 区域格式的字符串,并允许 Excel 即时处理它们飞。不是最好的解决方案,但数字日期在 1899 年 12 月 31 日之后的每一天都会用 1 表示,因为 Excel 日期在 1899 年 12 月 31 日之后的每一天都会超过 60 年。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多