Routine CxInclude

From sasCommunity
Jump to: navigation, search

Despite inclusion in the category Macros.by.Ron.Fehd, this program is a parameterized %include.

Call_Execute_Parameterized_Include

On a weekly basis I use this routine more than any other single program in my toolbox.

Programs

CxInclud.sas

 /*       Name: CxInclud.sas   Ronald J. Fehd
      location: <UNC>\SAS-site\includes
----------------------------------------------------------------------
Summary       : description  : call execute a parameterized %include
                                    using control data set rows
                                    as set of parameters
                purpose      : provide generic method to call programs
                ------------------------------------------------------
Contexts      : program group: statement generator
                program  type: routine
                SAS      type: parameterized include procedure
                uses routines: n/a
----------------------------------------------------------------------
Specifications: input  : macro variables
                         CxData   : data set
                         CxInclude: program(s) to %include
                process: for each row in CxData
                             for each variable,
                                 Stmnt:=%let var = value;
                                 submit Stmnt
                             Stmnt:= %Include &CxIncludes.;
                             submit Stmnt
                output : from called program(s)
----------------------------------------------------------------------
Usage Example:
autoexec:
filename Project  '.'; *'C:\SAS-site\include-tests';
filename SiteIncl 'C:\SAS-site\includes';
 
- - -  ...\SAS-site\include-tests\TestInclude.sas - - -
title2 'TestInclude';
%Put _global_;
- - -  CxInclude-test-sashelp-class-sort.sas - - -
*name: ...\SAS-site\include-tests\CxInclude-test-sashelp-class-sort.sas;
PROC Sort data = sashelp.Class
         (keep = Sex)
                 nodupkey
          out  = Work.Sort_Class_Sex;
          by     Sex;
%Let CxData    = Work.Sort_Class_Sex;*(drop | keep | rename | where);
%Let CxInclude = Project(TestInclude);
%Include SiteIncl(CxInclud);
 
NOTE: CALL EXECUTE generated line.
1         +  %let Sex = F;
2         +  %Include SiteIncl(TestInclude);
----------------------------------------
history: developed during 2008 while writing:
http://www.sascommunity.org/wiki/SmryEachVar_A_Data_Review_Suite
----------------------------------------
word count: UltraEdit information: <Alt> <Search> <Word Count>
               DateTime: 6/23/2012 5:02:30 PM
                  Words:  477
                  Lines:  133
Characters(no   spaces): 3632
Characters(with spaces): 5195
**** ........................ */
**** description: allocate testing variable;
**** purpose    : centralize allocation for use by both data steps;
%Let CxTesting = %eval(    %sysfunc(getoption(mprint )) eq MPRINT
                       and %sysfunc(getoption(source2)) eq SOURCE2);
 
**** description: read data structure;
**** purpose    : calculate max length of _CxStmnt;
PROC Contents data = &CxData.
                     noprint
              out  = Work._CxContents
             (keep = Name Type Length);
 
DATA _Null_;
     retain _MaxLength %length(*Include_&CxIncludes._);
do   until(EndoFile);
     set Work._CxContents end = EndoFile;
     ** Type in(1=N,2=C)     hex16;
     if Type eq 1 then Length = 16;
     _MaxLength = max(_MaxLength,sum(%length(*let_),length(Name)
                                    ,%length(_=_)  ,Length));
     end;
call symputx('CxLengthStmnt',_MaxLength);
if   &CxTesting. then call execute(
     '%nrstr(%put note: CxInclude CxLengthStmnt:&CxLengthStmnt.;)');
stop;
run;
PROC Delete data = Work._CxContents;
 
**** description: main: read &CxData.;
**** purpose    : read control data set, assemble statement, submit;
DATA _Null_;
     if 0   then set &CxData.;
     attrib _CxStmnt   length = $ &CxLengthStmnt.
            _CxName    length = $ 32
            _CxI       length =    4;
     array  _CxVarC(*) _character_;
     array  _CxVarN(*) _numeric_;
 
do until(EndoFile);
   set &CxData. end = EndoFile;
   do _CxI = 1 to dim(_CxVarC) -2;
      _CxName = vname(_CxVarC(_CxI));
      ** make statement:   *let     Name  =  value;
      _CxStmnt = catx(' ','%let',_CxName,'=',_CxVarC(_CxI));
      link CxStmnt;
      end;
   do _CxI = 1 to     dim(_CxVarN) -1;
      _CxName  =    vname(_CxVarN(_CxI));
      _CxStmnt = catx(' ','%let',_CxName,'='
                     ,put(_CxVarN(_CxI),hex16.));
      link CxStmnt;
      end;
   _CxStmnt = "%Include &CxIncludes.";
   link CxStmnt;
   end;
 
