SAS 9.4 64 位 XLSX 32 位导入:带有日期和文本的列作为文本读入,带有未格式化的日期
SAS 9.4 64-bit XLSX 32-bit import: Columns with date and text read in as text, with unformatted dates
我正在使用 64 位 SAS 9.4 从 32 位 Excel 导入文件。我的许多 Excel 列都包含日期和日期列表,如下所示:
9 月日期列
9/13 & 9/27
9/13 & 9/26
9/01 & 9/10 & 9/21
9/23
9/30
9/30
9/28
我不是该文件的所有者,它会定期更新,因此所有主要操作和格式化都需要在 SAS 中进行。导入后,我可以将其更改为每行一个日期的正常列表,但导入本身没有正确导入日期。我的导入代码:
PROC IMPORT OUT=Raw_Import DATAFILE= "J:\filename.xlsx" DBMS=XLSX REPLACE;
SHEET="Sheetname";
GETNAMES=YES;
RUN;
SeptemberDatesCol 导入为字符变量(根据需要),除了 some 具有单个日期的行,日期与 Excel 一起导入原始未格式化日期约定值:
9 月日期列
9/13 & 9/27
9/13 & 9/26
9/01 & 9/10 & 9/21
9/23
42643
42643
42641
我可以做些什么来使列正确导入?当我使用 DBMS=EXCELCS 时,出现 'failed to connect to the server' 错误。考虑到我工作的软件设置(64 位 SAS 9.4 和 32 位 Excel),DBMS=EXCEL 不起作用。预先感谢您提供的任何建议。
当您在包含混合文本和数字的 XLSX 文件中导入列时,SAS 将以原始格式导入数字。您可以使用简单的算术将看起来像原始日期的字符串从 Excel 的基准日期转换为 SAS 的基准日期。因此,如果您减去两个系统使用的基准日期之间的天数差异,还减去 1,因为 SAS 从 0 开始计数,Excel 从 1 开始计数,还减去 1,因为 Excel 认为 1900 年是闰年,你得到.
sasdt = exceldt - ('01JAN1960'd - '01JAN1900'd +2) ;
但是由于 '01JAN1960' 只是零,您可以简化为
sasdt = exceldt + '01JAN1900'd - 2 ;
现在你只需要一点逻辑来区分数字和字符串。例如,您可以测试字符串是否转换为 1('01JAN1900'd)和 43,100('31DEC2017'd)之间的数字,以及它是否确实将其转换为 MM/DD/YYYY 格式的字符串。
if 0 <= input(SeptemberDatesCol,??32.) <= 43100 then
SeptemberDatesCol = put(input(SeptemberDatesCol,??32.),mmddyys10.)
;
因此您的示例数据将转换为:
52 data have ;
53 input SeptemberDatesCol . ;
54 put SeptemberDatesCol= @ ;
55 if 0 <= input(SeptemberDatesCol,??32.) <= 43100 then
56 SeptemberDatesCol = put(input(SeptemberDatesCol,??32.)+'01JAN1900'd-2,mmddyys10.)
57 ;
58 put '-> ' SeptemberDatesCol ;
59
60 cards;
SeptemberDatesCol=9/13 & 9/27 -> 9/13 & 9/27
SeptemberDatesCol=9/13 & 9/26 -> 9/13 & 9/26
SeptemberDatesCol=9/01 & 9/10 & 9/21 -> 9/01 & 9/10 & 9/21
SeptemberDatesCol=9/23 -> 9/23
SeptemberDatesCol=42643 -> 09/30/2016
SeptemberDatesCol=42643 -> 09/30/2016
SeptemberDatesCol=42641 -> 09/28/2016
我正在使用 64 位 SAS 9.4 从 32 位 Excel 导入文件。我的许多 Excel 列都包含日期和日期列表,如下所示:
9 月日期列
9/13 & 9/27
9/13 & 9/26
9/01 & 9/10 & 9/21
9/23
9/30
9/30
9/28
我不是该文件的所有者,它会定期更新,因此所有主要操作和格式化都需要在 SAS 中进行。导入后,我可以将其更改为每行一个日期的正常列表,但导入本身没有正确导入日期。我的导入代码:
PROC IMPORT OUT=Raw_Import DATAFILE= "J:\filename.xlsx" DBMS=XLSX REPLACE;
SHEET="Sheetname";
GETNAMES=YES;
RUN;
SeptemberDatesCol 导入为字符变量(根据需要),除了 some 具有单个日期的行,日期与 Excel 一起导入原始未格式化日期约定值:
9 月日期列
9/13 & 9/27
9/13 & 9/26
9/01 & 9/10 & 9/21
9/23
42643
42643
42641
我可以做些什么来使列正确导入?当我使用 DBMS=EXCELCS 时,出现 'failed to connect to the server' 错误。考虑到我工作的软件设置(64 位 SAS 9.4 和 32 位 Excel),DBMS=EXCEL 不起作用。预先感谢您提供的任何建议。
当您在包含混合文本和数字的 XLSX 文件中导入列时,SAS 将以原始格式导入数字。您可以使用简单的算术将看起来像原始日期的字符串从 Excel 的基准日期转换为 SAS 的基准日期。因此,如果您减去两个系统使用的基准日期之间的天数差异,还减去 1,因为 SAS 从 0 开始计数,Excel 从 1 开始计数,还减去 1,因为 Excel 认为 1900 年是闰年,你得到.
sasdt = exceldt - ('01JAN1960'd - '01JAN1900'd +2) ;
但是由于 '01JAN1960' 只是零,您可以简化为
sasdt = exceldt + '01JAN1900'd - 2 ;
现在你只需要一点逻辑来区分数字和字符串。例如,您可以测试字符串是否转换为 1('01JAN1900'd)和 43,100('31DEC2017'd)之间的数字,以及它是否确实将其转换为 MM/DD/YYYY 格式的字符串。
if 0 <= input(SeptemberDatesCol,??32.) <= 43100 then
SeptemberDatesCol = put(input(SeptemberDatesCol,??32.),mmddyys10.)
;
因此您的示例数据将转换为:
52 data have ;
53 input SeptemberDatesCol . ;
54 put SeptemberDatesCol= @ ;
55 if 0 <= input(SeptemberDatesCol,??32.) <= 43100 then
56 SeptemberDatesCol = put(input(SeptemberDatesCol,??32.)+'01JAN1900'd-2,mmddyys10.)
57 ;
58 put '-> ' SeptemberDatesCol ;
59
60 cards;
SeptemberDatesCol=9/13 & 9/27 -> 9/13 & 9/27
SeptemberDatesCol=9/13 & 9/26 -> 9/13 & 9/26
SeptemberDatesCol=9/01 & 9/10 & 9/21 -> 9/01 & 9/10 & 9/21
SeptemberDatesCol=9/23 -> 9/23
SeptemberDatesCol=42643 -> 09/30/2016
SeptemberDatesCol=42643 -> 09/30/2016
SeptemberDatesCol=42641 -> 09/28/2016