BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
leackell13
Fluorite | Level 6

Hi,

 

I originally received 2 Excel sheets to merge together for this project. After I merged them, I successfully corrected the dates using this code:

 

DATA SubQ.dataclean1;

SET SubQ.data;

date_varXR1 = Input(postop_XR_date, mmddyy10.); /* Change dates from character to date values */
format date_varXR1 mmddyy10.;
DROP postop_XR_date;
RENAME date_varXR1=postop_XR_date;
XR2_num = Input(Second_Xray_date, mmddyy10.);
date_varXR2 = XR_num - 21916;
format date_varXR2 mmddyy10.;
DROP Second_Xray_date;
RENAME date_varXR2=Second_Xray_date;
RUN;

However, they just gave me a more recent Excel file with the data already combined, and now the same code isn't working. Is there something different about this Excel file that is causing an issue? I have attached the file with only the dates (removed private patient info).

 

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

Excel is just not a great data source. Below code should work for you.

PROC IMPORT 
  OUT= work.temp 
  DATAFILE= "c:\temp\Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx"
  DBMS=xlsx REPLACE;
  SHEET="CPT 23472";
  /* ensure that all columns get always read as character */
  GETNAMES=no;
run;

/* read csv into SAS table */
data want;
  attrib 
    postop_XR_date                length=8 format=date9.
    Immediate_postop_XR_findings  length=$1000
    Second_Xray_date              length=8 format=date9.
    Date_res_of_gas               length=8 format=date9.
    Infection                     length=$2
    ;
  set work.temp(firstobs=2);

  /* for dates: convert string with Excel count of days to SAS Date value */
  postop_XR_date                =input(a,?? 32.) + '30DEC1899'd ;             
  Immediate_postop_XR_findings  =b;
  Second_Xray_date              =input(c,?? 32.) + '30DEC1899'd ;
  Date_res_of_gas               =input(d,?? 32.) + '30DEC1899'd ;
  Infection                     =e;

  drop a b c d e;

run;

/* clean-up */
proc delete data=work.temp;
run;quit;

Because the Excel dates get read as character the SAS columns contain a string of digits that is the count of days like Excel does it. To convert this to a SAS Date value which is the count of days since 1/1/1960 we need to add more days to it as discussed and solved here

 

I'm using getnames=no with Proc Import to ensure that the Excel columns always get converted to a SAS character variable. This to ensure stable results even for the day where you get an Excel with no blank cells where SAS would convert the values directly to numerical columns with SAS Date values (if we wouldn't treat the header column as data).

 

 

 

View solution in original post

12 REPLIES 12
Quentin
Super User

What does 'not working' mean?  Are you getting an error in your log?  (Please show) Are you getting an incorrect results? (Please show)

 

Could be a typo in your code?:

	XR2_num = Input(Second_Xray_date, mmddyy10.);
	date_varXR2 = XR_num - 21916;   * <--- should this be XR2_num - 21916? ;

 

The Boston Area SAS Users Group is hosting free webinars!
Next up: Lisa Mendez & Richann Watson present Get Tipsy with Debugging Tips for SAS® Code: The After Party on Wednesday Jul 16.
Register now at https://www.basug.org/events.
leackell13
Fluorite | Level 6
Good catch on that typo! However, even when I corrected it, I still got inaccurate results. I have attached a screenshot of my log.
ballardw
Super User

Run Proc Contents on the data from the new spread sheet and show us the result.

 

One thing I see as a possibility is that the data may been "imported" as a date value so those Inputs to create date values from character may not be needed and result in messages in the log about invalid data. Or that the text of dates changed so that the informat to read the data needs to change.

 

Please post LOG as text, copy the text and on the forum open a text box and paste the log text.

Pictures are much harder to do things like copy text and show a suggested change, as in I'm too lazy to retype much if any of your log.

 

You might want to spend some time scanning the forum about all the inconsistencies encountered from one version to another of "same structure" spreadsheet files that do not import "correctly".

leackell13
Fluorite | Level 6
You may have a point because this is what the log shows:

