Routine CxMacro

From sasCommunity
Jump to: navigation, search

Author: Ronald_J._Fehd

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

Call_Execute_Parameterized_Include

This is a successor to the Routine_CxInclude.

Programs

CxMacro.sas

 /*       Name: CxMacro.sas    Ronald J. Fehd
      location: <UNC>\SAS-site\includes
-----------------------------------------------------------------------
Summary       : description  : call execute a macro
                                    using control data set rows
                                    as set of parameters
                purpose      : provide generic method to call macro
                -------------------------------------------------------
Contexts      : program group: statement generator
                program  type: routine
                SAS      type: parameterized include procedure
                uses routines: n/a
-----------------------------------------------------------------------
Specifications: input  : macro variables
                         CxData      : data set
                         CxMacroName : name of macro
                         CxMacroParms: parameters to pass to macro call
                process: for each row in CxData
                             Stmnt:= &CxMacroName.(<&CxMacroParms.,>
                         for each variable,
                             append to Stmnt: var = value,
                         replace ending comma with close paren
                         submit Stmnt
                output : from called macro
-----------------------------------------------------------------------
Usage Example:
autoexec:
filename Project  'C:\SAS-site\include-tests';
filename SiteIncl 'C:\SAS-site\includes';
filename SiteMacr 'C:\SAS-site\macros';
options  SASautos = (Project SiteMacr SASautos)
         mautosource;
 
%Macro TestMacro(Testing = 1)/parmbuff;
%put SysPbuff: &SysPbuff.;
run;
%mend;
 
*name: ...\SAS-site\include-tests\CxMacro-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 CxMacroName = TestMacro;
%Let CxMacroParms= ;*ex: data=sashelp.class,var=sex;
%Include SiteIncl(CxMacro);
 
NOTE: CALL EXECUTE generated line.
1         +  %TestMacro(Sex=F);
SysPbuff: (Sex=F)
note: CxMacro ending CxData: Work.Freq_Class_Sex CxMacroName: TestMacro
----------------------------------------
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:28:57 PM
                  Words:  496
                  Lines:  138
Characters(no   spaces): 3958
Characters(with spaces): 5509
**** ........................ */
**** 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);
%let CxTimeStart = %sysfunc(datetime(),hex16.);
 
**** description: setup: read data structure of &CxData.;
**** purpose    : calculate length of Stmnt;
PROC Contents data = &CxData.
                     noprint
              out  = Work._CxContents
             (keep = Name Type Length);
DATA _Null_;
     retain _MaxLength %length(*&CxMacroName.*&CxMacroParms.);
do   until(EndoFile);
     set Work._CxContents end = EndoFile;
     ** Type in(1=N,2=C)     hex16;
     if Type eq 1 then Length = 16;
     ** append ,name=value       ,        Name  = value;
     _MaxLength = sum(_MaxLength,1,length(Name),1,Length);
     end;
*** +1 for close paren;
_MaxLength = sum(_MaxLength,1);
call symputx('CxLengthStmnt',_MaxLength);
if   &CxTesting. then call execute(cats('%nrstr('
     ,'%Put note: CxMacro 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;
   ** initialize Stmnt:=  macro-name+open paren <+parameters,>;
   _CxStmnt = cats('%',"&CxMacroName.(");
   if %length(&CxMacroParms.) then
      _CxStmnt = cats(_CxStmnt,"&CxMacroParms.,");
 
   ** append: VarName = value comma;
   do _CxI = 1 to dim(_CxVarC) -2;
      _CxName  =vname(_CxVarC(_CxI));
      _CxStmnt = cats(_CxStmnt,_CxName,'=',_CxVarC(_CxI),',');
      end;
   do _CxI = 1 to dim(_CxVarN) -1;
      _CxName  =vname(_CxVarN(_CxI));
      _CxStmnt = cats(_CxStmnt,_CxName,'='
                     ,put(_CxVarN(_CxI),hex16.),',');
      end;
 
   * replace last comma with close paren;
   substr(_CxStmnt,length(_CxStmnt),1) = ')';
 
   if  &CxTesting. then putlog _CxStmnt=;
   call execute(cats('%nrstr(',_CxStmnt,';)'));
   end;
if not &CxTesting. then
     call execute('%nrstr(%symdel CxLengthStmnt CxTesting;)');
else call execute('%nrstr(%Put _global_;)');
stop;
run;
%let CxTimeEnd = %sysfunc(datetime(),hex16.);
%Put note: CxMacro used real time %sysfunc
           (putn(&CxTimeEnd.x-&CxTimeStart.x,time12.3));
%symdel           CxTimeEnd    CxTimeStart;
%Put note: CxMacro ending CxData: &CxData. CxMacroName: &CxMacroName.;

CxMacro tests

*name: <UNC>\SAS-site\include-tests\CxMacro-test-freq.sas;
options mprint source2;*testing:= on;
 
PROC Freq data   = sashelp.Class;
          tables   Sex
                 / noprint
             out = Work.Freq_Class_Sex;
 
%Let CxData      = Work.Freq_Class_Sex;
%Let CxMacroName  = Put note: testing;
%Let CxMacroParms  =;*note: no ending comma;
%Include SiteIncl(CxMacro);

Log:

NOTE: CALL EXECUTE generated line.
1         + %Put note: CxMacro CxLengthStmnt: &CxLengthStmnt.;
note: CxMacro CxLengthStmnt: 74

....

NOTE: CALL EXECUTE generated line.
1         + %Put note: testing(Sex=F,COUNT=4022000000000000,PERCENT=4047AF286BCA1AF3);
note: testing(Sex=F,COUNT=4022000000000000,PERCENT=4047AF286BCA1AF3)
2         + %Put note: testing(Sex=M,COUNT=4024000000000000,PERCENT=404A50D79435E50E);
note: testing(Sex=M,COUNT=4024000000000000,PERCENT=404A50D79435E50E)
3         + %Put _global_;
GLOBAL CXTESTING 1
GLOBAL CXDATA Work.Freq_Class_Sex
GLOBAL CXMACRONAME Put note: testing
GLOBAL CXTIMESTART 41D8AD7D33CDF3B6
GLOBAL CXMACROPARMS
GLOBAL CXLENGTHSTMNT 74
146       +%let CxTimeEnd = %sysfunc(datetime(),hex16.);
147       +%Put note: CxMacro used real time %sysfunc
148       +           (putn(&CxTimeEnd.x-&CxTimeStart.x,time12.3));
note: CxMacro used real time  0:00:00.078
149       +%symdel           CxTimeEnd    CxTimeStart;
150       +%Put note: CxMacro ending CxData: &CxData. CxMacroName: &CxMacroName.;
note: CxMacro ending CxData: Work.Freq_Class_Sex CxMacroName: Put note: testing

How to convert those hex values

See testing program in Routine_CxInclude#How_to_convert_those_hex_values

References

--[[Ronald_J._Fehd]] macro.maven == the radical programmer 08:01, 20 June 2012 (EDT)