For one of the subject areas I deal with day to day, categorical data values are often stored in the database in narrow character fields, so we need to apply SAS formats to get readable values out in reports. To maintain these formats I store them in an Excel workbook, looking roughly like this:
This is a relatively painless way to manage keeping SAS formats up to date, as well as making them easily accessible to people who need to inspect them. Each format is stored in a named range, with the name of the range matching the name of the format. The column headers are chosen to agree with the SAS Format procedure requirement for an input control data set. The above range, for instance, would be named ‘excel_user’, and would be used to input the required data for a character format (Type=’C’) also named ‘excel_user’ (Fmtname).
So how do I get them into SAS from Excel? Once again, the SAS/ACCESS Excel libname statement is helpful here. First, we assign a libref ‘wb’ to the workbook holding the format ranges, and another libref ‘sasprogs’ which will be used to store the format catalog:
libname wb Excel "&path.\formats.xls" ver=2002 ; libname sasprogs "&path" ;
Next we need to get a list of all the ranges that we’re interested in here. In this workbook the only named ranges are the ones containing the formats. Any other names that the libname engine detects will be the names of worksheets, which will contain a ‘$’ character. So, we simply exclude these from the query against the dictionary.tables table:
proc sql; create table tmp as select memname from dictionary.tables where libname='WB' and index(memname, '$') = 0 ; quit;
So now the table ‘tmp’ holds a list of all the format range names in the workbook. Now we need to use this table to guide SAS in building those formats. What we need to do is to submit a proc format statement for every one of those names. Like so:
%macro load_fmt(name) ; proc format library=sasprogs.sasfmts cntlin=wb.&name ; %mend load_fmt;
Now we simply need to loop through the set of names to load each of the formats into the sasprogs.sasfmts catalog:
data _null_; set tmp; call execute('%load_fmt('||memname||')') ; run;
All that’s left to do now is a little tidying up:
/*Close the file*/ libname wb clear ; /*Inspect format contents*/ proc format library=sasprogs.sasfmts fmtlib cntlout=sasprogs.sasfmt_data; run; /*Add them into the search path*/ options fmtsearch=(library sasfmts);
And we’re done – all the formats are now loaded and available in the SAS session. Now if there are any changes, or a new format needs to be created, just add it into the file, save it and re-run this script. Sorted!