1 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
68
69 DATA SubQ.dataclean1;
70
71 SET SubQ.data;
72
73 date_varXR1 = Input(postop_XR_date, mmddyy10.); /* Change dates from character to date values */
74 format date_varXR1 mmddyy10.;
75 DROP postop_XR_date;
76 RENAME date_varXR1=postop_XR_date;
77 XR2_num = Input(Second_Xray_date, mmddyy10.);
78 date_varXR2 = XR2_num - 21916;
79 format date_varXR2 mmddyy10.;
80 DROP Second_Xray_date;
81 RENAME date_varXR2=Second_Xray_date;
82 /* date_varAdd = Input(Additional_Service_Date, mmddyy10.);
83 format date_varAdd mmddyy10.;
84 DROP Additional_Service_Date;
85 RENAME date_varAdd=Additional_Service_Date;
86 XR_num = Input(Immediate_postop_XR_date, 8.);
87 date_varXR = XR_num - 21916;
88 format date_varXR mmddyy10.;
89 DROP Immediate_postop_XR_date;
90 RENAME date_varXR=Immediate_postop_XR_date;
91 XR2_num = Input(SECOND_XR_date, 8.);
92 date_varXR2 = XR2_num - 21916;
93 format date_varXR2 mmddyy10.;
94 DROP SECOND_XR_date;
95 RENAME date_varXR2=SECOND_XR_date;
96 date_numResolution = Input(Date_Resolution, 8.);
97 date_varResolution = date_numResolution - 21916;
98 format date_varResolution mmddyy10.;
99 DROP Date_Resolution;
100 RENAME date_varResolution=Date_Resolution; */
101
102
103 RUN;

NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43633
Immediate postop XR findings=Re-redemonstration right reverse total shoulder arthroplasty in anatomic alignment, without loosening o
r periprosthetic fracture. Suspect bone demineralization. Heterotopic ossification about the superolateral right shoulder.
Second_Xray_date=43649 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=2
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43115
Immediate postop XR findings=A reverse left total shoulder prosthesis is present. Soft tissue gas is visible, consistent with recent
surgery. Second_Xray_date=43152 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=3
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43297
Immediate postop XR findings=Compared with December 7, 2017. New postoperative changes associated with reverse shoulder arthroplasty
with intact hardware on this single view. Second_Xray_date=43327 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=.
date_varXR2=. _ERROR_=1 _N_=4
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43560
Immediate postop XR findings=Interval reverse shoulder arthroplasty in the right. No dislocation at this time. One cerclage wire see
n about the proximal right humerus. The lateral cortex of the proximal humerus is disrupted. The shaft of the humeral prosthesis app
ears angulated, its tip more medial and the proximal aspect of the device more lateral. This alignment is much as on the fluoroscopi
c images from earlier today, however. Second_Xray_date=43574 Date_res_of_gas=43602 Infection=N date_varXR1=. XR2_num=. date_varXR2=.
_ERROR_=1 _N_=5
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43724
Immediate postop XR findings=Interval right shoulder arthroplasty with no evidence of hardware complication. Small foci of air vis
ualized around the right shoulder. Alignment is anatomic. Heterotopic ossification visualized in the proximal humerus.
Second_Xray_date=43739 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=7
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43178
Immediate postop XR findings=A reverse right total shoulder prosthesis is newly demonstrated. There is no evidence of hardware compl
ication. The bones are demineralized Second_Xray_date=43194 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=.
_ERROR_=1 _N_=14
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43105
Immediate postop XR findings=Based upon a single AP view, reverse shoulder prosthesis hardware is in anatomic alignment and there ar
e no signs of periprosthetic fracture. Postoperative soft tissue air is expected. Included lung is clear. Second_Xray_date=43117
Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=16
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43311
Immediate postop XR findings=A new right reverse total shoulder prosthesis is present. There is no evidence of hardware complicati
on. Moderate degenerative changes are present at the acromioclavicular joint. Second_Xray_date=43320 Date_res_of_gas=43404
Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=18
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43042
Immediate postop XR findings=Left shoulder arthroplasty. No prosthetic dislocation or periprosthetic fracture. The visible ribs
are intact and lungs are clear. Second_Xray_date=43419 Date_res_of_gas= Infection=N date_varXR1=04/30/1942 XR2_num=. date_varXR2=.
_ERROR_=1 _N_=19
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43423
Immediate postop XR findings=Interval postsurgical changes related to right reverse total shoulder arthroplasty. Gas within the su
bacromial space is likely postsurgical in etiology. No evidence of hardware fracture, loosening, or periprosthetic fracture on thi
s limited single view. Faint linear osseous density along the superior lateral margin of the residual humeral head, is present on
preoperative radiographs, may be related to tendinopathy. Second_Xray_date=43434 Date_res_of_gas= Infection=N date_varXR1=.
XR2_num=. date_varXR2=. _ERROR_=1 _N_=21
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43486
Immediate postop XR findings= A revision left total shoulder prosthesis is newly demonstrated. There is no evidence of hardware l
oosening. Soft tissue gas is present about the left shoulder Second_Xray_date=43498 Date_res_of_gas= Infection=N date_varXR1=.
XR2_num=. date_varXR2=. _ERROR_=1 _N_=27
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43339
Immediate postop XR findings=Interval placement of a reverse right total shoulder prosthesis. The prosthetic alignment is anatomic
. No periprosthetic fracture. Subsegmental atelectasis is present in the left lung base. Second_Xray_date=43348
Date_res_of_gas=43446 Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=28
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43840
Immediate postop XR findings=Reverse total shoulder prosthesis is in place in the interim. No periprosthetic fracture or dislocation
. Soft tissues lying over the lateral arm. Second_Xray_date=43845 Date_res_of_gas=N/A Infection=N date_varXR1=. XR2_num=.
date_varXR2=. _ERROR_=1 _N_=30
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43416
Immediate postop XR findings=Interim left reverse total shoulder arthroplasty in anatomic alignment, without evidence of hardware co
mplication. Unchanged moderate acromioclavicular osteoarthrosis. No acute fracture or aggressive osseous lesion. Post surgical
changes in the soft tissues. Second_Xray_date=43425 Date_res_of_gas=43516 Infection=N date_varXR1=. XR2_num=. date_varXR2=.
_ERROR_=1 _N_=32
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43451
Immediate postop XR findings=Reverse total shoulder arthroplasty in place without evidence of complication. Mild pulmonary vascula
r congestion of the visualized lung field. Post surgical changes with subcutaneous gas. Second_Xray_date=43460
Date_res_of_gas=43574 Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=33
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43486
Immediate postop XR findings=compared with examination April 9, 2018. New postoperative changes total left shoulder arthroplasty wit
h intact hardware in this single view. Surgical drain is in place. Incompletely visualized spine hardware. Second_Xray_date=43497
Date_res_of_gas=43637 Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=38
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43556
Immediate postop XR findings=Post surgical changes from left reverse total shoulder arthroplasty. Components appear well aligned.
No evidence of periprosthetic fracture. Overlying soft tissues are unremarkable. Small joint effusion with small pockets of su
bcutaneous gas, presumably postprocedural in nature. Mild osteoarthrosis of the acromioclavicular joint. Partially visualized lo
wer lumbar spine fixation. Second_Xray_date=43572 Date_res_of_gas= Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1
_N_=39
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=43269
Immediate postop XR findings=A reverse right total shoulder prosthesis is present. There is no evidence of periprosthetic fracture
or hardware failure. Soft tissue gas is demonstrated, consistent with recent surgery. Second_Xray_date=43278 Date_res_of_gas=
Infection=N date_varXR1=. XR2_num=. date_varXR2=. _ERROR_=1 _N_=40
NOTE: Invalid argument to function INPUT at line 77 column 12.
postop_XR_date=42170
Immediate postop XR findings=There is a right shoulder hemiarthroplasty in anatomic alignment without loosening or failure. Hetero
geneous appearance of the soft tissues is noted related to recent surgery. The right hemithorax is unremarkable
Second_Xray_date=NONE Date_res_of_gas= Infection=N date_varXR1=04/21/1970 XR2_num=. date_varXR2=. _ERROR_=1 _N_=41
NOTE: Invalid argument to function INPUT at line 73 column 16.
NOTE: Invalid argument to function INPUT at line 77 column 12.
WARNING: Limit set by ERRORS= option reached. Further errors of this type will not be printed.
postop_XR_date=43131
Immediate postop XR findings=A reverse left total shoulder prosthesis is newly demonstrated. The greater tuberosity fracture fragmen
t demonstrates mild displacement Second_Xray_date=43138 Date_res_of_gas=43161 Infection=N date_varXR1=. XR2_num=. date_varXR2=.
_ERROR_=1 _N_=43
NOTE: Missing values were generated as a result of performing an operation on missing values.
Each place is given by: (Number of times) at (Line):(Column).
481 at 78:24
NOTE: Mathematical operations could not be performed at the following places. The results of the operations have been set to
missing values.
Each place is given by: (Number of times) at (Line):(Column).
380 at 73:16 393 at 77:12
NOTE: There were 733 observations read from the data set SUBQ.DATA.
NOTE: The data set SUBQ.DATACLEAN1 has 733 observations and 6 variables.
NOTE: DATA statement used (Total process time):
real time 0.02 seconds
user cpu time 0.01 seconds
system cpu time 0.00 seconds
memory 1752.75k
OS Memory 26808.00k
Timestamp 09/30/2022 09:36:21 PM
Step Count 41 Switch Count 2
Page Faults 0
Page Reclaims 200
Page Swaps 0
Voluntary Context Switches 51
Involuntary Context Switches 0
Block Input Operations 768
Block Output Operations 1056


