Hi:
What you describe is fairly standard macro conditional logic. There is a difference between data step logic and macro conditional logic, in both syntax and "timing".
Since SAS looks at the SET/KEEP statement in order to build the program data vector for your program (and be sure it has the right variable names) -- even though you have your set statement inside data step conditional logic, SAS still sees both of your SET/KEEP statements at compile time. So the fact that you're getting an error and incorrect or no output means that you have to build your set statements conditionally -- and this points to using SAS Macro conditional logic, not data step logic. If you remove the KEEP= option from your code, you may avoid getting error messages, and you may in fact get output, but it's really better in this instance to move to the use of macro logic instead of data step logic.
In order to turn this into a correct macro program that uses conditional logic you generally should follow these steps:
1) have a working SAS program (or in your case, have 2 working SAS programs).
once both programs are working correctly and producing the correct output, look at the programs carefully and decide which parts are "conditional" and which parts can stay the same for every invocation.
2) decide on the names of your macro variables and, where possible, test the programs from #1 using hard-coded macro variables with %LET statements
3) convert the conditional portions of the programs (either whole steps or partial steps or partial pieces of code) to be inside a macro program definition( %MACRO/%MEND ) -- which will DEFINE the statements or code snippets that you want to send to the compiler when the macro is invoked and the macro statements are resolved.
4) test the new macro program and the macro conditional logic in that macro program by invoking the macro program defined in #3. The name of the macro program is what came after the %MACRO keyword in #3.
Here's an example of what I mean.
1) Here are my 2 working SAS programs:
[pre]
** step #1;
data newfile;
set sashelp.class(keep=name sex age height);
if sex = "M";
run;
proc print data=newfile;
title 'Newfile from sashelp.class';
run;
data newfile2;
set sashelp.shoes(keep=region product sales);
if region = "Canada";
run;
proc print data=newfile2;
title 'Newfile2 from sashelp.shoes';
run;
[/pre]
And I decide that I am going to call my macro variables &WANT and &KEEPLIST.
So, my #2 version (without the PROC PRINTS) of the program looks like this:
[pre]
%let want = M;
%let keeplist = "name sex age height";
data newfile;
set sashelp.class(keep=&keeplist);
if sex = "&want";
run;
** proc print step;
%let want = Canada;
%let keeplist = "region product sales";
data newfile2;
set sashelp.shoes(keep=&keeplist);
if region = "&want";
run;
** proc print step;
[/pre]
I also decide that my macro program will just generate the SET statement and the IF statement that I need to select the records.
My macro definition looks like this and at this point I want to add some error processing to the macro definition:
[pre]
** step #3 DEFINE the macro program;
%macro choose(want=, keeplist=);
%If &want=M %then %do;
set sashelp.class(keep=&keeplist);
if sex = "&want";
%end;
%else %if &want = Canada %then %do;
set sashelp.shoes(keep=&keeplist);
if region = "&want";
%end;
%else %do;
data _null_;
file print;
title '3) Error Message';
put '----- ----- ----- ----- -----';
put "You did not choose M or Canada as the value you wanted";
put "You chose WANT=&WANT and KEEPLIST=&KEEPLIST ";
put "Please reinvoke the macro with the correct choices";
put '----- ----- ----- ----- -----';
run;
%end;
%mend choose;
[/pre]
In #3, I DEFINED the macro program CHOOSE. I also defined it to have some KEYWORD parameters WANT and KEEPLIST. To invoke this program, I will use the macro trigger % in front of the macro program name. So in order to test the macro program the invocation will be one of these 2 possibilities:
[pre]
%CHOOSE(want=M,keeplist=name age sex height);
%CHOOSE(want=Canada,keeplist=region product sales);
[/pre]
But I also need to invoke the macro for all conditions, including the error condition, and examine the output. And, since my macro program does NOT generate a full data step, but only generates code snippets, I have to invoke the macro in the right way (inside a DATA step program) as shown in #4 below:
[pre]
** step #4 test the macro defined above;
ods listing;
** 1) test want=M should use sashelp.class;
data newfile;
%choose(want=M, keeplist=name sex age height);
run;
proc print data=newfile;
title '1) Use Macro first time';
run;
** 2) test want=Canada should use sashelp.shoes;
data newfile2;
%choose(want=Canada, keeplist=region product sales);
run;
proc print data=newfile2;
title '2) Use Macro second time';
run;
** 3) test macro with value not allowed;
data newfile3;
%choose(want=Pacific, keeplist=region subsidiary sales);
run;
proc print data=newfile3;
title '3) Use Macro third time';
run;
[/pre]
The Macro definition program is like a typewriter. You pass parameters to the typewriter when you invoke the macro program and the macro program automatically types the right SET and IF statement -- before the statements are compiled, so the compiler NEVER sees the wrong statement.
(Note how inside macro conditional logic %IF/%DO, I do not use any quotes when I test the values for &WANT -- this is because the macro processor knows that it's just dealing with text strings -- so inside the macro conditional logic, quotes are unnecessary. BUT, inside the data step program, where I want the resolved value of &WANT to be compared to a data set variable, I have to use quotes appropriately in the data step logic.)
So your question was -- Is it possible to use a DO statement when selecting my data sets-- the answer is yes -- but there are multiple ways of doing it. IF you want to stick with DATA step logic, there IS a way to make it work, but I don't normally recommend using DATA step logic to generate code snippets. As my dad used to say, in for a dime, in for a dollar -- which to me means that since you are already using macro variables (in for a dime) and IF you want to conditionally compile and execute code snippets, then you may as well use macro conditional logic to generate your code snippets (in for a dollar).
This is my "never fail" method for developing macros and implementing conditional logic.
cynthia