BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
sarahsasuser
Quartz | Level 8

Hi All,

I'm running a report on building stats. I'm using the by statement in the report so that I get separate tables for each building. I want to add I have the variables building_id and building_name to the title of each report. I am not sure how to create a macro for 2 variables. Can I modify this code to include the building_name as shown below? Also, instead of calling the individual buildings with %do_id at the end, can I build a smarter macro that looks for each unique ID number and runs the report?

%macro do_id(building_id);

%macro do_name(building_name);

     title1 "Annual Report for &id and &name;

     proc report data=buildings;

          by buiding_id;

          define .....

run;

%mend do_id;

%mend do_name;

%do_id (A94);

%do_id (A02)

%do_id (A503);

%do_id (A06);

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Make sure the parameter names you define in the %MACRO statement match the macro variable references in the code.

Make sure to use double quotes so that macro references are resolved.

Make sure to quote the values of character variables in the generated SAS code.

%macro do_id_name(id,name);

proc report data=have nowd split='/';

    title "&id and &name";

   where building_id = &id and building_name = "&name" ;

  columns Type Subtype Region Count Expected count_ontime late pct_within pct_not_within;

  define Type/display  " Type";

  define subtype /display  "subtype";

  define  Region/display  "Region";

  define Count/ display "Count";

  define Expected/  display 'Expected';

  define count_ontime/display '# Ontime';

  define late/display  '# late';

  define Pct_within/display  '% ontime' format=PERCENT7.0;

  define Pct_not_within/display  '% late' format=PERCENT7.0;

run;

%mend do_id_name;

%do_id_name(1, 1222 smith st);


To generate a call for each value in the data there are a number of methods.

With a small list of values you might just generate the calls into a macro variable.


proc sql noprint ;

  select distinct cats('%do_id_name(', building_id , ',' , building_name ,')')

    into :runlist separated by ';'

from have

;

quit;

&runlist ;


View solution in original post

11 REPLIES 11
Tom
Super User Tom
Super User

Not sure what the question is.

If you want the TITLE to reflect the value of the BY variable then use #BYVAL() in the TITLE statement.  See the documentation on the TITLE statement.  http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000220968.htm

title1 "Annual Report for #byval(building_id) and #byval(building_name)"

options nobyline;

proc ...

   by building_id building_name;

....


If you want to pass more than one parameter into a macro then just define it with more than one parameter.

%macro do_id_name(id,name);

....

  title1 "Annual Report for &id and &name";

...

where building_id = &id and building_name = "&name" ;

....

%mend do_id_name;

sarahsasuser
Quartz | Level 8

Hi Tom,

Thanks for your suggestions. Since I have a couple of different tables I want to create for each building I think using a macro with more than one parameter is the best solution. However, I'm new to macros and am having trouble with the next step. I wrote this marco: %macro do_id_name(id,name). When I call the macro with %do_id_name; I get this error:


WARNING: Apparent symbolic reference ID not resolved.

WARNING: Apparent symbolic reference NAME not resolved.

ERROR: Syntax error while parsing WHERE clause.

ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string,

              a numeric constant, a datetime constant, a missing value, INPUT, PUT.

ERROR 76-322: Syntax error, statement will be ignored.

I have:

%macro do_id_name(id,name);

....proc report

  title1 "Annual Report for &id and &name";

...

where building_id = &id and building_name = "&name" ;

....

proc report

title1 "Annual Report for &id and &name";

...

where building_id = &id and building_name = &name ;

....

%mend do_id_name;

%do_id_name;

Reeza
Super User

You don't need a macro if you're generating all at once is what Tom is implying. The BY variables become macro variables of a sort and you can reference them, without having to explicitly create them.

See how Tom used #byval(building_id) and #byval(#name) in the title above.

If you want a macro route then its best to post your code and log to help with debugging. for starters, your last line that calls the macro doesn't include the input parameters or the underscores in the macro name.

Tom
Super User Tom
Super User

You will need to create a real macro with real code replacing the ... Smiley Happy

This message is an indication that your macro is not defined. Check for errors from SAS when it actually compiled the macro.

WARNING: Apparent symbolic reference ID not resolved.

WARNING: Apparent symbolic reference NAME not resolved.