104
105 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
115

The weird thing is when I import the file:


PROC IMPORT OUT= SubQ.data DATAFILE= "/home/u58935925/sasuser.v94/sports med/SubQ/Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx"
DBMS=xlsx REPLACE;
SHEET="CPT 23472";
GETNAMES=YES;
RUN;

it shows the dates as 5-digit numbers (which I realize are the number of days from day 0) as character values. And like I said, those 2 conversions resulted in accurate dates when they were used on a different Excel spreadsheet with similar data.
Tom
Super User Tom
Super User

That is not a very friendly way to share data.  The workbook has three sheets.  Two of them have names that are not valid SAS names.  And the third is completely empty.

915  libname xx xlsx "C:\downloads\Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx";
NOTE: Libref XX was successfully assigned as follows:
      Engine:        XLSX
      Physical Name: C:\downloads\Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx
916  proc copy inlib=xx outlib=work;
917  run;

NOTE: Copying XX.CPT 23472 to WORK.CPT 23472 (memtype=DATA).
NOTE:    Variable Name Change.  Immediate postop XR findings -> Immediate_postop_XR_findings
NOTE: BUFSIZE is not cloned when copying across different engines. System Option for BUFSIZE was used.
ERROR: The value CPT 23472 is not a valid SAS name.
ERROR: File WORK.'CPT 23472'n.DATA has not been saved because copy could not be completed.
NOTE: Copying XX.MYBI2.CUMEDICINE.US BISM SERVIC to WORK.MYBI2.CUMEDICINE.US BISM SERVIC (memtype=DATA).
NOTE:    Variable Name Change.  23472 -> _23472
NOTE: BUFSIZE is not cloned when copying across different engines. System Option for BUFSIZE was used.
ERROR: The value MYBI2.CUMEDICINE.US BISM SERVIC is not a valid SAS name.
ERROR: File WORK.'MYBI2.CUMEDICINE.US BISM SERVIC'n.DATA has not been saved because copy could not be completed.
NOTE: Copying XX.SHEET1 to WORK.SHEET1 (memtype=DATA).
NOTE: BUFSIZE is not cloned when copying across different engines. System Option for BUFSIZE was used.
NOTE: The import data set has 0 observations and 0 variables.
NOTE: There were 0 observations read from the data set XX.SHEET1.
NOTE: The data set WORK.SHEET1 has 0 observations and 0 variables.
NOTE: Statements not processed because of errors noted above.
NOTE: PROCEDURE COPY used (Total process time):
      real time           0.06 seconds
      cpu time            0.04 seconds

