Excel-VBA将不正确的date值从SAS传输到Excel表单

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

我也使用了我的VBA代码中的那些列的format ,如Sheet2.Range(Range("C2"), Range("C2").End(xlDown)).NumberFormat = "YYYY-MM-DD" 。 那么它应该把整个列转换成正确的date格式。

然而,最后,我在1955-08-311955-08-31这样的Excel表中得到了date值,而不是2015-09-012015-09-30

我检查了SAS表,两列都是numeric ,格式是date YYDDMM10.

我在VBA代码中以YYMMDDYY-MM-DD的格式显示,但是没有帮助。 它仍然是在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使用1/1/1960作为第0天的参考date。

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

1/1/1960和12/31/1899之间的天数是21,916。

由于您要从SAS转到Excel,请将21916添加到SASdate。

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

在Excel中设置显示格式不会改变它如何识别单元格中的值。

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

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

您需要将一个属性添加到logging集中,以告诉它如何在导入date时格式化date(将datecolumnnamereplace为date列的名称,您可以通过用逗号分隔列表来定义多个列。

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

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

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

编辑1

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

 ' 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 

从SASdate,时间和date时间值 :

SASdate值是表示1960年1月1日至指定date之间的天数的值。 SAS可以执行AD 1582到AD 19,900之间的date计算。 1960年1月1日以前的date是负数; 之后的date是正数。

如果找不到转换因子,则可能希望将实际的基于数字的date转换为本地计算机的MDY与DMY区域格式中的string看起来像date,并允许Excel对其进行即时处理。 不是最好的解决scheme,但数字date将总是超过60年,没有换算系数,因为1899年12月31日以后每天的Exceldate都是1。