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: Jane Eslinger presenting PROC REPORT and the ODS EXCEL destination on Mar 27 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

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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