NOTE: The SAS System stopped processing this step because of errors.

If you set the VALIDMEMNAME option to EXTEND you can use name literals for member names.  T

Let's check out that first sheet to see what is going on.

proc contents data=xx.'CPT 23472'n varnum; run;

You seem to have 3 variables that from their names appear like they should have date values, but instead are character strings.

#    Variable                        Type    Len    Format    Informat    Label

1    postop_XR_date                  Char      8    $8.       $8.         postop_XR_date
2    Immediate_postop_XR_findings    Char    640    $640.     $640.       Immediate postop XR findings
3    Second_Xray_date                Char      5    $5.       $5.         Second_Xray_date
4    Date_res_of_gas                 Char      5    $5.       $5.         Date_res_of_gas
5    Infection                       Char      2    $2.       $2.         Infection

So let's look at a few of the values to see what is happening.  No need to look at all 600+ characters of that long string.

proc print data=xx.'CPT 23472'n(obs=10) width=min;
  format _character_ $32. ;
run;

Result:

                                                           Second_     Date_
            postop_                                         Xray_     res_of_
     Obs    XR_date      Immediate_postop_XR_findings       date        gas      Infection

       1     42604     Reverse total shoulder arthropla     42620                    N
       2     43633     Re-redemonstration right reverse     43649                    N
       3     43115     A reverse left total shoulder pr     43152                    N
       4     43297     Compared with December 7, 2017.      43327                    N
       5     43560     Interval reverse shoulder arthro     43574      43602         N
       6     42506     New reverse total shoulder prost     42517                    N
       7     43724     Interval right shoulder arthropl     43739                    N
       8     42580     A reverse right total shoulder p     42592                    N
       9     42723     There is been interval placement     42734                    N
      10     42681     There is been interval placement     42690                    N

So it clearly looks like some of the cells in those three columns have TEXT instead of DATE values.  So when SAS converted the sheet into a dataset it had to make the variable CHARACTER to handle those few cells with text in them.  When it does that it stores the actual number Excel uses to represent the date values as a raw digit string.  Hence the 5 digit strings we see in the first 10 observations.

So let's see what type of gibberish is confusing excel and SAS about what type of variables those should be.

proc print data=xx.'CPT 23472'n(obs=10) width=min;
  where not (lengthn(postop_XR_date) in (0,5))
     or not (lengthn(Second_Xray_date) in (0,5))
     or not (lengthn(Date_res_of_gas) in (0,5))  
;
  format _character_ $32. ;
run;

So the first one has '1/29/18'.  That looks like a date to me. Perhaps whoever built the spreadsheet is in a region that prefers to enter dates in DMY order instead. If so then there is no month number 29.

The second one has values like 'NONE'.  That is NOT a date in any shape.

The third one has values like 'N/A' or 'NA'.  Neither of those is a date either.

 

Fixing the second two looks simple.  Just convert the string to a number and add '30DEC1899'd to adjust for the difference in offset date. (Do NOT use magic numbers like the one in your post, how can anyone reading that understand why you used that particular number?)

For the first one you might want to add some more logic to check if the string is actually in MDY style instead.

data want;
  set xx.'CPT 23472'n ;
  array dates postop_XR_date Second_Xray_date Date_res_of_gas ;
  array daten postop_XR_date_n Second_Xray_date_n Date_res_of_gas_n ;
  do over dates;
    daten=input(dates,??5.);
    if not missing(daten) then daten=daten+'30DEC1899'd ;
    else daten=input(dates,??mmddyy10.);
  end;
  format postop_XR_date_n Second_Xray_date_n Date_res_of_gas_n yymmdd10.;
run;

proc print data=want (obs=10) width=min;
  format _character_ $32.;
run;

Tom_0-1664568877311.png

 

 

