DATA Step, Macro, Functions and more

Macro Variables- "ERROR: The %DO statement is not valid in open code."

Reply
Occasional Contributor
Posts: 14

Macro Variables- "ERROR: The %DO statement is not valid in open code."

I sometimes use SAS macro variables to generate/store SAS code automatically. It was a nice way to do things for me, until yesterday. The following codes gives me errors:

"ERROR: The %DO statement is not valid in open code."

"ERROR: The %END statement is not valid in open code."

But apparently the %do and %end are within the macro boundary.

*===========================;

%macro test();

data t;

x=%nrstr("%do i=1 %to 5;");

y=%nrstr("%end;");

call symputx("y",y);

call symputx("x",x);

run;

&x.;

&y.;

%mend;

%test();

*===========================;

It looks like some bug that relates to how SAS interprets/resolves a macro variable that contains keywords such as "%do", "%end", etc.  I have tried various ways to bypass the problem but so far failed.

Super User
Super User
Posts: 7,407

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

The &x.; is being resolved as %do I=1 %to 5;, however at that time the code has passed through the macro pre-processor and hence is in open code.  I would question why you are doing this at all, the macro language is there so you can create code which gets replicated or modified at pre-processor time.  Not sure why you need to have a macro to generate a loop?  If you really have to do that then:

data _null_;

     do I=1 to 5;

          call execute("%my_macro(....);");

     end;

run;

would probably be more effective though dependant on your scenario.  If you could expand you example I could provide further information.

Occasional Contributor
Posts: 14

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

Thanks. Here is a self explanatory example of what I want to achieve -- I am relying on SAS to generate the code for me. The code structure is dynamic. For example, the # (in the example it is n=4) of %do loop level is an adjustable parameter.

%macro test1(n);

data s;

format x $100.; x="";

format y $100.; y="";

%do j=1 %to &n.;

x="%do i&j.=1 %"||"to 5;"||strip(x);

y="%end;"||strip(y);

%end;

call symputx("y",y);

call symputx("x",x);

run;

&x.;

&y.;

%mend;

%test1(n=4);

Super User
Posts: 6,946

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

How should the final code look like?

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Posts: 5,085

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

The real question is a little different:  If the macro were to execute successfully, what would the generated SAS code look like?  It is entirely likely that the final solution will involve more DATA step code and less macro language ... but it's necessary to begin by looking at where you would like to end up.

Occasional Contributor
Posts: 14

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

here is the final code that my sas code generates: when n=4 and when n=3 respectively.

*================================;

%macro test (n);

     %do i1=1 %to 5;

     %do i2=1 %to 5;

     %do i3=1 %to 5;

     %do i4=1 %to 5;

          /* do something */

     %end;%end%;end%;end%;

%mend test;

%test(n=4);

*================================;

*================================;

%macro test (n);

     %do i1=1 %to 5;

     %do i2=1 %to 5;

     %do i3=1 %to 5;

          /* do something */

     %end;%end%;end%;

%mend test;

%test(n=3);

*================================;

Super User
Posts: 5,085

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

It's tricky ... but you knew that.  It might be easiest to write code to a file, such as:

%macro test1 (n);

   data _null_;

   file myfile noprint;

   put 'macro test (n);';

   do i=1 to &n;

     i_char = left(put(i, 3.));

      put '%do i'   i_char   ' = 1 %to 5;';

   end;

   put '/* do something */';

   do i=1 to &n;

      put '%end;';

   end;

   put '%mend test;';

   run;

   %include myfile;

   %test (&n)

%mend test1;

%test1 (4)

I'll have to think about other approaches.

Is there a reason you need &n macro variables, each with its own loop?  Certainly it would be possible to code something like %do i=1 %to 5**n;  Perhaps you're presenting a simplified version and the "5" doesn't really get hard-coded?

Occasional Contributor
Posts: 14

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

yes, the value 5 is not hard coded.

I was able to "auto-generate" codes that contains "do to;/end;" loop previously.  but now stuck with "%do %to;/%end;" loop

Let me go back to think about this and get back to you guys when I got some concrete idea.

Super User
Super User
Posts: 7,407

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

Hi,

Could you provide a concrete example of what you input is, and what you want out.  You can try the below, this seems to generate the loops as your macro does:

data test (drop=i j);

  length loop ender $2000.;

  do i=1 to 10;

    do j=1 to 5;

      loop='do i'||strip(put(i,best.))||'=1 to 5; '||strip(loop);

      ender='end;'||strip(ender);

    end;

  end;

  call execute('data _null_;'||strip(loop)||strip(ender)||'run;');

run;

Personally I tend to favour this method of doing things when I have lots of loops, the reason is you can put all your parameters, loop, clause in a dataset, then just run over that generating the code as you go.

Super User
Posts: 5,085

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

Just a small piece of the puzzle, in case it helps ...

If the ending vlaue of 5 is not hard-coded, presumably you actually have something equivalent to:

%do i1=1 %to &i1_max.;

%do i2=1 %to &i2_max.;

You could get the proper number of loops with something along these lines:

%do i=1 %to &i1_max.*&i2_max.*&i3_max.;

Sometimes having the proper number of loops is sufficient, sometimes not.

Super User
Super User
Posts: 7,407

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

Yes, not sure what the idea is here, your code basically resolves to (in my eyes):

%macro test (n);

     %do I=1 %to &n.;

          /* do something */

     %end;

%mend test;

%test;

I don't see why you are creating the string to hold your do loop, then adding it into the code later on?

Respected Advisor
Posts: 3,777

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

%DO must be compiled and that is NOT what is happening with your program.

Occasional Contributor
Posts: 14

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

I also wrote another piece of code which run successfully without error log-- this evidence supports the argument that "%DO must be compiled and that is NOT what is happening with your program.".

%macro test2();

data r;

z=%nrstr("%macro inner(); %do i=1 %to 5; data a&i; run; %end; %mend; %inner();");

call symputx("z",z);

run;

&z.;

%mend;

%test2();

Anyway, to me, SAS' not being able to accept "%DO/%END" in macro variables is a design deficiency. I will let you good folks know if I find any workarounds. thanks.

Super User
Super User
Posts: 7,407

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

Its end of day for me, but am I missing something, surely the same could be achieved by:

%macro test (n);

     %do I = 1 %to &N.;

          %do J=1 %to 5;

               /* do something */

          %end;

     %end;

%mend test;

%test(n=4);

There are also a fair few other options, utilize arrays and call execute is one example I can think of, setup a dataset with all your loops in then generate the code.

Occasional Contributor
Posts: 14

Re: Macro Variables- "ERROR: The %DO statement is not valid in open code."

sorry but i guess they are different?

you code has 2 nested loop, but my code has 4 nested loop when n=4, and it can actually generate 100 nest loops if i set the parameter n=100 in my code.

Ask a Question
Discussion stats
  • 15 replies
  • 1716 views
  • 0 likes
  • 5 in conversation