BookmarkSubscribeRSS Feed
Philip_Jou
Calcite | Level 5

This is more of a question about the general understanding of how SAS processes procedures as I did develop a work around to this problem.

Here is the code below:

%macro runrpt_all(nRun,dataset);

    %do z=1 %to &nRun;

        data _null_;

            set work.&dataset;

            if _n_ = &z then do;

                call symput('as_grp',trim(assess_Grp));

                call symput('lbl_1',trim(label_1));

                call symput('lbl_2',trim(label_2));

                call symput('lbl_3',trim(label_3));

                call symput('level',trim(lvl));

            end;

        run;

        %runrpt(&as_grp,%str(&lbl_1),%str(&lbl_2),&level,&lbl_3);

        dm "ODSRESULTS;CLEAR";dm 'CLEAR LOG;CLEAR OUTPUT;';

    %end;

    %put EXIT;

%mend runrpt_all;

Here is the situation. The code above was created in order to automate a process to run the macro "%runrpt" instead of having many "%runrpt" macro statements and adjusting them each program run. Within the dataset, Label_1 (&lbl_1) and Label_2 (&lbl_2) has instances of commas in their data. The "%runrpt" macro takes 4 variables in, so the commas would pose an issue. In order to resolve that case, the manual method used the %str() macro to encapsulate the manually inputted string that contained commas. So I decided to replicate the same method, hence why you see %str(&lbl_1) and %str(&lbl_2). However, doing that produced the very error I was trying to avoid; detection of too many parameters passed in.

So my question is, how does SAS process a %str() statement with a macro-variable inside. Again, under the manual method of placing %str(string,with,commas), the macro will run fine. Once I switch it to using a macro variable, I get the error regarding too many parameters detected.

My work-around is as follows:

        data _null_;
            set work.&dataset;
            if _n_ = &z then do;
                call symput('as_grp',trim(assess_Grp));
                call symput('lbl_1',cats('%str(',label_1,')'));
                call symput('lbl_2',cats('%str(',label_2,')'));
                call symput('lbl_3',trim(label_3));
                call symput('level',trim(lvl));
            end;
        run;

        %runrpt(&as_grp,&lbl_1,&lbl_2,&level,&lbl_3);


Thanks for any help to answer this question

3 REPLIES 3
Quentin
Super User

Hi,

If you want to quote the resolved value of  a macro variable, you need to use another quoting function, either %bquote() or %superq() rather than %str().

On  a related note, I suggest you look at CALL EXECUTE for this sort of data driven macro call approach.  With it, you can have a dataset of macro parameter values (as you have), and then in a data step, call a macro once for every record, passing in the values.  So you can do what you've done with less overhead.

Something like (untested):

data _null_;
  set work.&dataset;
  call execute 
    (
    '%nrstr('
        ||  '%RunRpt'
        ||    '('
        ||    ' assess_Grp '
        ||    ',label_1 '
        ||    ',label_2 '
        ||    ',label_3 '
        ||    ' )'
        || ')'
    );
run;


HTH

--Q.

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Philip_Jou
Calcite | Level 5

Thank you Quentin for your response. There are too many macro functions to keep track of and I had just forgotten that one.

Regarding your suggestion to use call execute. I did think of using that as I have implemented that strategy in other portions of the project I am working on. The quick method that came out of my head was what you see. I may convert the code later however the overhead concerns are not critical to this program at the moment.

Thank you again for the help.

Philip

Tom
Super User Tom
Super User

%SUPERQ() is probably the safest way to quote.

%runrpt(&as_grp,%superq(lbl_1),%superq(lbl_2),&level,%superq(lbl_3));

Other things to consider is to modify the macro so that parameters where the values might have commas or other special characters are delivered with quotes around them.

%runrpt(&as_grp,"&lbl_1","&lbl_2",&level,"&lbl_3");

As far as a quick method for generating a lot of macro calls from a data set I find that using SAS to write the code to a file is the easiest to work with.  You can eyeball the file to make sure the code looks right.  Open it and submit the first few lines.  Or even take it and embed it in another program.

filename code temp ;

data _null_;

  set work.&dataset;

   file code ;

  put '%runrpt'

    / '(' access_grp

    / ',' label_1 :quote.

    / ',' label_2 :quote.

    / ',' lvl

    / ',' label_3 :quote.

    / ');'

  ;

   if getoption('DMS')='DMS' then put

      "dm 'ODSRESULTS;CLEAR';"

    / "dm 'CLEAR LOG;CLEAR OUTPUT';"

  ;

run;

%inc code / source2 ;  

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 3 replies
  • 2005 views
  • 0 likes
  • 3 in conversation