Your SAS programs, embedded in web apps and elsewhere

Change a Global Variable Dynamically in a Macro

Accepted Solution Solved
Reply
Super Contributor
Posts: 497
Accepted Solution

Change a Global Variable Dynamically in a Macro

Is there a way in SAS 9.2 to dynamically change a Global variable within a SAS macro e.g.

%Global testVar;

%macro Test(variableToChange);

                %let variableToChange = “A”;

%mend;

%Test(testVar);


Accepted Solutions
Solution
‎05-28-2015 09:59 AM
Super User
Posts: 5,509

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

Very close ... need to add an ampersand:

%let &variableToChange = "A";

It's not clear that you want quotes as part of the new value ... your example will change the variable to a set of three characters where the second character is A and the first and third characters are quotes.

Also, the local symbol table must not contain a macro variable named testVar. If it does, the local version will be changed not the global version.

View solution in original post


All Replies
Solution
‎05-28-2015 09:59 AM
Super User
Posts: 5,509

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

Very close ... need to add an ampersand:

%let &variableToChange = "A";

It's not clear that you want quotes as part of the new value ... your example will change the variable to a set of three characters where the second character is A and the first and third characters are quotes.

Also, the local symbol table must not contain a macro variable named testVar. If it does, the local version will be changed not the global version.

Super Contributor
Posts: 497

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to Astounding

Is there a way for a SAS macro to return a value?  I found some documentation that looked like the below.  Where the paper left the semi-colon off but it didn’t work for me in SAS 9.2.

%macro Test(variableToChange);

            %let variableToChange = ‘A’;

              &variableToChange /*this would be returned??*/

%mend;

Super User
Posts: 5,509

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

This time you need to add two ampersands.  The text to be returned should be:

&&&variableToChange

&variableToChange resolves to TextVar.  Adding the two ampersands resolves to the value of &TextVar.

Super User
Super User
Posts: 7,962

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to Astounding

Is it good practice to do this however?  The term Global means the whole program, to change that within a specific section seems to defeat the purpose.  Take an example:

%global pi;

%let pi=3.14;

%macro print();

     proc print ...;

     %let pi=3.141;

%mend print;

%Check_Circle_Measurements();


%Print();


%Check_Circle_Measurements();


...


The print changes the calculation later on.  Ok, with this you can see that, but if you have several files included, would you not lose confidence in the fact that pi had changed?  This is one of the old obfuscation techniques, change something which appears to be one thing into another in a subtle manner so its hard to see.

Super Contributor
Posts: 497

Re: Change a Global Variable Dynamically in a Macro

%let &variableToChange = “A”; worked for me on a simple scenario.  I tried using the same logic in a more complex macro and found that I’m running into an error on

%let &spacedList = &spacedList.%scan(%superQ(commaList), 1, str(,));

Where this works.

%let degStudLev = &degStudLev.%scan(%superQ(degStudLevComma), 1, str(,));

The full examples are below.  I’m thinking that I need to enclose commaList with something. 

/*outputs degStudLevdegS (Weird Output)*/

%Macro convertCommaListToSpaced(commaList, spacedList);

       %let &spacedList = &spacedList.%scan(%superQ(commaList), 1, str(,));

%mend;

%macro testmacro3();

       %let degStudLevComma = AH,AX,AV,AI;

       %let degStudLev= %str();

       %convertCommaListToSpaced(degStudLevComma, degStudLev);

       %put &degStudLev;

%mend;

%testmacro3;

/*outputs AH (Good Output)*/

%Macro convertCommaListToSpaced(commaList, spacedList);

       %let degStudLevComma = AH,AX,AV,AI;

       %let degStudLev= %str();

       %let degStudLev = &degStudLev.%scan(%superQ(degStudLevComma), 1, str(,));

%mend;


%macro testmacro3();

       %convertCommaListToSpaced(degStudLevComma, degStudLev);

       %put &degStudLev;

%mend;

%testmacro3;

Super Contributor
Posts: 497

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

A little simpler example of the problem.

This produces: degStuLevComma.

/*outputs degStuLevComma*/

%Macro convertCommaListToSpaced(commaList, spacedList);

       %let test = A;

       %put &commaList;

%mend;

%macro testmacro3();

       %let degStudLevComma = AH,AX,AV,AI;

       %let degStudLev= %str();

       %convertCommaListToSpaced(degStudLevComma, degStudLev);

%mend;

%testmacro3;

Super Contributor
Posts: 497

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

I found I can use this:

%let degStudLev = %convertCommaListToSpaced(commaList =%str(%quote(&degStudLevComma)), spacedList =&degStudLev); 

Still my result is not equivalent to running this without the macro.

Super User
Super User
Posts: 7,962

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

Sorry to sound like a broken record, but the examples you have given above would be far simpler to put lists of options in datasets rather than trying to force macro language to do base language processing.

data list;

     val="A"; output;

     val="B"; output;

     val="C"; output;

run;


/* Use list in base code */

proc sql;

     create table WANT as

     select * from HAVE where ID in (select VAL from LIST);

quit;


/* Use list to create where list */

proc sql;

     select VAL into :V_LIST separated by " ";  /* Just change if you want commas */

quit;

data want;

     set have (where=(id in (&V_LIST.));

run;

Etc.  The above seems far simpler to me that all that %xyz(&&&ABC&&&YYX%something());

Super Contributor
Posts: 497

Re: Change a Global Variable Dynamically in a Macro

RW9,


The input format is A,B,C.

Step 1 requires format A B C

Step 2 requires ‘A’, ‘B’, ‘C’

I need the macro to convert the input format to at least step 1. 

I also need to run this logic on 20 different inputs at different parts of the stored process.

Super User
Super User
Posts: 7,962

Re: Change a Global Variable Dynamically in a Macro

Posted in reply to DavidPhillips2

Not sure what you mean by "input" as don't use stored processes, but:

data _null_;

     set input;

     call symput('step1',tranwrd(input,","," "));

     call symput('step2',"'"||tranwrd(input,",","','")||"'");

run;

Should do it.

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 10 replies
  • 985 views
  • 6 likes
  • 3 in conversation