BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
ojaro
SAS Employee

Hi all,

 

I have the following code:

 

%let performance_range_start = 2019-11-01;
%let performance_range_end = 2020-02-01;

%macro inner2;

%put 'UPDATE DATA FOR:' &person_id;

%mend;

%macro inner1;
	data _NULL_;
		set pg.people(obs=5);
		CALL SYMPUT("person_id",strip(person_id));
		put 'START WORK:' person_id;
		%inner2;
	run;
%mend;

%macro outer;
   %let start=%sysfunc(inputn(&performance_range_start,yymmdd10.));
   %let end=%sysfunc(inputn(&performance_range_end,yymmdd10.));
   %let dif=%sysfunc(intck(month,&start,&end));
   %do i=0 %to &dif;
   	  %let r_start=%sysfunc(intnx(month,&start,&i,b),date9.);
	  %put 'PROCESS:' &r_start;
      %inner1;
   %end;
%mend;

%outer;

which outputs:

START WORK:1
START WORK:2
START WORK:3
START WORK:4
START WORK:5
'PROCESS:' 01DEC2019
'UPDATE DATA FOR:' 5

...
...

I was expecting:

START WORK:1
'PROCESS:' 01DEC2019
'UPDATE DATA FOR:' 1
START WORK:2
'PROCESS:' 01DEC2019
'UPDATE DATA FOR:' 2
START WORK:3
'PROCESS:' 01DEC2019
'UPDATE DATA FOR:' 3
START WORK:4
'PROCESS:' 01DEC2019
'UPDATE DATA FOR:' 4

...
...

Any pointers to where I am going wrong here? Do I somehow need to wait for the inner macros to finish before processing the next observation on the outer macro?

Many thanks in advance,

 

Olli

 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

Timing.

When your have something like that calls a macro inside a data step:

	data _NULL_;
		set pg.people(obs=5);
		CALL SYMPUT("person_id",strip(person_id));
		put 'START WORK:' person_id;
		%inner2;
	run;

The macro %inner2 executes when the data _null_ step compiles.

So you may want:

	data _NULL_;
		set pg.people(obs=5);
		CALL SYMPUT("person_id",strip(person_id));
		put 'START WORK:' person_id;
       run;
      %inner2;

What do you expect from this? You are reading 5 observations and the value of the macro variable &person_id will be that of the last of the 5 (or any number) read.

 

If you want to do something for each record in your input set PG.People you may be looking for the function CALL EXECUTE to create the code that runs after the data step completes.

View solution in original post

4 REPLIES 4
ballardw
Super User

Timing.

When your have something like that calls a macro inside a data step:

	data _NULL_;
		set pg.people(obs=5);
		CALL SYMPUT("person_id",strip(person_id));
		put 'START WORK:' person_id;
		%inner2;
	run;

The macro %inner2 executes when the data _null_ step compiles.

So you may want:

	data _NULL_;
		set pg.people(obs=5);
		CALL SYMPUT("person_id",strip(person_id));
		put 'START WORK:' person_id;
       run;
      %inner2;

What do you expect from this? You are reading 5 observations and the value of the macro variable &person_id will be that of the last of the 5 (or any number) read.

 

If you want to do something for each record in your input set PG.People you may be looking for the function CALL EXECUTE to create the code that runs after the data step completes.

ojaro
SAS Employee
Thanks so much for explaining how SAS data step executes. I can confirm that by changing my code to use CALL EXECUTE, I can see the desired effect.

Thanks again,

Olli
Astounding
PROC Star

There is no reason for %inner2 to use any macro language.  You could easily change its definition to be:

 

%macro inner2;

put 'UPDATE DATA FOR:' person_id;

%mend;

In fact, you might just include the PUT statement in the DATA step itself, without definining %inner2 at all.  You created the START WORK logic with no macro language, you could be able to similarly create the UPDATE DATA FOR logic with no macro language.

 

With a little more of a description of the intention, you might be able to get rid of all the macro language except for the two %LET statements at top.  The DATA step "knows" how to manipulate data much more easily than macro language does.

 

 

sustagens
Pyrite | Level 9

Try this non-macro approach

%let start = '01Nov2019'd;
%let end = '01Feb2020'd;

data _null_;
set pg.people (obs=5);
format r_start date9.;
dif=intck('month',&start,&end);
do i=0 to dif;
	put 'START WORK: ' person_id;
	r_start=intnx('month',&start,i,'b');
	put 'PROCESS: ' r_start;
	put 'UPDATE DATA FOR: ' person_id;
	put;
end;
run;

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 1821 views
  • 0 likes
  • 4 in conversation