/*
/ Program : lstattrib.sas
/ Version : 1.0
/ Author : Roland Rashleigh-Berry
/ Date : 24-Oct-2009
/ Purpose : Lists the variable attributes of the specified dataset in the
/ form of a LENGTH statement and ATTRIB statement that can be used
/ in sas code.
/ SubMacros : none
/ Notes : The information is written to the log as syntactically correct sas
/ code so you can copy and paste it into your sas program to help
/ you create a new dataset with the same attributes as the original
/ dataset. An actual example of what is written to the log is shown
/ below in the usage notes section.
/
/ This macro is intended for interactive use as part of a data
/ pooling exercise, to generate correct LENGTH and ATTRIB statements
/ for the final pooled datasets. This macro could be run against
/ correct template datasets or datasets known to be correct so that
/ the LENGTH and ATTRIB statements could be stored in a central
/ location where programmers can copy and paste the code into their
/ own data pooling programs. The aim is to ensure that the final
/ datasets have all the correct variables and attributes.
/
/ See also the %dsattrib macro.
/
/ Usage : %lstattrib(sasuser.demog)
/
/ ****** Attributes obtained from sasuser.demog ******;
/ DATA xxxxxx;
/ *- The order of the variables in the following LENGTH statement matches -;
/ *- the variable order in the original dataset so do not change. -;
/ LENGTH dob 8 trtcd 8 sexcd 8 racecd 8 weight 8 height 8 patno 8 invid 8
/ sitecd 8 fascd 8 age 8
/ ;
/
/ *- The SET or MERGE statement for the input dataset(s) should be -;
/ *- placed after the LENGTH statement and before the attributes. -;
/ SET yyyyyy;
/
/ *- Cancel existing formats and informats in the input dataset(s) -;
/ FORMAT _all_ ;
/ INFORMAT _all_ ;
/
/ *- Assign output variable attributes -;
/ ATTRIB
/ age format=3. label="AGE (YEARS)"
/ dob format=DATE9. informat=DATE7. label="DATE OF BIRTH"
/ fascd format=NY. informat=COMMA13. label="FULL ANALYSIS SET (N/Y)"
/ height format=5.1 informat=COMMA13. label="HEIGHT (CM)"
/ invid informat=COMMA13. label="INVESTIGATOR ID"
/ patno informat=COMMA13. label="PATIENT NUMBER"
/ racecd format=RACECD. informat=COMMA13. label="RACE CODE"
/ sexcd format=SEXCD. informat=COMMA13. label="GENDER CODE"
/ sitecd informat=COMMA13. label="SITE CODE"
/ trtcd format=TRTCD. informat=COMMA13. label="TREATMENT REGIMEN"
/ weight format=5.1 informat=COMMA13. label="WEIGHT (KG)"
/ ;
/
/ *- KEEP statement for the variables listed above -;
/ KEEP age dob fascd height invid patno racecd sexcd sitecd trtcd weight
/ ;
/ RUN;
/
/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------
/ ds (pos) (unquoted) One-level or two-level dataset name
/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------
/
/===============================================================================
/ This is public domain software. No guarantee as to suitability or accuracy is
/ given or implied. User uses this code entirely at their own risk.
/=============================================================================*/
%put MACRO CALLED: lstattrib v1.0;
%macro lstattrib(ds);
%local lib dsname dslabel maxname maxformat maxinformat error;
%let error=0;
%if not %sysfunc(exist(&ds)) %then %do;
%let error=1;
%put ERROR: (lstattrib) Specified dataset &ds does not exist;
%end;
%if &error %then %goto error;
%if not %length(%scan(&ds,2,.)) %then %do;
%let lib=%sysfunc(getoption(user));
%if not %length(&lib) %then %let lib=work;
%let lib=%upcase(&lib);
%let dsname=%upcase(&ds);
%end;
%else %do;
%let lib=%upcase(%scan(&ds,1,.));
%let dsname=%upcase(%scan(&ds,2,.));
%end;
proc sql noprint;
select memlabel into :dslabel separated by " "
from dictionary.tables
where libname="&lib" and memname="&dsname";
create table _attr as
select name, length, type, format, informat, label, varnum
from dictionary.columns
where libname="&lib" and memname="&dsname"
order by name;
create table _lens as
select name, length, type, varnum
from _attr
order by varnum;
select max(length(name)), max(length(format)), max(length(informat))
into :maxname, :maxformat, :maxinformat separated by " "
from _attr;
quit;
data _null_;
length _str _str2 $ 200 _allvars $ 4000;
retain maxname &maxname maxformat &maxformat maxinformat &maxinformat
_allvars;
file log;
if _n_=1 then do;
if maxformat=1 then maxformat=-8;
if maxinformat=1 then maxinformat=-10;
put @1 "****** Attributes obtained from &ds ******;";
%if %length(&dslabel) %then %do;
_str='DATA xxxxxx(label="'||"&dslabel"||'");';
%end;
%else %do;
_str='DATA xxxxxx;';
%end;
put @1 _str;
put @3 "*- The order of the variables in the following LENGTH statement matches -;";
put @3 "*- the variable order in the original dataset so do not change. -;";
put @3 "LENGTH " @;
__i=1;
_str=" ";
do until(__i>_nobs);
do until(length(_str)>60 or __i>_nobs);
set _lens nobs=_nobs point=__i;
if type EQ "char" then _str2=trim(name)||" $ "||left(put(length,5.));
else _str2=trim(name)||" "||left(put(length,5.));
_str=trim(_str)||" "||_str2;
__i=__i+1;
end;
put @10 _str;
_str=" ";
end;
put @10 ";";
put;
put @3 "*- The SET or MERGE statement for the input dataset(s) should be -;";
put @3 "*- placed after the LENGTH statement and before the attributes. -;";
put @3 "SET yyyyyy;";
put;
put @3 "*- Cancel existing formats and informats in the input dataset(s) -;";
put @3 "FORMAT _all_ ;";
put @3 "INFORMAT _all_ ;";
put;
put @3 "*- Assign output variable attributes -;";
put @3 "ATTRIB" ;
end; *- end of _n_=1 -;
set _attr end=last;
_allvars=trim(_allvars)||" "||name;
if type="char" then _str="$"||trim(left(put(length,6.)));
else _str=trim(left(put(length,6.)));
put @5 name @;
if format ne " " then put @(maxname+6) "format=" format @;
if informat ne " " then put @(maxname+maxformat+14) "informat=" informat @;
_str='"'||trim(tranwrd(label,'"','""'))||'"';
put @(maxname+maxformat+maxinformat+24) "label=" _str @;
put ;
if last then do;
put @5 ";" ;
put;
put @3 "*- KEEP statement for the variables listed above -;";
put @3 "KEEP " @;
scanidx=1;
do until(scan(_allvars,scanidx," ")=" ");
_str=" ";
do until(scan(_allvars,scanidx," ")=" " or length(_str)>65);
_str=trim(_str)||" "||scan(_allvars,scanidx," ");
scanidx=scanidx+1;
end;
put @8 _str;
end;
put @8 ";" ;
put @1 "RUN;";
end;
run;
proc datasets nolist;
delete _attr _lens;
run;
quit;
%goto skip;
%error:
%put ERROR: (lstattrib) Leaving macro due to error(s) listed;
%skip:
%mend;