BookmarkSubscribeRSS Feed
Abdu
Calcite | Level 5

"Assuming you keep this approach in place, definitely expect to call the macro using DOMAIN=LB ... no quotes needed."

Then if I do not apply: LENGTH LB $2;  LB='LB'; before %BASEANVARS(DOMAIN=LB); I will get "Variable LB is uninitialized" warning.

Tom
Super User Tom
Super User

When writing a macro you need to take care what are decisions that the macro needs to make (macro logic) and what just statements that the macro logic needs to generate. In general you should not include quotes around your parameter values and instead add quotes where needed in any SAS code that the macro generates.  In this case there is no need for quotes as you are not testing the macro parameter value against the value of any SAS data variable.  Instead you are using the value as part of a variable name.

So your original macro could be re-written as below. 

The effect is that the new variable PARCAT1 is defined and assigned a value only when DOMAIN is LB.

%macro mymacro(domain);

%if %upcase(&domain)=LB %then %do;

  length parcat1 $50;

  parcat1 = &domain.cat;

%end;

%mend mymacro;

Abdu
Calcite | Level 5

Thank you, Tom.

Maybe I was not very clear.  Actually, I does not have a variable have value 'LB'.  My question is just a technique question.  How can I pass 'LB' to macro without putting 'LB' to a variable then pass the variable to macro parameter domain.  In my previous response, my working macro is generate a variable then pass it to macro parameter.  I was trying to find a easier way.  I do have two solutions:

1. As you said and applied in my previous code, I named a variable LB that have value 'LB'.

2. Create a independent macro, that as JW suggested.

Thank you very much, SAS community.  I am improving by all of your comments.

Abdu.

Tom
Super User Tom
Super User

In normal SAS statements you need to put quotes around literal values so that it knows you do not mean a variable name or other language token. In general to a macro quotes are just like any other character. So if you want to call the macro with the value of LB then that is what you would do.

data want;

set have;

%mymacro(LB);

run;

jwillis
Quartz | Level 8

Abdu,

As a member of a SAS team and a trainer of novice SAS programmers, I want to take Tom's statement one step further.  Your coding style can be difficult to maintain as proven by all the comments to your post.  May I invite you to look through the community and find examples of call symputs that call macros based on values in a dataset and data _null_ statements that build entire processing flows (data and sql).  I am observing that your style is mixing two styles of programming. A data step that calls a macro and a macro that contains code used in a datastep.  My own style and preference is to build a macro that builds code and then call the macro.   For example:

(This is untested code for example purposes only.  The syntax has not been verified)

%global domain;

%MACRO MyMacro(Domain=);

DATA _LB_1;

  MERGE ADSL _LB_S;

  BY USUBJID;

  IF STRIP(UPCASE(LBSTAT)) = 'NOT DONE' THEN DELETE;

  FORMAT ADT DATE9. ATM TIME5.;

  %if %UPCASE(&DOMAIN.))=LB %THEN %DO;

  LENGTH PARCAT1 $50;

  PARCAT1 = &DOMAIN.CAT;       /* assume LBCAT is a variable in one of the merged datasets */

%end;

  RUN;

%MEND MyMacro;

%MyMacro(domain=LB);

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 19 replies
  • 1529 views
  • 6 likes
  • 7 in conversation