You also might have unbalanced quotes or () that are confusing it.

sarahsasuser
Quartz | Level 8

Hi Reeza and Tom,

I don't want to use the #byval because I have 3 report tables I need to make for each building id. If I do a byval, it will run table #1 for each building, and then table 2 for each building and so on. I want instead to run for building 1 tables #1 - table #3, then building 2 tables 1-3, etc.

Here is my code. Do I need to call each building id/name combo in the %do_id_name; statement? For instance %do_id_name (1, 1222 smith st)? I'd like for the macro to run through the dataset and run the report for each unique building id/name combo, instead of me having to tell it to. Is that possible?

%macro do_id_name(building_id,building_name);

proc report data=have nowd split='/';

    title '&id and&name';

   where building_id = &id and building_name = &name ;

  columns Type Subtype Region Count Expected count_ontime late pct_within pct_not_within;

  define Type/display  " Type";

  define subtype /display  "subtype";

  define  Region/display  "Region";

  define Count/ display "Count";

  define Expected/  display 'Expected';

  define count_ontime/display '# Ontime';

  define late/display  '# late';

  define Pct_within/display  '% ontime' format=PERCENT7.0;

  define Pct_not_within/display  '% late' format=PERCENT7.0;

run;

%mend do_id_name;

%do_id_name;

Reeza
Super User

Yes its possible, first off though macro variables only resolve when in double quotes. And you may need to quote your macro variables in your where condition to have the code be valid SAS code.

Again, you've provided parameters at the top but haven't called it with any...

sarahsasuser
Quartz | Level 8

Hi Reeza,

I forgot that double quotes were needed. I've substituted double quotes for singles in the proc report statement and around "&name" as this is a character field. I've added the parameters when I call the macro: %do_id_name (building_id,building_name);

However I'm still getting this error:

2500  %mend do_id_name;

2501  %do_id_name(building_id,building_name);

WARNING: Apparent symbolic reference ID not resolved.

WARNING: Apparent symbolic reference NAME not resolved.

NOTE: Line generated by the invoked macro "DO_ID_NAME".

1     proc report data=les.all_cover nowd split="/";     where building_id = &id and building_name =

-

22

76

1   ! "&name" ;     columns ....

WARNING: Apparent symbolic reference ID not resolved.

WARNING: Apparent symbolic reference NAME not resolved.

ERROR: Syntax error while parsing WHERE clause.

ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string,

              a numeric constant, a datetime constant, a missing value, INPUT, PUT.

ERROR 76-322: Syntax error, statement will be ignored.

Reeza
Super User

The last example in the link below is close to what you're looking for, there are also lots of other examples on here, but get your base macro working first Smiley Happy

Statistical Computing Seminar: Introduction to SAS Macro Language

sarahsasuser
Quartz | Level 8

Thanks, the documentation is helpful.

Tom
Super User Tom
Super User

Make sure the parameter names you define in the %MACRO statement match the macro variable references in the code.

Make sure to use double quotes so that macro references are resolved.

Make sure to quote the values of character variables in the generated SAS code.

%macro do_id_name(id,name);

proc report data=have nowd split='/';

    title "&id and &name";

   where building_id = &id and building_name = "&name" ;

  columns Type Subtype Region Count Expected count_ontime late pct_within pct_not_within;

  define Type/display  " Type";

  define subtype /display  "subtype";

  define  Region/display  "Region";

  define Count/ display "Count";

  define Expected/  display 'Expected';

  define count_ontime/display '# Ontime';

  define late/display  '# late';

  define Pct_within/display  '% ontime' format=PERCENT7.0;

  define Pct_not_within/display  '% late' format=PERCENT7.0;

run;

%mend do_id_name;

%do_id_name(1, 1222 smith st);


To generate a call for each value in the data there are a number of methods.

With a small list of values you might just generate the calls into a macro variable.


proc sql noprint ;

  select distinct cats('%do_id_name(', building_id , ',' , building_name ,')')

    into :runlist separated by ';'

from have

;

quit;

&runlist ;


sarahsasuser
Quartz | Level 8

Thanks Tom! This was very helpful.

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
  • 11 replies
  • 1398 views
  • 6 likes
  • 3 in conversation