pass iterator as value to macro function [duplicate] - sas

This question already has answers here:
Dynamically call macro from sas data step
(3 answers)
Closed 4 years ago.
I would like to pass do iterator as value - see example below
%macro print_to_log(val=);
%put &val;
%mend print_to_log;
data _null_;
do i = -15 to 0;
%print_to_log(val=i);
end;
run;
It only prints the character i to the log.

Will this work for you, if you use another macro instead of null ds as below?
%macro print_to_log(val);
%put &val;
%mend print_to_log;
%macro loop;
%do i = -15 %to 0;
%print_to_log(&i);
%end;
%mend loop;
%loop;

Related

Comparing date columns using sas macros

I I’m trying to compare two columns, both of which are dates. I know that some are the same so I expect to have some flagged as 1 within the macro. Which I can see when I don’t use the macro. Can anyone help.
Data test;
Set source;
*this works;
If date_1=date_2 then do;
X=1;
End;
else do;
X=0;
End;
*this doesnt work;
%macro flags(start=,flag=);
%If &start=date_2 %then %do;
&flag=1;
%End;
%else %do;
&flag=0;
%End;
%mend flags(start=flag_1,flag=x);
Run;
I tried to compare columns i was expecting a 1 if dates were the same and 0 if not.
Everything is 0 within a macro but ok if not using one.
If you want the macro to generate the same data step then make sure that it generates the IF statements also. You will need to call the macro inside of a data step so that the generated SAS code is run in a valid location.
%macro flags(start=,flag=);
if &start=date_2 then do;
&flag=1;
end;
else do;
&flag=0;
end;
%mend ;
data test;
set source;
%flags(start=flag_1,flag=x);
run;
PS SAS will evaluate a boolean expression as 1 for true and 0 for false so your code could be reduced to
%macro flags(start=,flag=);
&flag = (&start=date_2);
%mend ;
Which really does not need to be a macro.
data test;
set source;
x = (flag_1 = date_2);
run;

decrease macro variable containing date in steps

I currently using:
data _null_;
do i = 1 to 5;
temp = -10 * i;
%let minimum_date = %sysfunc(intnx(day,%sysfunc(today()),temp),date9.);
PUT temp;
end;
run;
This gives me an error:
ERROR: Argument 3 to function INTNX referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
Any ideas how to fix this please?
PS:
Ultimate aim expressed as pseudo-ish code:
data _null_;
do i = 1 to 5;
* set minimum_date to today - i*-10;
minimum_date = intnx('day',today(),i*-10);
* assign minimum_date to macro variable min_date;
call symput(min_date,minimum_date);
* invoke programs that use macro variable;
%include '/Bla/ChildProgram1.sas';
%include '/Bla/ChildProgram2.sas';
end;
run;
You asked SAS to evaluate the string TEMP as if it was a number. You should just remove the macro code and use normal code.
data _null_;
do i = 1 to 5;
minimum_date = intnx('day',today(),i*-10);
format mininum_date date9.;
put i= minimum_date=;
call execute(cats('%nrstr(%let) minimum_date=',put(minimum_date,date9),';'));
call execute("%include '/Bla/ChildProgram1.sas';");
call execute("%include '/Bla/ChildProgram2.sas';");
end;
run;
Or you could write a macro so that you could use a %DO loop.
%macro runall ;
%let start=%sysfunc(today());
%do i=1 %to 5;
%let minimum_date=%sysfunc(intnx(day,&start,-10*&i),date9);
%include '/Bla/ChildProgram1.sas';
%include '/Bla/ChildProgram2.sas';
%end;
%mend runall;
%runall;

Calling a Macro in a loop?

