Hello
Here is my code.
What is wrong with my code.
I want to perform data step statements based on condition on macro var (The macro var is defined by user and get value 1 or 0)
Data have;
input custID X;
cards;
1 10
3 30
;
Run;
%let ind_OOT=1;
/*%let ind_OOT=0;*/
%macro My_Macro;
%IF &ind_OOT.=1 %THEN %DO;
Data have;
set have;
Ind_out_sample=0;
outsample=0;
Run;
%ELSE %DO;
Data have;
set have;
Run;
%END;
%MEND My_Macro;
%My_Macro
Here is Log error
1 The SAS System 12:24 Thursday, December 19, 2024
1 ;*';*";*/;quit;run;
2 OPTIONS PAGENO=MIN;
3 %LET _CLIENTTASKLABEL='Program (4)';
4 %LET _CLIENTPROCESSFLOWNAME='Process Flow';
5 %LET _CLIENTPROJECTPATH='';
6 %LET _CLIENTPROJECTPATHHOST='';
7 %LET _CLIENTPROJECTNAME='';
8 %LET _SASPROGRAMFILE='';
9 %LET _SASPROGRAMFILEHOST='';
10
11 ODS _ALL_ CLOSE;
12 OPTIONS DEV=PNG;
13 GOPTIONS XPIXELS=0 YPIXELS=0;
14 FILENAME EGSR TEMP;
15 ODS tagsets.sasreport13(ID=EGSR) FILE=EGSR
16 STYLE=HTMLBlue
17 STYLESHEET=(URL="file:///C:/Program%20Files/SASHome/SASEnterpriseGuide/7.1/Styles/HTMLBlue.css")
18 NOGTITLE
19 NOGFOOTNOTE
20 GPATH=&sasworklocation
21 ENCODING=UTF8
22 options(rolap="on")
23 ;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
24
25 GOPTIONS ACCESSIBLE;
26 %let ind_OOT=1;
27
28 %macro My_Macro;
29 %IF &ind_OOT.=1 %THEN %DO;
30 Data have;
31 set have;
32 Ind_out_sample=0;
33 outsample=0;
34 Run;
35 %ELSE %DO;
ERROR: There is no matching %IF statement for the %ELSE.
ERROR: A dummy macro will be compiled.
36 Data have;
37 set have;
38 Run;
39 %END;
40 %MEND My_Macro;
41 %My_Macro
_
180
WARNING: Apparent invocation of macro MY_MACRO not resolved.
ERROR 180-322: Statement is not valid or it is used out of proper order.
42
43 GOPTIONS NOACCESSIBLE;
44 %LET _CLIENTTASKLABEL=;
45 %LET _CLIENTPROCESSFLOWNAME=;
46 %LET _CLIENTPROJECTPATH=;
47 %LET _CLIENTPROJECTPATHHOST=;
48 %LET _CLIENTPROJECTNAME=;
49 %LET _SASPROGRAMFILE=;
2 The SAS System 12:24 Thursday, December 19, 2024
50 %LET _SASPROGRAMFILEHOST=;
51
52 ;*';*";*/;quit;run;
53 ODS _ALL_ CLOSE;
54
55
56 QUIT; RUN;
57
Sorry, I found that there was missing %End
so this code is correct now
Data have;
input custID X;
cards;
1 10
3 30
;
Run;
%let ind_OOT=1;
/*%let ind_OOT=0;*/
%macro My_Macro;
%IF &ind_OOT.=1 %THEN %DO;
Data have;
set have;
Ind_out_sample=0;
outsample=0;
Run;
%ELSE %DO;
Data have;
set have;
Run;
%END;
%MEND My_Macro;
%My_Macro
I still see some missing %END;
And by the way the selected part should be deleted:
What's the point to rewrite HAVE when you already have it?
B.
You missed to have a %END for the first %DO.
Generic comment:
Personally, macros are the worst place to use the same data set as source and output. Since the data step completely replaces the data set from the SET statement it can be a poor idea to begin with. In a macro it can be worse because you forget the possibility and don't realize that multiple calls to the macro can seriously affect the content.
data someset; set someset; <other code> run;
Second, since your %else loop does nothing except read the data set and rewrite it then all it does is waste clock cycles. Useless:
%ELSE %DO; Data have; set have; Run; %END;
And a style point, if this is close to the use point and not just testing general logic, your &ind_OOT value should be a parameter of the macro and not just appear in code assuming it was set.
@quickbluefish wrote:
If your program is a linear process that's meant to be run from top to bottom in its entirety (which I require everyone on my team to do) as opposed to highlighting and running chunks, then having the input and output dataset names the same is much more space-efficient, not to mention less likely to introduce errors (setting the wrong dataset). We do everything in Linux and launch everything from the command line. Your mileage may vary.
Even during development, you always batch submit the entire program rather than run in an interactive session? I think I've only known one programmer who always did batch submits, and completely eschewed interactive sessions. But depending on the size of the data and amount of processing, that has its own efficiency costs, running the entire program every time you update a single step.
In my experience, judicious use of PROC DELETE is enough to resolve any concerns about space efficiency.
@quickbluefish wrote:
If your program is a linear process that's meant to be run from top to bottom in its entirety (which I require everyone on my team to do) as opposed to highlighting and running chunks, then having the input and output dataset names the same is much more space-efficient, not to mention less likely to introduce errors (setting the wrong dataset). We do everything in Linux and launch everything from the command line. Your mileage may vary.
Part of the bit around Macros is re-usability and the possibility of ending up in an Autocall library. Which is not conducive to relying on "top to bottom". I would say that is a pretty tight restriction on running code.
@ballardw wrote:...
Part of the bit around Macros is re-usability and the possibility of ending up in an Autocall library. Which is not conducive to relying on "top to bottom". I would say that is a pretty tight restriction on running code.
This thread has wander a long way off topic, but I am not sure I see this point. Using or not using autocall macros has nothing to do with whether your code should be executed in whole instead of in parts.
Unless you are still running some ancient version of SAS there is no need to define a macro in that case. You can use simple %IF/%THEN/%END [%ELSE/%DO/%END] blocks in open code now.
%IF &ind_OOT.=1 %THEN %DO;
data have;
set have;
Ind_out_sample=0;
outsample=0;
run;
%END;
%ELSE %DO;
* Your example data step did nothing so no need for anything here ;
%END;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.