Today I would also use DOSUBL for this. But before there was DOSUBL, I hit this problem. I see it as a bug that that VARNAME function does not honor the KEEP/DROP option. I've been told in that in SCL, it does honor KEEP/DROP.
Luckly, Søren Lassen posted some solutions to SAS-L. Basic approach is to open the dataset twice, once with the keep/drop option, and once without. With that, you can loop over the list of variables without the keep/drop applied, and use the VARNUM function to test if the variable exists in the dataset with the keep/drop applied. Code like:
%macro ListVars(data);
/***
Based on %VarList macro developed by Søren Lassen
Posted to SAS-L December 2010 and May 4, 2015
Macro is complicated by fact that the varname function does not honor keep/drop option.
Therefore need workaround to prevent er ror msg if user specifies keep/drop.
The work around is to iterate over list of variables in dataset
without keep/drop applied, and check if each variable is in the dataset
with keep/drop applied.
***/
%local
dsid /*id of &data, with any keep/drop options*/
dsid2 /*id of &data, without any keep/drop options*/
i
var /*name of ith variable in &data*/
return
rc
;
%*If &data had a rename option, macro would not return the renamed variables;
%*So user is not allowed to use rename option.;
%if %sysfunc(find(&data,rename,i)) %then %do;
%put ER%str()ROR: (%nrstr(%%)&sysmacroname) cannot include rename option on dataset.;
%goto mexit;
%end;
%let dsid=%sysfunc(open(&data)); /*dataset with any keep/drop options*/
%let dsid2=%sysfunc(open(%scan(&data,1,%str(%( )))); /*dataset without keep/drop options*/
%do i=1 %to %sysfunc(attrn(&dsid2,nvars));
%let var=%sysfunc(varname(&dsid2,&i));
%if (%sysfunc(varnum(&dsid,&var))) %then
%do;
%if %superq(return) = %str() %then %let return=&var;
%else %let return=&return &var;
%end;
%end;
%let rc=%sysfunc(close(&dsid));
%let rc=%sysfunc(close(&dsid2));
&return
%mexit:
%mend ListVars;
%put %listvars(sashelp.class) ;
%put %listvars(sashelp.class(keep=_numeric_)) ;
%put %listvars(sashelp.class(drop=_character_)) ;
... View more