Here is a simple SAS program I created ...
%MACRO SCANLOOP();
%DO I=1 %TO 5;
%put &I;
%END;
%MEND;
%MACRO TEST();
%DO I=1 %TO 3;
%SCANLOOP();
%END;
%MEND;
%TEST();
RUN;
I was expecting this SAS code to produce the following output:
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
but instead I just got ...
1
2
3
4
5
Can anyone explain to me why?
Thanks
Brian
You need to define your macro variables as LOCAL. Otherwise SAS will use the existing macro variable with the same name in the outer scope. For your particular example you must make I local in the SCANLOOP macro. But you should really do it in both.
%MACRO SCANLOOP();
%LOCAL I;
%DO I=1 %TO 5;
%put &I;
%END;
%MEND;
Oh those variables are not scoped the way I expected. If I change the variable in the first macro from I to J then it works.

How can I excute macro program iteratively with consecutive constant numbers in sas? [duplicate]

This question already has answers here:
Dynamically call macro from sas data step
(3 answers)
Closed 8 years ago.
I am a beginner of macro. I modified a macro program and works.
But, I have to write the following macro hundred times as follows.
%quint(dsn=cc1, var=MB, quintvar=MB5, num=111) ;
%quint(dsn=cc1, var=MB, quintvar=MB5, num=112) ;
%quint(dsn=cc1, var=MB, quintvar=MB5, num=113) ;
-
-
%quint(dsn=cc1, var=MB, quintvar=MB5, num=400) ;
Everytime I make a program for this job, num is recognized as an arugment instead of constant numbers.
How can I make a short and easy one for this?
You can use RETAIN statement and CALL EXECUTE.
%macro quint (dsn, var, quintvar, num);
%put &dsn;
%put &var;
%put &quintvar;
%put #
%mend;
data _null_;
retain numv 111;
do until (numv = 400);
call execute ('%quint(cc1, MB, MB5,'||numv||')');
numv+1;
end;
run;
This works.
Using call execute is usually ok, but it can be a bit fiddly getting the quoting right, and I find that it sometimes fails to process complex macros correctly. I prefer to use a macro approach, by re-writing the original macro to accept parameters for the loop start and end, or by writing a wrapper macro, e.g.
%macro quint (dsn, var, quintvar, num);
%put &dsn;
%put &var;
%put &quintvar;
%put #
%mend;
%macro run_quint(dsn, var, quintvar, num_from, num_to);
%local i;
%do i = &num_from %to &num_to;
%quint(dsn=&dsn, var=&var, quintvar=&quintvar, num=&i)
%end;
%mend;
%run_quint(dsn=cc1, var=MB, quintvar=MB5, num_from=111, num_to = 115);

SAS macros to get the output for a desired range

I'm new to SAS. Please help with my query.
I have my codes working fine for a single date where I have defined
%let yyyymmdd= 20020509;
data x;
set PQ.CP_&yyyymmdd
and then the conditions to get the desired output.
Now, I want my same codes to work for the period between startrange=-50 days before yyyymmdd and endrange=-10 days before yyyymmdd. How can I define this in the beginning to get the output for this period also as I want to use it further. Please suggest me a way to do this.
Ok - am answering this in the context of your previous question - to address just the current question, ignore the 'inner loop' below:
%macro loop(yyyymmdd=, startrange=, endrange=);
%local date x ds1 ds2 y;
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
,%substr(&yyyymmdd,7,2)
,%substr(&yyyymmdd,1,4)));
/* this outer loop answers the curent question */
%do x=&startrange %to &endrange;
%let ds1=PQ.CP_%sysfunc(intnx(day,&date,&x),yymmddn8.);
%if %sysfunc(exist( &ds1 )) %then %do;
data x_%sysfunc(intnx(day,&date,&x),yymmddn8.);
set &ds1
/* this inner loop answers your previous question - remove if necessary */
%do y=-55 %to -10;
/* next date range is 55 to 10 days BEFORE the current iterative*/
/* value of (startrange-endrange) */
%let ds2=QA.TP_%sysfunc(intnx(day,&date,%eval(&y+&x)),yymmddn8.);
%if %sysfunc(exist( &ds2 )) %then %do;
&ds2
%end;
%end;
/* inner loop end */
;run;
%end;
%end;
/* outer loop end */
%mend;
%loop(yyyymmdd=20020509, startrange=-50, endrange=-10);