** Symbol-Delete global macro variables allocated here;
do _CxI = 1 to  dim(_CxVarC) -2;
   _CxName  = vname(_CxVarC(_CxI));
   _CxStmnt = catx(' ','%symdel',_CxName);
   link CxStmnt;
   end;
do _CxI = 1 to  dim(_CxVarN) -1;
   _CxName  = vname(_CxVarN(_CxI));
   _CxStmnt = catx(' ','%symdel',_CxName);
   link CxStmnt;
   end;
if   not &CxTesting. then
     call execute('%nrstr(%symdel CxLengthStmnt CxTesting;)');
else call execute('%nrstr(%Put _global_;)');
stop;
CxStmnt: if &CxTesting. then putlog  _CxStmnt=;
         call execute(cats('%nrstr(',_CxStmnt,';)'));
         return;
run;
%Put Note: CxInclude ending CxData: &CxData. CxIncludes: &CxIncludes.;

CxInclude tests

This is the one-line does-nothing-really test program for the demo.

%put note: TestInclude.sas;
*name: ...\SAS-site-include-tests\CxInclude-test-sashelp-contents.sas;
PROC Contents data   = sashelp._all_
                       noprint
              out    = Work.Contents_sashelp_all_names
             (keep   = Libname Memname Name Type Length);
 
%Let CxData      = Work.Contents_sashelp_all_names;
%Let CxIncludes  = Project(TestInclude);
%Include SiteIncl(CxInclud);

Log:

NOTE: The data set WORK.CONTENTS_SASHELP_ALL_NAMES has 948 observations and 5 variables.

....

NOTE: CALL EXECUTE generated line.
1         + %let LIBNAME = SASHELP;
2         + %let MEMNAME = ADOMSG;
3         + %let NAME = LEVEL;
4         + %let TYPE = 4000000000000000;
5         + %let LENGTH = 3FF0000000000000;
6         + %Include Project(TestInclude);
note: TestInclude.sas
7         + %let LIBNAME = SASHELP;
8         + %let MEMNAME = ADOMSG;
9         + %let NAME = LINENO;
10        + %let TYPE = 3FF0000000000000;
11        + %let LENGTH = 4014000000000000;
12        + %Include Project(TestInclude);
note: TestInclude.sas

....

note: TestInclude.sas
5679      + %let LIBNAME = SASHELP;
5680      + %let MEMNAME = _CMPIDX_;
5681      + %let NAME = Timestamp;
5682      + %let TYPE = 3FF0000000000000;
5683      + %let LENGTH = 4020000000000000;
5684      + %Include Project(TestInclude);
note: TestInclude.sas
5685      + %let LIBNAME = SASHELP;
5686      + %let MEMNAME = _CMPIDX_;
5687      + %let NAME = Type;
5688      + %let TYPE = 4000000000000000;
5689      + %let LENGTH = 4020000000000000;
5690      + %Include Project(TestInclude);
note: TestInclude.sas
5691      + %symdel LIBNAME ;
5692      + %symdel MEMNAME ;
5693      + %symdel NAME ;
5694      + %symdel TYPE ;
5695      + %symdel LENGTH ;
5696      + %symdel CxLengthStmnt CxTesting;
Note: CxInclude ending CxData: Work.Contents_sashelp_all_names CxIncludes: Project(TestInclude)

How to convert those hex values

*name: proc-print-data-name-value;
%Put _global_;
%Let TpDsid    = %sysfunc(open    (&Libref..&Memname. ));
%Let TpVarNum  = %sysfunc(varnum  (&TpDsid.,&Name.    ));
%Let TpVarType = %sysfunc(vartype (&TpDsid.,&TpVarNum.));
%Let TpLabel   = %sysfunc(varLabel(&TpDsid.,&TpVarNum.));
%Let TpRc      = %sysfunc(close   (&TpDsid.           ));
 
Proc Print data   = &Libref..&Memname.
          (where  = (&Name eq
          %sysfunc(ifc(&TpVarType. eq C,"&Value."
                                       , &Value. )) ));
           Title2 "data    : &Libref..&Memname.";
           Title3 "subset  : &Name eq &Value.";
           Title4 "freq    : count: &Count. ";
           Title5 " percent: &Percent. ";
           title6 Count   real: %sysfunc(inputn(&Count.,hex16.));
           title7 Percent real: %sysfunc(inputn(&Percent.,hex16.));
           title8 Percent real: %sysfunc(round(%sysfunc
                                        (inputn(&Percent.,hex16.)),.1));
           Title9 "vartype : &Name is &TpVarType.";
           Title10 "varlabel: %left(&TpLabel.)";
