Overview 288
Introduction 288
Objectives 289
Basic Concepts 289
Using Automatic Macro Variables 292
Example 293
Using User-Defined Macro Variables 293
Example 294
Processing Macro Variables 295
SAS Processing 295
Tokenization 296
Examples 298
Macro Triggers 298
Summary 319
Text Summary 319
Basic Concepts 319
Syntax 321
Sample Programs 321
Quiz 323
SAS macro variables enable you to substitute text in your SAS programs. Macro variables can supply a variety of information, including
operating system information
SAS session information
text strings.
When you reference a macro variable in a SAS program, SAS replaces the reference with the text value that has been assigned to that macro variable. By substituting text into programs, SAS macro variables make your programs more reusable and dynamic.
The following sample code shows how a macro variable might be used to substitute a year value throughout a program, enabling you to quickly and easily change the value of year
throughout the program:
%let year=2002; proc print data=sasuser.schedule; where year(begin_date)=&year; title "Scheduled Classes for &year"; run; proc means data=sasuser.all sum; where year(begin_date)=&year; class location; var fee; title1 "Total Fees for &year Classes"; title2 "by Training Center"; run;
In this chapter, you learn to
recognize some benefits of using macro variables
substitute the value of a macro variable anywhere in a program
identify and display automatic macro variables
create and display user-defined macro variables
recognize how macro variables are processed
display macro variable values and other text in the SAS log
use macro character functions
combine macro references with adjacent text or with other macro variable references
use macro quoting functions.
In the SAS programs that you write, you might find that you need to reference the same variable, data set, or text string multiple times.
title "Total Sales for 2002"; data perm.sales2002; set perm.sales; if year(enddate)=2002; run; proc print data=perm.sales2002; run;
Then, you might need to change the references in your program in order to reference a different variable, data set, or text string. Especially if your programs are lengthy, scanning for specific references and updating them manually can take a lot of time, and it is easy to overlook a reference that needs to be updated.
title "Total Sales for 2001"; data perm.sales2001; set perm.sales; if year(enddate)=2002; run; proc print data=perm.sales2001; run;
If you use a macro variable in your program, these updates are quick and easy because you only need to make the change in one place.
%let year=2002; title "Total Sales for &year"; data perm.sales&year; set perm.sales; if year(enddate)=&year; run; proc print data=perm.sales&year; run;
The value of the macro variable is inserted into your program, so you can make one change and have the change appear throughout the program.
Macro variables are part of the SAS macro facility, which is a tool for extending and customizing SAS and for reducing the amount of program code you must enter in order to perform common tasks. The macro facility has its own language, which enables you to package small or large amounts of text into units that have names. From then on, you can work with the names rather than with the text itself.
There are two types of macro variables:
automatic macro variables, which are provided by SAS
user-defined macro variables, whose values you create and define.
Whether automatic or user-defined, a macro variable is independent of a SAS data set and contains one text string value that remains constant until you change it. The value of a macro variable is substituted into your program wherever the macro variable is referenced.
The value of a macro variable is stored in a symbol table. The values of automatic macro variables are always stored in the global symbol table, meaning that these values are always available in your SAS session. The values of user-defined macro variables are often stored in the global symbol table as well.
Macro variables can be defined and referenced anywhere in a SAS program except within the data lines of a DATALINES statement. You will learn more about how to define and reference macro variables throughout this chapter.
In order to substitute the value of a macro variable in your program, you must reference the macro variable. A macro variable reference is created by preceding the macro variable name with an ampersand (&). The reference causes the macro processor to search for the named variable in the symbol table and to return the value of the variable if the variable exists. If you need to reference a macro variable within quotation marks, such as in a title, you must use double quotation marks. The macro processor will not resolve macro variable references that appear within single quotation marks.
You will learn more about the macro processor later in this chapter. Δ
To reference the macro variable amount
from the global symbol table that is represented above, you place &amount
in your program, as follows:
You will see representations of code after substitution throughout this chapter. In a SAS session, you will not see this code. These representations are meant to show you what happens to your code behind the scenes, after macro processing. Δ
To reference the macro variable city
in a title, you must use double quotation marks to enclose the title text in the TITLE statement, as follows:
title "Students from &city";
When the macro processor cannot resolve a macro variable reference, a message is printed in the SAS log. For example, referencing a nonexistent macro variable results in a warning message. Referencing an invalid macro variable name results in an error message.
SAS creates and defines several automatic macro variables for you. Automatic macro variables contain information about your computing environment, such as the date and time of the session, and the version of SAS you are running. These automatic macro variables
are created when SAS is invoked
are global (always available)
are usually assigned values by SAS
can be assigned values by the user in some cases.
Some automatic macro variables have fixed values that are set when SAS is invoked.
Name | Value |
| the date of the SAS invocation (DATE7.) |
| the date of the SAS invocation (DATE9.) |
| the day of the week of the SAS invocation |
| the time of the SAS invocation |
| FORE (interactive execution) or BACK (noninteractive or batch execution) |
| an abbreviation for the operating system that is being used, such as OpenVMS, WIN, HP 300 |
| the release of SAS that is being used |
| an identifier for the current SAS session or for the current batch job (the user ID or job name for mainframe systems, the process ID (PID) for other systems) |
Some automatic macro variables have values that automatically change based on submitted SAS statements.
Name | Value |
| the name of the most recently created SAS data set, in the form |
| text that is specified when SAS is invoked |
| contains a return code status that is set by the DATA step and some SAS procedures to indicate whether the step or procedure executed successfully |
You can substitute system information such as the time, day, and date your SAS session was invoked and the version of SAS you are running in footnotes for a report.
footnote1 "Created &systime &sysday, &sysdate9"; footnote2 "on the &sysscp system using Release &sysver"; title "REVENUES FOR DALLAS TRAINING CENTER"; proc tabulate data=sasuser.all(keep=location course_title fee); where upcase(location)="DALLAS"; class course_title; var fee; table course_title=" " all="TOTALS", fee=" "*(n*f=3. sum*f=dollar10.) / rts=30 box="COURSE"; run;
time of day (SYSTIME
)
day of the week (SYSDAY
)
date (day, month, and year) (SYSDATE9
)
operating environment (SYSSCP
)
release of SAS (SYSVER
)
You have seen that SAS provides a variety of automatic macro variables for you. You can also create your own macro variables.
The simplest way to define your own macro variables is to use a %LET statement. The %LET statement enables you to define a macro variable and to assign a value to it.
If variable already exists, value replaces the current value. Δ
To create a macro variable named time
and assign a value of afternoon to it, you would submit the following %LET statement:
%let time=afternoon;
When you use the %LET statement to define macro variables, you should keep in mind the following rules:
All values are stored as character strings.
Mathematical expressions are not evaluated.
The case of the value is preserved.
Quotation marks that enclose literals are stored as part of the value.
Leading and trailing blanks are removed from the value before the assignment is made.
When you define a macro variable, remember that its value is always a character string. This table provides examples of macro variable assignment statements to illustrate the rules that are listed in the previous section.
%LET Statement | Variable Name | Variable Value | Length |
|
| Ed Norton | 9 |
|
| ' Ed Norton ' | 13 |
|
| "Joan's Report" | 15 |
|
| 0 | |
|
| 0 | 1 |
|
| 4+3 | 3 |
|
| 0+4+3 | 5 |
|
| varlist | 7 |
|
| name age height | 15 |
In the following example, the value DALLAS is assigned to the macro variable site
. The macro variable site
is then used to control program output.
%let site=DALLAS; title "REVENUES FOR &site TRAINING CENTER"; proc tabulate data=sasuser.all(keep=location course_title fee); where upcase(location)="&site"; class course_title; var fee; table course_title=' ' all='TOTALS', fee=' '*(n*f=3. sum*f=dollar10.) / rts=30 box='COURSE'; run;
You have seen how to create and reference macro variables. In order to work with macro variables in the programs that you write, you need to understand how macro variables are processed and stored. First, it is important that you understand how SAS processing works.
A SAS program can be any combination of
DATA steps and PROC steps
global statements
SAS Component Language (SCL) code
Structured Query Language (SQL) code
SAS macro language code.
When you submit a program, it goes to an area of memory called the input stack. This is true for all code that you submit, such as a DATA step, SCL code, or SQL code.
Once SAS code is in the input stack, SAS
reads the text in the input stack (left-to-right, top-to-bottom)
routes text to the appropriate compiler upon demand
suspends this activity when a step boundary such as a RUN statement is reached
executes the compiled code if there are no compilation errors
repeats this process for any subsequent steps.
Between the input stack and the compiler, SAS programs are tokenized into smaller pieces. A component of SAS known as the word scanner divides program text into fundamental units called tokens.
Tokens are passed on demand to the compiler.
The compiler requests tokens until it receives a semicolon.
The compiler performs a syntax check on the statement.
SAS stops sending statements to the compiler when it reaches a step boundary. Examples of step boundaries include a RUN statement (run;
) or the beginning of a new DATA or PROC step. Once the entire step has been compiled, it is executed.
The word scanner recognizes four types of tokens:
A literal token is a string of characters that are treated as a unit. The string is enclosed in either single or double quotation marks.
Examples: "Any text" 'Any text'
A number token is a string of numerals that can include a period or E-notation (real numbers). Date constants, time constants, datetime constants, and hexadecimal constants are also number tokens.
Examples: 23 109 '01jan2002'd 5e8 42.7
A name token is a string of characters that begins with a letter or underscore and that continues with underscores, letters, or digits. A period can sometimes be part of a name.
Examples: infile _n_ item3 univariate dollar10.2
A special token is any character or group of characters that has a reserved meaning to the compiler.
Examples: * / + - ** ; $ ( ) . & %
A token ends when the word scanner detects
the beginning of another token
a blank after a token.
The maximum length of any token is 32767 characters.
var x1 - x10 z ;
This example contains six tokens: var x1 - x10 z ;
title 'Report for May' ;
This example contains three tokens: title 'Report for May' ;
Macro variable references and %LET statements are part of the macro language. The macro facility includes a macro processor that is responsible for handling all macro language elements. Certain token sequences, known as macro triggers, alert the word scanner that the subsequent code should be sent to the macro processor.
The word scanner recognizes the following token sequences as macro triggers:
% followed immediately by a name token (such as %let)
& followed immediately by a name token (such as &amt).
When a macro trigger is detected, the word scanner passes it to the macro processor for evaluation. The macro processor
examines these tokens
requests additional tokens as necessary
performs the action indicated.
For macro variables, the processor does one of the following:
creates a macro variable in the symbol table and assigns a value to the variable
changes the value of an existing macro variable in the symbol table
looks up an existing macro variable in the symbol table and returns the variable's value to the input stack in place of the original reference.
The word scanner then resumes processing tokens from the input stack.
The word scanner will not recognize macro triggers that are enclosed in single quotation marks. Remember that if you need to reference a macro variable within a literal token, such as the title text in a TITLE statement, you must enclose the text string in double quotation marks or the macro variable reference will not be resolved. Δ
When you submit a macro variable reference, the macro processor resolves the reference and passes the value directly back to the input stack. Therefore, you will not see the value that the compiler receives. In order to debug your programs, it might be useful for you to see the value that replaces your macro variable reference. You can use the SYMBOLGEN system option to monitor the value that is substituted for a macro variable reference.
This system option displays the results of resolving macro variable references in the SAS log. That is, when the SYMBOLGEN option is turned on, SAS writes a message to the log for each macro variable that is referenced in your program. The message states the macro variable name and the resolved value.
Remember that since SYMBOLGEN is a system option, its setting remains in effect until you modify it or until you end your SAS session. Δ
Suppose you have previously assigned values to the macro variables amount
, city
, and company
, and you submit the following code:
data new; set sasuser.all; where fee>&amount; where also city_state contains "&city"; where also student_company contains '&company'; run;
Here is a sample SAS log that shows the messages that are generated by the SYMBOLGEN option for this code. The WHERE ALSO conditions augment the initial WHERE condition using the AND operator. In this example, the where processing will be done for the following condition: (fee>&amount) AND (city_state contains "&city") AND (student_company contains '&company').
Notice that no message is displayed for the final macro variable reference ('&company'
). Because this macro variable reference is enclosed in single quotation marks rather than in double quotation marks, the word scanner does not resolve it.
Another way of verifying the values of macro variables is to write your own messages to the SAS log. The %PUT statement writes text to the SAS log.
The %PUT statement
writes only to the SAS log
always writes to a new log line, starting in column one
writes a blank line if text is not specified
does not require quotation marks around text
resolves macro triggers in text before text is written
removes leading and trailing blanks from text unless a macro quoting function is used
wraps lines when the length of text is greater than the current line size setting
can be used either inside or outside a macro definition.
Suppose you want to verify the value of the macro variable city
. Since the %PUT statement resolves macro references in text before writing text to the SAS log, you can use it to show the stored value of city
.
%put The value of the macro variable CITY is: &city;
You can also simply submit the statement &put &city;
without any additional text. This statement will write the resolved value of the macro variable city
to the SAS log. However, it will not write any additional text to the log. You might find that it is a good idea to add explanatory text to your %PUT statements in order to maintain clarity in the SAS log. The %PUT statement has several optional arguments that you can add.
Argument | Result in SAS Log |
_ALL_ | Lists the values of all macro variables |
_AUTOMATIC_ | Lists the values of all automatic macro variables |
_USER_ | Lists the values of all user-defined macro variables |
Notice that when you use optional arguments such as _ALL_, each macro variable name is also written to the SAS log, along with a label of either AUTOMATIC or GLOBAL.
The SAS programming language uses matched pairs of either double or single quotation marks to distinguish character constants from names. The quotation marks are not stored as part of the token that they define. For example, in the following program, var is stored as a four-byte variable that has the value text.If text were not enclosed in quotation marks, it would be treated as a variable name. var2 is stored as a seven-byte variable that has the value example.
data one; var='text'; text='example'; var2=text; run;
Similarly, the title text in the following example is Joan's Report
. Although the TITLE statement contains a matched pair of double quotation marks, the title itself does not include these outer quotation marks. However, the outer quotation marks cause the unmatched single quotation mark within the text to be interpreted as an apostrophe that is part of the title text.
proc print; title "Joan's Report"; run;
Earlier you learned that macro variable values are character strings, and you saw examples of macro variables whose values included special characters. Now, suppose you want to store one or more SAS statements in a macro variable. For example, suppose you want to create a macro variable named prog
with data new; x=1; run; stored as its value.
options symbolgen; %let prog=data new; x=1; run; &prog proc print; run;
Here is part of the SAS log that results from the above program.
Notice that according to the SYMBOLGEN statement in the log, the macro variable prog
has been assigned a value of data new. SAS interpreted the first semicolon as the end of the macro assignment statement. In this case, we want the semicolon to be part of the macro variable value, but SAS has no way of knowing that. In this situation, you need to mask text that you want to assign to a macro variable. That is, you need to hide the normal meaning of the semicolon from the macro processor. You can use a macro quoting function to do this.
The %STR function is used to mask (or write quotation marks around) tokens during compilation so that the macro processor does not interpret them as macro-level syntax. That is, the %STR function hides the normal meaning of a semicolon and other special tokens and mnemonic equivalents of comparison or logical operators so that they appear as constant text. Special tokens and mnemonic equivalents include
; + - * / , < > = blank LT EQ GT AND OR NOT LE GE NE
The %STR function also
enables macro triggers to work normally
preserves leading and trailing blanks in its argument.
Applying this to our previous example, there are a number of ways that text can be quoted. Remember that we wanted to create a macro variable named prog
that has data new; x=1; run; as its value.
Method One
You could quote all text.
%let prog=%str(data new; x=1; run;);
Method Two
You could quote only the semicolons.
%let prog=data new%str(;) x=1%str(;)run%str(;);
Method Three
You could create an additional macro variable, assign a quoted value to it, and reference it in the assignment statement for the prog macro variable.
%let s=%str(;); %let prog=data new&s x=1&s run&s;
Each of these methods accomplishes the same thing: they all assign the value data=new; x=1; run; to the macro variable prog
.
The %STR function can also be used to quote tokens that typically occur in pairs:
' ")(
Suppose you want to assign text that contains an apostrophe (') to a macro variable. Without any quoting, this will lead to errors.
options symbolgen; %let text=Joan's Report; proc print data=sasuser.courses; where days > 3; title "&text"; run;
The word scanner interprets the apostrophe as the beginning of a literal that is defined by a pair of single quotation marks. You can use the %STR function to avoid this error. In the last section you saw several methods of using the %STR function to mask the normal meaning of a semicolon. However, none of the methods shown will correctly mask the apostrophe in our current example.
When you quote tokens that typically appear in pairs, such as quotation marks or parentheses, you must take one additional step. To perform this quoting, you precede the token that you want to quote with a percent sign (%) within the %STR function argument.
%let text=%str(Joan%'s Report); %let text=Joan%str(%')s Report;
The value of text
is Joan's Report in both cases.
Sometimes you might want to hide the normal meaning of an ampersand or a percent sign. The %NRSTR function performs the same quoting function as %STR, except it also masks macro triggers (& and %). The NR in the name %NRSTR stands for No Resolution. %NRSTR has the same syntax as %STR.
Suppose you want to create a macro variable named period and to assign a value of May&Jun to it. If you attempt to use the %STR function in the assignment statement, SAS will interpret the ampersand as a macro trigger and generate a warning message. You need to use the %NRSTR function instead.
%let Period=%str(May&Jun); %put Period resolves to: . %let Period=%nrstr(May&Jun); %put Period resolves to: .
The following portion of a SAS log shows the results of both the %STR and the %NRSTR functions for this example.
Like the %STR function, the %BQUOTE function is used to mask (or write quotation marks around) special characters and mnemonic operators. However, while the %STR function performs during compilation, the %BQUOTE function performs during execution. That is, the %BQUOTE function masks a character string or resolved value of a text expression during execution of a macro or macro language statement so that special characters and mnemonic operators are not interpreted as anything other than plain text. Special tokens and mnemonic equivalents include
' '' ( ) ; + - * / , < > = blank LT EQ GT AND OR NOT LE GE NE
The %BQUOTE function also
does not require that quotation marks be marked
enables macro triggers to work normally
preserves leading and trailing blanks in its argument.
Remember the example where you want to assign text that contains an apostrophe ('
) to a macro variable. You used the %STR function to mask the apostrophe.
%let text=%str(Joan%'s Report); %let text=Joan%str(%')s Report;
You can accomplish this task using the %BQUOTE function. The %BQUOTE function does not require that unmatched quotation marks be marked, so the title that contains an apostrophe requires no special syntax.
%let text=%bquote(Joan's Report);
The %NRBQUOTE function works the same as the %BQUOTE function except that %NRBQUOTE also masks the special characters listed below. Δ
&
%
Often when working with macro variables, you will need to manipulate character strings. You can do this by using macro character functions. With macro character functions, you can
change lowercase letters to uppercase
produce a substring of a character string
extract a word from a character string
determine the length of a character string, and more.
Macro character functions have the same basic syntax as the corresponding DATA step functions, and they yield similar results. It is important to remember that although they might be similar, macro character functions are distinct from DATA step functions. As part of the macro language, macro functions enable you to communicate with the macro processor in order to manipulate text strings that you insert into your SAS programs. The next few sections explore several macro character functions in greater detail.
The %UPCASE function enables you to change the value of a macro variable from lowercase to uppercase before substituting that value in a SAS program. Since most comparison operators in the SAS language are case sensitive, it is often necessary to change values to uppercase.
The Sasuser.All data set contains student information and registration information for computer training courses. Suppose you want to create a summary of the uncollected course fees:
%let paidval=n; proc means data=sasuser.all sum maxdec=0;
where paid="&paidval"; var fee; class course_title; title "Uncollected Fees for Each Course"; run;
Because the value of the macro variable paidval
was specified in lowercase, the WHERE expression finds no matching observations. All the values of the data set variable Paid
are stored in uppercase.
Now we will use the %UPCASE function in the WHERE statement:
%let paidval=n;
proc means data=sasuser.all sum maxdec=0;
where paid="%upcase(&paidval)";
var fee;
class course_title;
title "Uncollected Fees for Each Course";
run;
You can see that this time the WHERE expression does find matching observations.
If the argument contains a special character, a mnemonic operator, or a macro trigger, you will need to use the %QUPCASE function. %QUPCASE has the same syntax as the %UPCASE function, and it works the same as %UPCASE except that it also masks mnemonic operators and special characters (including macro triggers).
These statements show the results produced by %UPCASE and %QUPCASE:
%let a=begin; %let b=%nrstr(&a); %put UPCASE produces: %upcase(&b); %put QUPCASE produces: %qupcase(&b);
In the first %PUT statement, the macro reference &b
resolves to &a
, which is converted to &A
because of the %UPCASE function. Since the resolved value contains a macro trigger, it is treated as a macro variable reference and &A
resolves to the value begin. The second %PUT statement uses the %QUPCASE function, which masks the ampersand in the resolved value of the macro variable b
so that this value is not treated as another macro variable reference. Executing these statements produces the following messages in the SAS log.
The %SUBSTR function enables you to extract part of a character string from the value of a macro variable.
If the length of n is greater than the number of characters following position in argument, %SUBSTR issues a warning message and returns a substring that contains the characters from position to the end of the string. If n is not specified, %SUBSTR also returns a substring that contains the characters from position to the end of the string. Δ
For example, assume that the macro variable date
has the value 05JAN2002.
The code %substr(&date,3)
will return the value JAN2002.
The code %substr(&date,3,3)
will return the value JAN.
The code %substr(&date,3,9)
will return the value JAN2002 and will produce a warning message.
The values of position and n can also be the result of a mathematical expression that yields an integer. For example, %substr(&var,%length(&var)-1)
returns the last two characters of the value of the macro variable var
.
The %LENGTH function accepts an argument that is either a character string or a text expression. If the argument is a character string, %LENGTH returns the length of the string. If the argument is a text expression, %LENGTH returns the length of the resolved value. If the argument has a null value, %LENGTH returns 0. Δ
Suppose you want to print a report on all courses that have been taught since the start of the current month. You can use the %SUBSTR function and the SYSDATE9
macro variable to determine the month and year, as follows:
proc print data=sasuser.schedule;
where begin_date between
"01%substr(&sysdate9,3)"d and
"&sysdate9"d;
title "All Courses Held So Far This Month";
title2 "(as of &sysdate9)";
run;
If the argument contains a special character, a mnemonic operator, or a macro trigger, you will need to use the %QSUBSTR function. %QSUBSTR has the same syntax as the %SUBSTR function, and it works the same as %SUBSTR except that it also masks mnemonic operators and special characters (including macro triggers).
These statements show the results produced by %SUBSTR and %QSUBSTR:
%let a=one; %let b=two; %let c=%nrstr(&a &b); %put C: &c %put With SUBSTR: %substr(&c,1,2); %put With QSUBSTR: %qsubstr(&c,1,2);
Executing these statements produces the following messages in the SAS log. As you can see, the first %PUT statement shows that &c
resolves to the value &a &b
. In the second %PUT statement, the %SUBSTR function extracts the value &a
from the resolved value of the macro variable reference &c
, and resolves &a
to one. The third %PUT statement shows that the %QSUBSTR function prevents the value &a
from being resolved further.
The %INDEX function enables you to determine the position of the first character of a string within another string.
The %INDEX function
searches source for the first occurrence of string
returns a number representing the position in source of the first character of string when there is an exact pattern match returns 0
when there is no pattern match.
returns 0
when there is no pattern match.
The following statements find the first character V
in a string:
%let a=a very long value; %let b=%index(&a,v); %put V appears at position &b.;
Executing these statements writes the following line to the SAS log.
The %SCAN function enables you to extract words from the value of a macro variable.
If argument contains a comma, you must enclose argument in a quoting function. Similarly, in order to use a single blank or a single comma as the only delimiter, you must enclose the character in the %STR function. Δ
The delimiters that %SCAN recognizes vary between ASCII and EBCDIC systems. If you omit delimiters, SAS treats the following characters as default delimiters:
ASCII systems: blank . < ( + & ! $ * ) ; ^ - / , % |
EBCDIC systems: blank . < ( + | & ! $ * ) ; -/ ,% ¦¢
If delimiters includes any of the default delimiters for your system, the remaining default delimiters are treated as text.
You can use PROC DATASETS along with the %SCAN function and the SYSLAST
macro variable to investigate the structure of the most recently created data set:
data work.thisyear; set sasuser.schedule; where year(begin_date) = year("&sysdate9"d); run; %let libref=%scan(&syslast,1,.); %let dsname=%scan(&syslast,2,.); proc datasets lib=&libref nolist; title "Contents of the Data Set &syslast"; contents data=&dsname; run; quit;
If the argument contains a special character, a mnemonic operator, or a macro trigger, you will need to use the %QSCAN function. %QSCAN has the same syntax as the %SCAN function, and it works the same as %SCAN except that it also masks mnemonic operators and special characters (including macro triggers).
You have learned that by using the automatic macro variables SYSDATE9
and SYSTIME
you can include the date and time in a title:
title1 "Report Produced on &sysdate9"; title2 "at &systime";
SYSDATE9
represents the date on which the SAS session started, and SYSTIME
represents the time at which the SAS session started. Suppose you would rather see the date in some other format, or suppose you would rather see the current date or time. You can use the %SYSFUNC function to execute other SAS functions as part of the macro facility.
All SAS functions can be used with %SYSFUNC except
DIF
DIM
HBOUND
INPUT
IORCMSG
LAG
LBOUND
MISSING
PUT
RESOLVE
SYMGET
all Variable Information functions, including functions such as VNAME and VLABEL. For a complete list of Variable Information functions, see the SAS documentation.
You can use the INPUTC or INPUTN function in place of the INPUT function. Similarly, you can use the PUTC or PUTN function in place of the PUT function with %SYSFUNC. Δ
Suppose the following code was submitted on Friday, June 7, 2007:
title "%sysfunc(today(),weekdate.) - SALES REPORT";
The title on the next report would be Friday, June 7, 2007 - SALES REPORT
.
As with macro character functions, if the argument for a %SYSFUNC function contains special characters or mnemonic operators, you must use the quoting version of the function. The %QSYSFUNC function has the same syntax as the %SYSFUNC function. %QSYSFUNC works the same as %SYSFUNC except that it also masks mnemonic operators and special characters.
Suppose you want to create a report title that includes the current date in WORDDATE. format. You could use this statement:
title "Report Produced on %sysfunc(today(),worddate.)";
However, that would result in the following title:
Report Produced on June 7, 2007
The extra blanks are from the default length of the WORDDATE. format. You need to left justify the resulting formatted date. You cannot nest functions within %SYSFUNC, but you can use a %SYSFUNC for each function that you need, as shown in this example:
title "Report Produced on %sysfunc(left(%sysfunc(today(),worddate.)))";
However, this statement results in the following error message.
Table 9.13. SAS Log
|
The LEFT function expects only one argument, but you are passing "June 7, 2007" to it. It interprets the comma as the delimiter between two arguments.
You can mask the comma by using the %QSYSFUNC function instead, as follows:
title "Report Produced on %sysfunc(left(%qsysfunc(today(),worddate.)))";
The modified statement generates the following title:
Report Produced on June 7, 2007
You can reference macro variables anywhere in your program. Some applications might require placing a macro variable reference adjacent to leading text (text &variable) or trailing text (&variabletext) or referencing adjacent macro variables (&variable&variable) in order to build a new token. When you combine macro variable references and text, it is important to keep in mind how SAS interprets tokens.
Remember that a token ends when the word scanner detects either the beginning of a new token or a blank after a token.
You can place text immediately before a macro variable reference to build a new token. For example, suppose that data sets are stored in a SAS library, using the naming convention Yyymon, where yy is a two-digit year such as 02
or 01
, and mon is a three-letter month such as JUN
or AUG
. Data set names could include examples such as Y01DEC and Y02MAR. You can write a program that uses a macro variable to build the month portion of the SAS data set name.
%let month=jan; proc chart data=sasuser.y02&month; hbar week / sumvar=sale; run; proc plot data=sasuser.y02&month; plot sale*day; run;
If you are using the SAS Learning Edition, you will not be able to submit this code because it uses PROC CHART and the CHART procedure is not included in the software. This example is used in the next several sections and in the chapter summary. Δ
You can reference macro variables that have no blanks between them to build new tokens.
For example, you can modify the previous program to enable both the month and the year to be substituted:
%let year=02; %let month=jan; proc chart data=sasuser.y&year&month; hbar week / sumvar=sale; run; proc plot data=sasuser.y&year&month; plot sale*day; run;
The generated program is identical to the program in the previous example. That is, the compiler sees the same code for both of these examples.
You can place text immediately after a macro variable reference as long as the macro variable name can still be tokenized correctly.
For example, you can modify the previous program to substitute the name of an analysis variable:
%let year=02;
%let month=jan;
%let var=sale;
proc chart data=sasuser.y&year&month;
hbar week / sumvar=&var; run; proc plot data=sasuser.y&year&month; plot &var*day; run;
The generated program is identical to the program in the previous two examples. That is, although you are changing the code that you submit, you are not changing the code that the compiler sees.
Sometimes you might want to place a macro variable name immediately before text other than a special character. For example, you might want to modify the previous program so that it is easy to switch between using the CHART and PLOT procedures of Base SAS software and the GCHART and GPLOT procedures of SAS/GRAPH software.
/* GRAPHICS should be null or G */ %let graphics=g; %let year=02; %let month=jan; %let var=sale; proc &graphicschart data=sasuser.y&year&month; hbar week / sumvar=&var; run; proc &graphicsplot data=sasuser.y&year&month; plot &var*day; run;
The messages written to the SAS log reveal problems with this program.
SAS interprets the macro variable's name to be graphicschart
instead of graphics
because there is no delimiter between the macro variable reference and the trailing text.
The word scanner recognizes the end of a macro variable name when it encounters a special character that cannot be part of the name token. In other words, the special character acts as a delimiter. For example, a period (.) is a special character that is treated as part of the macro variable reference and that does not appear when the macro variable is resolved.
To correct the problem in the previous example, you need to add a period after the reference to the macro variable graphics
.
%let graphics=g; %let year=02; %let month=jan; %let var=sale; proc &graphics.chart data=sasuser.y&year&month; hbar week / sumvar=&var; run; proc &graphics.plot data=sasuser.y&year&month; plot &var*day; run;
When these SAS statements are executed
the word scanner treats &graphics.
as the reference
the value of the macro variable graphics
is returned to the input stack
the word scanner processes gchart
as one token.
We can extend this example and further modify the previous program to include a macro variable that is used to define the libref:
%let lib=sasuser; %let graphics=g; %let year=02; %let month=jan; %let var=sale; libname &lib 'SAS-data-library'; proc &graphics.chart data=&lib.y&year&month; hbar week / sumvar=&var; run; proc &graphics.plot data=&lib.y&year&month; plot &var*day; run;
Notice, however, that this code does not perform the desired substitutions.
The period after &lib
is interpreted as a delimiter. You need to use a second period after the delimiter period to supply the necessary token:
%let lib=sasuser; ... libname &lib 'SAS-data-library'; proc &graphics.chart data=&lib..y&year&month; ... proc &graphics.plot data=&lib..y&hear&month;
The first period is treated as a delimiter, and the second period is treated as text.
This section contains the following:
a text summary of the material taught in this chapter
syntax for statements and options
sample programs
points to remember.
Macro variables can supply a variety of information, from operating system information, to SAS session information, to any text string that you define. Updating multiple references to a variable, data set, or text string is a simple process if you use macro variables in your programs. Macro variables are part of the SAS macro facility, which is a tool for extending and customizing SAS and for reducing the amount of text you must enter in order to perform common tasks.
Values of macro variables are stored in symbol tables. Values that are stored in the global symbol table are always available. In order to substitute the value of a macro variable in your program, you must reference that macro variable by preceding the macro variable name with an ampersand. You can reference a macro variable anywhere in a SAS program except within data lines.
SAS provides automatic macro variables that contain information about your computing environment. Automatic macro variables are created when SAS is invoked. Many of these variables have fixed values that are assigned by SAS and which remain constant for the duration of your SAS session. Others have values that are updated automatically based on submitted SAS statements.
You can create and define your own macro variables with the %LET statement. The %LET statement enables you to assign a value for your new macro variable and to store that value in the global symbol table. Macro variable values are character strings; except for leading and trailing blanks, values are stored exactly as they appear in the assignment statement.
When submitted, a SAS program goes to an area of memory called the input stack. From there, the word scanner divides the program into small chunks called tokens and passes them to the appropriate compiler for eventual execution. Certain token sequences are macro triggers, which are sent to the macro processor for resolution. Once a macro variable has been resolved by the macro processor, the stored value is substituted back into the program in the input stack, and word scanning continues.
You can use the SYMBOLGEN system option to monitor the value that is substituted for a macro variable reference. You can also use the %PUT statement to write messages, which can include macro variable values, to the SAS log.
The %STR function enables you to quote tokens during compilation in order to mask them from the macro processor. The %NRSTR function enables you to quote tokens that include macro triggers from the macro processor. The %BQUOTE function enables you to quote a character string or resolved value of a text expression during execution of a macro or macro language statement.
You can use macro character functions to apply character string manipulations to the values of macro variables. The %UPCASE function enables you to change values from lowercase to uppercase. The %QUPCASE function works the same as %UPCASE except that it also masks special characters and mnemonic operators. The %SUBSTR function enables you to extract part of a string from a macro variable value. The %QSUBSTR function works the same as %SUBSTR except that it also masks special characters and mnemonic operators. The %INDEX function enables you to determine the location of the first character of a character string within a source. Using the %SCAN function, you can extract words from the value of a macro variable. The %QSCAN function works the same as %SCAN except that it also masks special characters and mnemonic operators.
You can use the %SYSFUNC function to execute other SAS functions. The %QSYSFUNC function works the same as the %SYSFUNC function except that it also masks special characters and mnemonic operators.
You might sometimes need to combine a macro variable reference with other text. You can place text immediately before or immediately after a macro variable reference. You can also combine two macro variable references in order to create a new token. You might need to use a delimiter when you combine macro variable references with text.
OPTIONS NOSYMBOLGEN | SYMBOLGEN; |
%PUT text; |
%LET variable=value; |
%STR (argument) |
%NRSTR (argument) |
%BQUOTE (argument) |
%UPCASE (argument) |
%QUPCASE (argument) |
%SUBSTR (argument, position <,n>) |
%QSUBSTR (argument, position <,n>) |
%INDEX (source,string) |
%SCAN (argument, n <,delimiters>) |
%QSCAN (argument, n <,delimiters>) |
%SYSFUNC (function(argument(s))< ,format>) |
%QSYSFUNC (function(argument(s))< ,format>) |
options symbolgen; %let year=2002; proc print data=sasuser.schedule; where year(begin_date)=&year; title "Scheduled Classes for &year"; run; proc means data=sasuser.all sum; where year(begin_date)=&year; class location; var fee; title1 "Total Fees for &year Classes"; title2 "by Training Center"; run;
footnote1 "Created &systime &sysday, &sysdate9"; footnote2 "on the &sysscp system using Release &sysver";
title "REVENUES FOR DALLAS TRAINING CENTER"; proc tabulate data=sasuser.all(keep=location course_title fee); where upcase(location)="DALLAS"; class course_title; var fee; table course_title=" " all="TOTALS", fee=" "*(n*f=3. sum*f=dollar10.) / rts=30 box="COURSE"; run;
%let year=02; %let month=jan; proc chart data=sasuser.y&year&month; hbar week / sumvar=sale; run; proc plot data=sasuser.y&year&month; plot sale*day; run;
Macro variables can make your programs more reusable and dynamic.
When you submit code to SAS, macro variable references are resolved by the macro processor, and their values are substituted into your program.
You can use the %PUT statement to write any text, including resolved macro variables, to the SAS log.
If you reference a macro variable within quotation marks, you must use double quotation marks. Macro variable references that are enclosed in single quotation marks will not be resolved.
Most macro character functions have corresponding functions (such as %QSUBSTR and %QSCAN) that also mask special characters and mnemonic operators.
Select the best answer for each question. After completing the quiz, check your answers using the answer key in the appendix.
Which of the following statements is false?
A macro variable can be defined and referenced anywhere in a SAS program except within data lines.
Macro variables are always user-defined, and their values remain constant until they are changed by the user.
Macro variables are text strings that are independent of SAS data sets.
The values of macro variables can be up to 65,534 characters long.
Which of the following TITLE statements correctly references the macro variable month
?
title "Total Sales for '&month' ";
title "Total Sales for 'month'";
title "Total Sales for &month";
title Total Sales for "&month";
Which of the following statements will generate an error message while trying to display the value of the macro variable month
in the SAS log?
options &month;
%PUT &month;
options symbolgen;
%PUT the macro variable MONTH has the value &month.;
Which statement will create a macro variable named location
that has the value storage?
&let location = storage;
let &location = storage;
%let location = "storage";
%let location = storage;
What value will these statements assign to the macro variable reptitle
:
%let area = "Southeast"; %let reptitle = * Sales Report for &area Area *;
Sales Report for Southeast Area
Sales Report for "Southeast" Area
*Sales Report for "Southeast" Area*
* Sales Report for "Southeast" Area *
Assuming that you began your SAS session today, which of the following statements correctly sets the macro variable currdate
to today's date:
%let currdate = %sysfunc(today(), worddate.);
%let currdate = &sysdate9;
%let currdate = %sysfunc(date());
all of the above
Macro character functions
can be used to manipulate character strings in macro variable values.
have the same basic syntax as the corresponding DATA step functions and yield similar results.
all of the above
none of the above
The four types of tokens that SAS recognizes are
expressions, literals, names, and special characters.
literals, names, numbers, and special characters.
expressions, names, numbers, and special characters.
expressions, literals, numbers, and special characters.
What are the resulting values for the macro variables that are defined here?
%let month1 = June; %let month2 = July; %let period1 = &month1&month2; %let period2 = May&month1; %let period3 = &month2.Aug;
month1 June
month2 July
period1 June July
period2 May June
period3 July Aug
month1 June
month2 July
period1 JuneJuly
period2 MayJune
period3 July.Aug
month1 June
month2 July
period1 JuneJuly
period2 MayJune
period3 JulyAug
month1 June
month2 July
period1 junejuly
period2 Mayjune
period3 julyaug
Which of the following correctly produces a title in which the current date is left justified in order to remove extra blanks?
title "Report for %sysfunc(left(%sysfunc(today(),worddate.)))";
title "Report for %sysfunc(left(today(), worddate.))";
title "Report for %sysfunc(left(%qsysfunc(today(), worddate.)))";
title "Report for %left(today(), worddate.))";