BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
abaker_ca
Calcite | Level 5

Hello,

 

I'm trying to execute a macro in a do loop and am stuck. I'm new to macros and I know there are a lot of problems with my code! 

Please go easy on me and in your correction, assume my knowledge is already limited so I might not understand everything you say at first.

 

Here's a sample macro that works fine on its own:

 

/*the macro*/

%macro calc(n, i);
data power_calc;
result = &n**&i;
run;
%mend;

 

Here's the looping macro I wrote to execute %calc:

 

%macro loop(n, start, end);
   %do i=&start %to &end;
  
%calc(n=&n, i=&i);

   %end;
%mend;

 

Here's the call to the looping macro:

 

%let n = 2;

%let start = 1;
%let end = 4;

%loop(start = &start, end = &end);

 

 

Here are the error messages where I can see that the call to %calc is not resolving

 


NOTE: Line generated by the invoked macro "CALC".
1 result = &n**&i;
------
180

ERROR 180-322: Statement is not valid or it is used out of proper order.

NOTE: Line generated by the invoked macro "LOOP".
9    %calc(n=&n, i=&i)   
----
217
ERROR 217-322: Invalid statement due to first character being unprintable (hexadecimal representation: C2A0C2A0).

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User
Please see the code posted, that just has slight modifications to your original code. The last step at the end combines the data sets created together.

View solution in original post

14 REPLIES 14
PaigeMiller
Diamond | Level 26

You didn't give the argument N a value in this line

 

%loop(start = &start, end = &end)

 

and so when %loop executes, N has no value and the code fails.

 

Its the same as typing

 

%loop(start = &start, end = &end, n=);

 

and so again argument N has no value. I leave it up to you to figure out what value to place after N= in the above statement.

--
Paige Miller
abaker_ca
Calcite | Level 5

Sorry. I pasted a version of the code that didn't have the &n argument in the call. I fixed this at one point and still get the same error messages.

 

The call in the code was:

%let n = 2;
%let start = 1;
%let end = 4;

%loop(n = &n, start = &start, end = &end);

 

And the error messages are the same:

 

 

NOTE: Line generated by the invoked macro "CALC".
1 result = &n**&i;
------
180

ERROR 180-322: Statement is not valid or it is used out of proper order.

NOTE: Line generated by the invoked macro "LOOP".
9    %calc(n=&n, i=&i)   
----
217
ERROR 217-322: Invalid statement due to first character being unprintable (hexadecimal representation: C2A0C2A0).

 

PaigeMiller
Diamond | Level 26

Using

 

%let n = 2;
%let start = 1;
%let end = 4;

%loop(n = &n, start = &start, end = &end)

everything works for me.

 

Since it is not working for you, please turn on the macro debugging options by running this line of code

 

options mprint;

and then run your code again and show us the ENTIRE log (every single line, every single character, not just the error messages) by copying the log as text and then pasting it into the window that appears when you click on the </> icon. DO NOT SKIP THESE INSTRUCTIONS.

PaigeMiller_0-1663012019648.png

 

--
Paige Miller
Tom
Super User Tom
Super User

That macro %CALC() is not something you would call in that way (unless all you wanted was to write some stuff to the SAS log) because it always writes the same dataset, POWER_CALC.  So after the looping only the results of the last call will still exist.

 

Perhaps your real macro is more complex and that is the problem?

abaker_ca
Calcite | Level 5
Do you know how I should call %calc() so that it writes out each iteration?
Tom
Super User Tom
Super User

@abaker_ca wrote:
Do you know how I should call %calc() so that it writes out each iteration?

It is not about how you call it but what it is doing.

If you can change the macro then make it create a different dataset each time.

%macro calc(n, i);
data power_calc_&n_&i;
result = &n**&i;
run;
%mend;

Or perhaps append an observation to a fixed dataset.  But in that case the dataset needs more variables.

%macro calc(n, i);
data next;
n=&n;
i=&i;
result = n**i;
run;
proc append data=next base=power_calc force;
run;
%mend;

If you cannot change the %CALC() macro the add the extra logic inside your looping macro.

%calc(&n,&i);
data next;
  n=&n;
  i=&i;
  set power_calc;
run;
proc append data=next base=all_power_calc force;
run;

 

abaker_ca
Calcite | Level 5

Unfortunately, none of the examples you've given work with the do loop macro. Although they are good examples of a better way to write the original %calc macro.

 

My issue is that I have an analysis where I will have to execute the macro I've written about 30 times and then append all the output together.

 

I'd prefer not to have to type out the call to the macro that many times!

 

But I just can't figure out how to execute it within a do-loop. 

 

Perhaps the do loop should be in the macro itself.....

Tom
Super User Tom
Super User

That is what the third example is for.  I just did not write out the looping code as you already had that.

abaker_ca
Calcite | Level 5

So I could put a do loop in the 3rd example? 

 

Tom
Super User Tom
Super User

You should be able to just add the extra steps after the call to the %calc macro in your existing %DO loop you shared before.

 

If the actual output of %calc() has enough variables to distinguish the the input N and I values you don't need to extra data step to add those variables.

abaker_ca
Calcite | Level 5

I hate to ask you to do all the heavy lifting for me but I truly don't know enough SAS to put this all together.

 

If I could add the extra steps in the %do loop, what would that look like? 

 

I've been laboring over this for a while and haven't figured it out on my own so I'd appreciate a complete set of code where the %calc is called in the %do that I can execute.

 

I just need one working example so I can pick it apart and hopefully understand the logic.

 

Reeza
Super User
Please see the code posted, that just has slight modifications to your original code. The last step at the end combines the data sets created together.
abaker_ca
Calcite | Level 5

The solution worked! 

 

Thank you so much. I'm going to see if I can use this general approach to my programming from now on.

 

Alice

Reeza
Super User

Don't use the same macro variables over to avoid confusion (e.g. i)

 

%macro calc(n, i);
data power_calc&i.;
result = &n**&i;
iteration = &i.;

run;
%mend;

 


%macro loop(n, start, end);
   %do j=&start %to &end;
  
%calc(n=&n, i=&j);

   %end;
%mend;

 

 

%let n = 2;
%let start = 1;
%let end = 4;

%loop(n=&n, start = &start, end = &end);


data want;
set power_calc1-power_calc&end.;
run;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 14 replies
  • 1480 views
  • 0 likes
  • 4 in conversation