leackell13
Fluorite | Level 6
Sorry, I should have specified that I'm only using one sheet:



PROC IMPORT OUT= SubQ.data DATAFILE= "/home/u58935925/sasuser.v94/sports med/SubQ/Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx"
DBMS=xlsx REPLACE;
SHEET="CPT 23472";
GETNAMES=YES;
RUN;
Kurt_Bremser
Super User

Your problems come from the fact that you use the worst available file format for data interchange. Use csv or other text files and read them with data steps, and you'll have full control over column types and attributes

Patrick
Opal | Level 21

Excel is just not a great data source. Below code should work for you.

PROC IMPORT 
  OUT= work.temp 
  DATAFILE= "c:\temp\Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx"
  DBMS=xlsx REPLACE;
  SHEET="CPT 23472";
  /* ensure that all columns get always read as character */
  GETNAMES=no;
run;

/* read csv into SAS table */
data want;
  attrib 
    postop_XR_date                length=8 format=date9.
    Immediate_postop_XR_findings  length=$1000
    Second_Xray_date              length=8 format=date9.
    Date_res_of_gas               length=8 format=date9.
    Infection                     length=$2
    ;
  set work.temp(firstobs=2);

  /* for dates: convert string with Excel count of days to SAS Date value */
  postop_XR_date                =input(a,?? 32.) + '30DEC1899'd ;             
  Immediate_postop_XR_findings  =b;
  Second_Xray_date              =input(c,?? 32.) + '30DEC1899'd ;
  Date_res_of_gas               =input(d,?? 32.) + '30DEC1899'd ;
  Infection                     =e;

  drop a b c d e;

run;

/* clean-up */
proc delete data=work.temp;
run;quit;

Because the Excel dates get read as character the SAS columns contain a string of digits that is the count of days like Excel does it. To convert this to a SAS Date value which is the count of days since 1/1/1960 we need to add more days to it as discussed and solved here

 

I'm using getnames=no with Proc Import to ensure that the Excel columns always get converted to a SAS character variable. This to ensure stable results even for the day where you get an Excel with no blank cells where SAS would convert the values directly to numerical columns with SAS Date values (if we wouldn't treat the header column as data).

 

 

 

leackell13
Fluorite | Level 6
Thanks! Just converting the file to a CSV file worked; the dates just imported how I wanted them to. I don't remember why, but I had previously had issues with importing CSV files, which is why I had been sticking with Excel.
Tom
Super User Tom
Super User

CSV files are much easier to deal with because you do not need to use PROC IMPORT to GUESS how to read them.  You can instead just write your own data step that reads them directly.

 

The one thing where XLSX files are better is when the values of one or more cells contain end of line characters.

https://communities.sas.com/t5/SASware-Ballot-Ideas/Enhancements-to-INFILE-FILE-to-handle-delimited-...

 

Patrick
Opal | Level 21

Actually: Using the EXCEL engine there is a direct way to get to the desired result.

options validvarname=v7;
PROC IMPORT 
  OUT= work.want 
  DATAFILE= "c:\temp\Master Compiled Spreadsheet 09-14-2022 Kelly edit dates only.xlsx"
  DBMS=excel 
  REPLACE
  ;
  dbdsopts= "dbtype=( postop_XR_date='date' 
                      Second_Xray_date='date' 
                      Date_res_of_gas='date'
                    )";
  ;
  SHEET="CPT 23472";
  GETNAMES=yes;
run;
Quentin
Super User

I wish the XLSX engine would support DBSASTYPE for specifying the type of each column when you read in an Excel file.  If you agree, please upvote: https://communities.sas.com/t5/SASware-Ballot-Ideas/Add-DBSASTYPE-or-similar-option-to-XLSX-engine-t....

The Boston Area SAS Users Group is hosting free webinars!
Next up: Lisa Mendez & Richann Watson present Get Tipsy with Debugging Tips for SAS® Code: The After Party on Wednesday Jul 16.
Register now at https://www.basug.org/events.

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 12 replies
  • 4881 views
  • 4 likes
  • 6 in conversation