As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Macro VarList

From sasCommunity
Jump to: navigation, search

My thanks to SAS(R) trainer Jim Simon for providing this working code in his SGF.2013 preconference seminar.

My purpose here to is to show code polishing and optimization.

Macro varlist

 /* name varlist.sas
description: read list of variables of data set
             option: type in C,N returns vars of only that type
    purpose: illustrates use of SCL functions
source: SGF.2013 pre-conference seminar
        Advanced Macro Tips and Techniques
        by Jim Simon
usage:
%put %varlist(sashelp.class,C);
%put %varlist(sashelp.class,N);
%put %varlist(sashelp.class  );
***/
%macro varlist(dsn,type);
%let type = %upcase(&type);
%local dsid i;
%let dsid = %sysfunc(open(&dsn));
%if not &dsid %then %do;
    %put ERROR: cannot open data set: &dsn .;
    %return;
    %end;
%if   &type eq N %then
      %do I = 1 %to %sysfunc(attrn(&dsid,nvars));
        %if %sysfunc(vartype(&dsid,&I)) eq N %then
            %sysfunc(varname(&dsid,&I));
        %end;
%else %if &type eq C %then
      %do I = 1 %to %sysfunc(attrn(&dsid,nvars));
          %if %sysfunc(vartype(&dsid,&I)) eq C %then
              %sysfunc(varname(&dsid,&I));
          %end;
%else %do I = 1 %to %sysfunc(attrn(&dsid,nvars));
      %sysfunc(varname(&dsid,&I))
      %end;
%let dsid = %sysfunc(close(&dsid));
%mend varlist;
*name: varlist-test.sas;
%put %varlist(sashelp.class,C);
%put %varlist(sashelp.class,N);
%put %varlist(sashelp.class  );

Log:

1          %put %varlist(sashelp.class,C);
Name               Sex
2          %put %varlist(sashelp.class,N);
Age             Height             Weight
3          %put %varlist(sashelp.class  );
Name       Sex       Age       Height       Weight

Commentary:

  1. three tests of each expected value of parameter type
  2. after each test same loop: %do I = 1 %to ...nvars;
  3. same value is returned: ...varname, according to vartype

Macro varlistL

Polishing: make separate lists of varnames to return.

 /* name varlistL.sas
description: read list of variables of data set
             option: type in C,N returns vars of only that type
    purpose: illustrates use of SCL functions
predecessor: SGF.2013 pre-conference seminar
             varlist
usage:
%put %varlistL(data=sashelp.class,type=C);
%put %varlistL(data=sashelp.class,type=N);
%put %varlistL(data=sashelp.class  );
***/
%macro varlistL
 (data=
 ,type=
 ,testing=1
 );
%*standardize type to match output from vartype function
%let type = %upcase(&type);
%local dsid i varname;
%*note: 3 lists only one of which is assigned;
%local List ListC ListN;
%let dsid = %sysfunc(open(&data));
%if not &dsid %then %do;
    %put ERROR: cannot open data set: &Data .;
    %return;
    %end;
%* consolidation: one loop
%do I = 1 %to %sysfunc(attrn(&dsid,nvars));
    %* consolidation: one function call;
    %let varname = %sysfunc(varname(&dsid,&I));
    %* make list of all vars regardless of type;
    %let List = &List &varname;
    %* consolidation: reduce two tests of type and vartype to one;
    %if %sysfunc(vartype(&dsid,&I)) eq &type %then
        %let List&type = &&List&type &varname;
    %end;
    %if &testing %then %put _local_;
%* return correct list: either List ListC or ListN;
&&List&type
%* todo: can avoid double ampersands?;
%let dsid = %sysfunc(close(&dsid));
%mend varlistL;

Log:

5          %put %varlistL(data=sashelp.class,type=C);
VARLISTL DATA sashelp.class
VARLISTL LIST Name Sex Age Height Weight
VARLISTL LISTC Name Sex
Name Sex
6          %put %varlistL(data=sashelp.class,type=N);
VARLISTL DATA sashelp.class
VARLISTL LIST Name Sex Age Height Weight
VARLISTL LISTN Age Height Weight
Age Height Weight
7          %put %varlistL(data=sashelp.class);
VARLISTL DATA sashelp.class
VARLISTL LIST Name Sex Age Height Weight
VARLISTL LISTN 
Name Sex Age Height Weight

Macro VarListX

Polishing: use original idea of returning value with loop: no need for separate list.

 /* name varlistX.sas
description: read list of variables of data set
             option: type in C,N returns vars of only that type
    purpose: illustrates use of SCL functions
predecessor: SGF.2013 pre-conference seminar
             varlist
usage:
%put %varlistX(data=sashelp.class,type=C);
%put %varlistX(data=sashelp.class,type=N);
%put %varlistX(data=sashelp.class  );
***/
%macro varlistX
 (data=
 ,type=
 );
%let type = %upcase(&type);
%local dsid i varname;
%let dsid = %sysfunc(open(&data));
%if not &dsid %then %do;
    %put ERROR: cannot open data set: &Data .;
    %return;
    %end;
%do I = 1 %to %sysfunc(attrn(&dsid,nvars));
    %let varname = %sysfunc(varname(&dsid,&I));
    %* return to original idea of write within loop;
    %if %sysfunc(vartype(&dsid,&I)) eq &type %then &varname;
    %else %if &type eq %then &varname;
    %* note: test of type eq <blank>;
    %end;
%let dsid = %sysfunc(close(&dsid));
%mend varlistX;

Commentary:

  1. reduced three loops: %do i = 1 to ...nvars;
    1. either of which was called only per value of parameter type, to one
  2. added assignment of macro variable varname from one function call to varname
  3. consolidated two tests of type eq C|N to one

Summary: reduced 13 lines of code to five, plus two comments.

--Ronald_J._Fehd macro.maven == the radical programmer