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.

BASUG is hosting free webinars Next up: Mike Sale presenting Data Warehousing with SAS April 10 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
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-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 1720 views
  • 0 likes
  • 3 in conversation