Search code examples
sasputletmacro-variable

SAS creating global macro and printing it


I am new to SAS environment. I just want to create a global this month variable and print it & use it
in the where condition of data step. My test codes are below:

    %macro vars();
        %global this_month = MONTH(today());
    %mend vars;
    %put this_month=&this_month; 

    The log in put statement is:  
    WARNING: Apparent symbolic reference THIS_MONTH not resolved.  
    this_month=&this_month

I expect the log as this_month=7, but no such result appears.How can i do this? Thanks in advance.


Solution

  • There are a few things to note about macro variables:

    1. Macro variables created in open code are global
    2. Macro variables created within a macro function will be local unless they are already defined, in which case the original value will be modified
    3. You cannot assign a macro variable a value while explicitly defining it is global or local
    4. Using DATA Step functions requires encapsulating them with %sysfunc()
    5. You need to call a macro function to execute it

    In your case, to create a global macro variable for this month, simply state it anywhere in your program before you want to define it:

    %let this_month = %sysfunc(month(%sysfunc(today())));
    %put this_month = &this_month;
    
    this_month = 7
    

    Now let's assume you want to have a global macro variable created from within a macro, similar to what you have in your code. Here's how you would do it:

    %macro vars; * Define a macro function;
        %global this_month;
        %let this_month = %sysfunc(month(%sysfunc(today())));
    %mend;
    %vars; * Execute the function;
    
    %put this_month = &this_month; 
    
    this_month = 7
    

    For fun, let's see what happens when we define a global macro variable, define a local macro variable of the same name, then see what the value of the global macro variable is.

    %let foo = bar;
    
    %put Before function: foo=&foo;
    
    %macro test;
        %let foo = baz;
        %put Inside function: foo=&foo;
    %mend;
    %test;
    
    %put After function: foo=&foo;
    
    Before function: foo=bar
    Inside function: foo=baz
    After function:  foo=baz
    

    You can see that the global value of foo was modified! This is because we already defined foo as global by defining it within open code. This may or may not be ideal, but you can fix this by explicitly defining foo as local within the macro function:

    %let foo = bar;
    
    %put Before function: foo=&foo;
    
    %macro test;
        %local foo;
        %let foo = baz;
        %put Inside function: foo=&foo;
    %mend;
    %test;
    
    %put After function: foo=&foo;
    
    Before function: foo=bar
    Inside function: foo=baz
    After function:  foo=bar
    

    This is why it's very important to define common variables as local (e.g. i, j, k, etc.), especially if you're using loops nested within macros.