%symdel TpDsid TpLabel TpRc TpVarNum TpVarType;
run;
Title2 CallExecInclude-Demo-ProcFreq.sas;
**options source2;
%Let Libref  = sashelp;
%Let Memname = Class;
%Let Name    = Sex;%*char;
%*Let Name    = Age;%*num;
 
%*Let Memname = Shoes;
%*Let Name    = Region;
%**et Name    = Product;*knot works: contains single quotes;
%*Let Name    = Subsidiary;
%*Let Name    = Stores;
 
%*Let Memname = CitiMon;
%**et Name    = FspCap;
     /* label = S&P'S COMMON STOCK PRICE INDEX: CAPITAL 'CLOSE S-QUOTE;
     /* WARNING: Apparent symbolic reference P not resolved;*/
 
PROC Freq data =   &Libref..&Memname.;
          tables   &Name.
                 / %* noprint %**;
             out = Work.ListValues
         (rename = (&Name. = Value));
 
Proc SQL; describe table Work.ListValues;
          quit;
          %symdel SqlObs SqLoops;
 
%Let CxData       = Work.ListValues;
%Let CxIncludes   = Project(proc-print-data-name-value)/source2;
%Include SiteIncl(CxInclud);

Log:

NOTE: SQL table WORK.LISTVALUES was created like:

create table WORK.LISTVALUES( label='Frequency Counts and Percentages' bufsize=4096 )
  (
   Value char(1),
   COUNT num label='Frequency Count',
   PERCENT num label='Percent of Total Frequency'
  );

....

1         + %let Value = F;
2         + %let COUNT = 4022000000000000;
3         + %let PERCENT = 4047AF286BCA1AF3;
4         + %Include Project(proc-print-data-name-value)/source2;
NOTE: %INCLUDE (level 2) file PROJECT(proc-print-data-name-value) is file 
      <UNC>\SAS-site\sas-include-tests\proc-print-data-name-value.sas.
163       +*name: proc-print-data-name-value;
164       +%Put _global_;
GLOBAL CXTESTING 0
GLOBAL VALUE F
GLOBAL PERCENT 4047AF286BCA1AF3
GLOBAL MEMNAME Class
GLOBAL COUNT 4022000000000000
GLOBAL CXDATA Work.ListValues
GLOBAL CXINCLUDES Project(proc-print-data-name-value)/source2
GLOBAL NAME Sex
GLOBAL CXLENGTHSTMNT 53
GLOBAL LIBREF sashelp

165       +%Let TpDsid    = %sysfunc(open    (&Libref..&Memname. ));
166       +%Let TpVarNum  = %sysfunc(varnum  (&TpDsid.,&Name.    ));
167       +%Let TpVarType = %sysfunc(vartype (&TpDsid.,&TpVarNum.));
168       +%Let TpLabel   = %sysfunc(varLabel(&TpDsid.,&TpVarNum.));
169       +%Let TpRc      = %sysfunc(close   (&TpDsid.           ));
170       +
171       +Proc Print data   = &Libref..&Memname.
172       +          (where  = (&Name eq
173       +          %sysfunc(ifc(&TpVarType. eq C,"&Value."
174       +                                       , &Value. )) ));
175       +           Title2 "data    : &Libref..&Memname.";
176       +           Title3 "subset  : &Name eq &Value.";
177       +           Title4 "freq    : count: &Count.";
178       +           Title5 " percent: &Percent.";
179       +*           Title6 " rounded: %left(%sysfunc(putn(&Percent.,6.2)))";
180       +           Title7 "vartype : &Name is &TpVarType.";
181       +           Title8 "varlabel: %left(&TpLabel.)";
182       +%symdel TpDsid TpLabel TpRc TpVarNum TpVarType;
183       +run;

NOTE: There were 9 observations read from the data set SASHELP.CLASS.
      WHERE Sex='F';
NOTE: The PROCEDURE PRINT printed page 2.

Listing:

data    : sashelp.Class
subset  : Sex eq F
freq    : count: 4022000000000000 
 percent: 4047AF286BCA1AF3 
Count   real: 9
Percent real: 47.3684210526315
Percent real: 47.4
vartype : Sex is C
varlabel: 

Obs    Name       Sex    Age    Height    Weight

  2    Alice       F      13     56.5       84.0
  3    Barbara     F      13     65.3       98.0
....


References

--Ronald_J._Fehd macro.maven == the radical programmer 07:57, 20 June 2012 (EDT)