100% found this document useful (2 votes)
511 views296 pages

LWMC1V2 001

Uploaded by

Henrique Modesto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
511 views296 pages

LWMC1V2 001

Uploaded by

Henrique Modesto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 296

SAS® Macro Language 1:

Essentials

Course Notes
SAS® Macro Language 1: Essentials Course Notes was developed by Stacey Syphus, Mark Jordan,
and Kathy Passarella . Additional contributions were made by Brittany Coleman, Bruce Dawless,
Davetta Dunlap, Brian Gayle, Gina Repole, and Theresa Stemler. Instructional design, editing, and
production support was provided by the Learning Design and Development team.
SAS and all other SAS Institute Inc. product or service names are registered trademarks or
trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration.
Other brand and product names are trademarks of their respective companies.
SAS® Macro Language 1: Essentials Course Notes

Copyright © 2019 SAS Institute Inc. Cary, NC, USA. All rights reserved. Printed in the United States
of America. No part of this publication may be reproduced, stored in a retrieval system, or
transmitted, in any form or by any means, electronic, mechanical, photocopying, or otherwise,
without the prior written permission of the publisher, SAS Institute Inc.

Book code E71585, course code LWMC1V2/MC1V2, prepared date 11Dec2019. LWMC1V2_001

ISBN 978-1-64295-754-9
For Your Information iii

Table of Contents

Lesson 1 Introduction ................................................................................................. 1-1

1.1 Why SAS Macro? ...................................................................................................... 1-3

1.2 Setting Up for This Course ........................................................................................ 1-8

1.3 Solutions .................................................................................................................. 1-13

Solutions to Activities and Questions ................................................................ 1-13

Lesson 2 SAS® Macro Facility .................................................................................... 2-1

2.1 Program Flow ............................................................................................................ 2-3

2.2 Creating and Using Macro Variables ....................................................................... 2-16


Practice.............................................................................................................. 2-39

2.3 Solutions .................................................................................................................. 2-40


Solutions to Practices ........................................................................................ 2-40

Solutions to Activities and Questions ................................................................ 2-42

Lesson 3 Storing and Processing Text ..................................................................... 3-1

3.1 Macro Functions ........................................................................................................ 3-3


Demonstration: Macro Functions ....................................................................... 3-19

Practice.............................................................................................................. 3-21

3.2 Using SQL to Create Macro Variables .................................................................... 3-23

Demonstration: Creating Macro Variables with a PROC SQL Query ................ 3-28

Practice.............................................................................................................. 3-32

3.3 Using the DATA Step to Create Macro Variables .................................................... 3-34

Demonstration: Creating Macro Variables with the DATA Step ......................... 3-48

Practice.............................................................................................................. 3-52

3.4 Indirect References to Macro Variables .................................................................. 3-53


Demonstration: Indirect References to Macro Variables ................................... 3-61
iv For Your Information

Practice.............................................................................................................. 3-63

3.5 Solutions .................................................................................................................. 3-64


Solutions to Practices ........................................................................................ 3-64

Solutions to Activities and Questions ................................................................ 3-72

Lesson 4 Working with Macro Programs .................................................................. 4-1

4.1 Defining and Calling a Macro .................................................................................... 4-3

Demonstration: Creating a Macro Definition with Parameters .......................... 4-14

Practice.............................................................................................................. 4-20

4.2 Macro Variable Scope ............................................................................................. 4-22

Practice.............................................................................................................. 4-42

4.3 Conditional Processing ............................................................................................ 4-44

Demonstration: Conditional Processing ............................................................ 4-58

Practice.............................................................................................................. 4-61

4.4 Iterative Processing ................................................................................................. 4-63

Demonstration: Iterative %DO Loops ................................................................ 4-67

Demonstration: %DO Loops with Indirect References ...................................... 4-72

Practice.............................................................................................................. 4-82

4.5 Solutions .................................................................................................................. 4-84

Solutions to Practices ........................................................................................ 4-84


Solutions to Activities and Questions ................................................................ 4-93

Lesson 5 Developing Macro Applications ................................................................ 5-1

5.1 Storing Macros........................................................................................................... 5-3

Demonstration: Macro Autocall Libraries ........................................................... 5-10

5.2 Generating Data-Dependent Code ......................................................................... 5-17

Demonstration: Generating Data-Dependent Code .......................................... 5-23

Practice.............................................................................................................. 5-25

5.3 Validating Parameters and Documenting Macros ................................................... 5-27


For Your Information v

Demonstration: Validating Parameters .............................................................. 5-38

Practice.............................................................................................................. 5-44

5.4 Solutions .................................................................................................................. 5-46

Solutions to Practices ........................................................................................ 5-46


Solutions to Activities and Questions ................................................................ 5-51
vi For Your Information

To learn more…
For information about other courses in the curriculum, contact the
SAS Education Division at 1-800-333-7660, or send e-mail to
[email protected]. You can also find this information on the web at
http://support.sas.com/training/ as well as in the Training Course
Catalog.

For a list of SAS books (including e-books) that relate to the topics
covered in this course notes, visit https://www.sas.com/sas/books.html or
call 1-800-727-0025. US customers receive free shipping to US
addresses.
Lesson 1 Introduction

1.1 Why SAS Macro? .................................................................................................................... 1-3

1.2 Setting Up for This Course .................................................................................................... 1-8

1.3 Solutions ................................................................................................................................ 1-13


Solutions to Activities and Questions ................................................................................... 1-13
1-2 Lesson 1 Introduction

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.1 Why SAS Macro? 1-3

1.1 Why SAS Macro?

Macro Programming

SAS Macro
Facility TEXT

The SAS macro


facility enables you
to write code that
rewrites itself!

3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Substituting System Values

title1 "Cars List";


title2 "Created at 10:24 AM on October 9, 2019";
footnote "Environment: SAS 9.4 on Win X64_10PRO";

proc print data=sashelp.cars;


run; How can the macro
Automatically language make
substitute system your job easier as a
values into a program. SAS programmer?

4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.
CarsProgram.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-4 Lesson 1 Introduction

Substituting User-Defined Values

Easily replace
title "Trucks by Origin"; repetitive values.
proc freq data=sashelp.cars;
where Type="Truck";
table Origin;
run; Truck
title "Average Highway MPG for Trucks";
proc means data=sashelp.cars mean maxdec=1; SUV
where Type="Truck";
var MPG_Highway;
class Origin;
run; Sports

5
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.
CarsProgram.sas

Conditional Processing
data mpg;
set sashelp.cars;
AvgMPG=mean(MPG_Highway, MPG_City);
run; Submit or modify
Did the step run without code based on a
warnings or errors? condition.

NO
YES
Write a custom error
Print the table.
message to the log.

proc print data=mpg; ERROR: MPG table was not created


run; successfully.

6
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.
CarsProgram.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.1 Why SAS Macro? 1-5

Repetitive Processing
title "4-Cylinder Cars";
proc print data=sashelp.cars;
where Cylinders=4;
run; Generate repetitive
SAS code.
title "6-Cylinder Cars";
proc print data=sashelp.cars;
where Cylinders=6;
run;

title "8-Cylinder Cars";


proc print data=sashelp.cars;
where Cylinders=8;
run;
7
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.
CarsProgram.sas

Data-Driven Applications
data hybrid sedan sports suv truck wagon;
set sashelp.cars;
select(Type);
when("Hybrid") output hybrid;
when("Sedan") output sedan;
when("Sports") output sports;
when("SUV") output suv;
when("Truck") output truck;
when("Wagon") output wagon;
otherwise;
end; Build programs
run; dynamically based on
data values.

8
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.
CarsProgram.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-6 Lesson 1 Introduction

Efficiency of Macro-Based Applications

The macro facility processes the


text in a program to automate
and customize the code.

CarsMacro.sas
9
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

To view an example of a program that uses the SAS macro language to address the challenges
presented in the previous slides, open CarsMacro.sas in the demos folder of the course files.

Efficiency of Macro-Based Applications

The macro language


won’t make your code
run faster, but it can
reduce your development
and maintenance time.

CarsMacro.sas
10
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.1 Why SAS Macro? 1-7

Developing a Macro Application

Use macro-level
Start with a Generalize Create a macro Validate
programming Add data-driven
validated SAS with macro definition with parameters and
for complex features
program variables parameters document
processing

We'll use this process to


start with regular SAS
code and produce a
macro application.

11
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Discussion
How do you envision the SAS macro
language helping you in your work?

Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-8 Lesson 1 Introduction

1.2 Setting Up for This Course

Data Used in This Course

Sashelp International Orion Star


storm retail

14
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Practicing in This Course

Demonstration Performed by your instructor as an example for you


to observe
Activity Short practice opportunities for you to perform in SAS,
either independently or with the guidance of your
instructor
Practice Extended practice opportunities for you to work on
independently
Case Study A comprehensive practice opportunity at the end
of the class

15
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.2 Setting Up for This Course 1-9

Choosing a Practice Level

Level 1 Solve basic problems with step-by-step guidance


Level 2 Solve intermediate problems with defined goals
Challenge Solve complex problems independently with
SAS Help and documentation resources
Choose one
practice per section
based on your
interest and skill
level.

16
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Extending Your Learning

17
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-10 Lesson 1 Introduction

Accessing the Course Files

course Make a note of the


activities
files location of your
course files folder.
autocall

case_study

data

demos

practices
18
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Accessing the Course Files


Programs in the
course activities, demos,
activities
files and practices
folders follow this
autocall naming convention.

case_study

data

demos
m104p01.sas
practices Macro 1, Lesson 4, practice 1
19
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.2 Setting Up for This Course 1-11

Creating the Course Data

course activities
files
autocall

case_study

cre8data.sas data

demos

practices
20
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

1.01 Activity (Required)


1. SAS Studio: In the Navigation pane, expand Files and Folders and then
navigate to the course files folder.
SAS Enterprise Guide: In the Servers list, expand Servers  Local  Files,
and then navigate to the course files folder.
2. Double-click the cre8data.sas file to open the program.
3. Find the %LET statement. As directed by your instructor, provide the path
to your course files folder.
4. Run the program and verify that a report that lists 13 tables is created.

21
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-12 Lesson 1 Introduction

1.02 Activity
1. Open the libname.sas program in the course files folder and run it.
2. Navigate to the SASHELP library and open the CARS table. Browse
the columns and values in the table. This table is used in many
of the sample programs.
3. Navigate to the MC1 library and open the STORM_FINAL table.
This table includes one row per storm recorded from 1980 to 2017.
This table is used in many of the demos.
4. Open and browse the CUSTOMERS table in the MC1 library. This table
is used in many of the practices.

Be sure to run the libname.sas program


each time the SAS session is restarted.
23
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1.3 Solutions 1-13

1.3 Solutions
Solutions to Activities and Questions

1.01 Activity – Correct Answer

Confirm that
these 13 SAS
tables were
created.

22
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
1-14 Lesson 1 Introduction

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
Lesson 2 SAS® Macro Facility

2.1 Program Flow .......................................................................................................................... 2-3

2.2 Creating and Using Macro Variables .................................................................................. 2-16


Practice ................................................................................................................................. 2-39

2.3 Solutions ................................................................................................................................ 2-40


Solutions to Practices ........................................................................................................... 2-40

Solutions to Activities and Questions ................................................................................... 2-42


2-2 Lesson 2 SAS® Macro Facility

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-3

2.1 Program Flow

SAS Programming Languages


DATA step language data manipulation

PROC SQL data manipulation and reporting

SAS procedures data analysis and reporting

Compile Execute
SAS program

3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

SAS Programming Languages


DATA step language data manipulation

PROC SQL data manipulation and reporting

SAS procedures data analysis and reporting

SAS Macro
SAS macro Language
language generate SAS program code

Macro
Facility
Text SAS program
4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-4 Lesson 2 SAS® Macro Facility

Conceptual SAS Program Flow

SAS code Compiler

Macro Macro
code Processor

5
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Conceptual SAS Program Flow


Word Scanner
Pulls text Transforms Sends
from the text to tokens for
input stack tokens processing

Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
SAS program run;

6
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-5

Token Types
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

A program is
separated into name number
components called
tokens. There are
four types of
tokens. special literal
7
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Name Tokens
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

• maximum of 32 characters
name • must begin with a letter or
underscore
• can include only letters,
digits, and underscores

8
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Formats and informats (COMMA11.2, $5.) are considered name tokens. The period and dollar sign
are treated as part of the name token.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-6 Lesson 2 SAS® Macro Facility

Number Tokens
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

• integer or floating-point values


• digits, decimal point, leading sign, number
and exponent indicator (e or E)
• date/time/datetime constants:
'29APR2019'd
'14:05:32.1't
'29APR2019 14:05:32.1'dt
9
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Literal Tokens
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

• string of any characters enclosed in


single or double quotation marks
• maximum of 32,767 characters
• treated as a single unit
literal
10
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-7

Special Tokens
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

• any character or group of


characters that have special
meaning to SAS
special • examples:
*/+-;().&%
11
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Token Delimiters
Input Stack
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
run;

A token ends when


Blanks separate
a new type of
tokens.
token begins.

12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-8 Lesson 2 SAS® Macro Facility

2.01 Activity
How many tokens are in each statement?

title "Trucks with Horsepower > 250"; __


proc print data=sashelp.cars; __
var Make Model MSRP Horsepower; __
where Type="Truck" and Horsepower>250; __
run; __

13
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenization Why do I need to


know about
tokenization?
Compiler

Word It can help you


Scanner
understand the
timing of how SAS
and macro language
title "Trucks with Horsepower > 250"; elements are
Input proc print data=sashelp.cars;
var Make Model MSRP Horsepower; processed.
Stack where Type="Truck" and Horsepower>250;
run;

15
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-9

Tokenization
title

Compiler

Word The word scanner reads


Scanner individual tokens and passes
them on to the compiler.
name title

"Trucks with Horsepower > 250";


Input proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
Stack where Type="Truck" and Horsepower>250;
run;

16
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenization
title "Trucks with Horsepower > 250"

Compiler

literal start "


name Trucks
Word name with
Scanner name Horsepower
special >
number 250
literal end "
;
Input proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
Stack where Type="Truck" and Horsepower>250;
run;

17
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

When a literal token is enclosed in double quotation marks, the word scanner examines
the individual tokens within the string before passing the text on to the compiler. If a literal token
is enclosed in single quotations marks, the word scanner does not tokenize the string.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-10 Lesson 2 SAS® Macro Facility

Tokenization
title "Trucks with Horsepower > 250";

Compiler
Execute

Global statements are


executed when a
Word
Scanner semicolon is reached.

special ;

proc print data=sashelp.cars;


Input var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
Stack run;

18
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenization

Compiler

name proc
name print
Word name data
Scanner special =
name sashelp
special .

cars;
Input var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
Stack run;

19
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-11

Tokenization
proc print data=sashelp.cars;

Compiler

name var
name Make
Word name Model
Scanner name MSRP
name Horsepower
special ;

where Type="Truck" and Horsepower>250;


Input run;
Stack

20
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenization
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
Compiler where Type="Truck" and Horsepower>250; Execute
run;

Steps are executed when


Word a step boundary is found.
Scanner

Input
Stack

21
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-12 Lesson 2 SAS® Macro Facility

Discussion
Why do you think unbalanced
quotation marks cause problems
when they are submitted in a
SAS program?

Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Triggers

&name-token The combination of a %


or & special token
immediately followed by
%name-token
a name token is called a
macro trigger.

23
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-13

Macro Triggers

• %PUT is a macro statement that


%PUT text; writes text to the log.
• Text is not quoted.
• Use NOTE:, WARNING:, or ERROR:
prefix to color the log message.

%put NOTE: This is a great program!;

73 %put NOTE: This is a great program!;


NOTE: This is a great program!

24
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenizing Code with Macro Triggers

Compiler

Word Macro triggers


Scanner modify word
scanner behavior.

%put NOTE: This is a great program!;


Input
Stack

25
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-14 Lesson 2 SAS® Macro Facility

Tokenizing Code with Macro Triggers


%put

Compiler

Macro Processor

Word
Scanner
special %
name put

NOTE: This is a great program!;


Input
Stack

26
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Tokenizing Code with Macro Triggers


%put NOTE: This is a great
program!;
Compiler

Macro Processor

Word log
Scanner NOTE: This is a great program!

Input
Stack

27
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.1 Program Flow 2-15

Processing Overview
Execute
Code Processing

PDV Data Tables

Code Generation
Word Macro Macro
Scanner Processor Catalogs
%put NOTE: This is a great program!
title "Trucks with Horsepower > 250";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower; Input Symbol
where Type="Truck" and

run;
Horsepower>250; Stack Tables
Tokenization Macro Facility

28
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.02 Activity
1. Name the possible stages involved in the SAS program flow.

2. What are the four types of tokens recognized by the word scanner?

3. How does the word scanner detect the end of a token?

4. What token sequence triggers interaction with the macro processor


during the tokenization process?

5. What macro statement writes a message to the log?

29
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-16 Lesson 2 SAS® Macro Facility

2.2 Creating and Using Macro Variables

Developing a Macro Application

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

Using macro
variables is an
effective way to make
your programs more
flexible.

33
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Variables

title " s with Horsepower > ";


proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type=" " and Horsepower> ;
run;
Macro variables
Truck 250 store text that can
be used anywhere in
Sedan 150 our SAS programs.

SUV 200

34
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.SAS

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-17

Macro Variables

Macro variables
each have a name
and value that are
stored in a memory- Global Symbol Table
based symbol table. Name Value

35
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables with %LET

%LET name=value; %let type=Truck;


%let hp=250;

Macro variable names:


• follow SAS naming rules
• are stored as uppercase Global Symbol Table
• are not case sensitive
Name Value
TYPE Truck
HP 250

36
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

If the %LET statement includes macro triggers for either name or value, the macro references are
processed before the macro variable name and value are assigned.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-18 Lesson 2 SAS® Macro Facility

Creating Macro Variables with %LET

%LET name=value; %let type=Truck;


%let hp=250;
• Case is preserved.
• Leading and trailing blanks are
removed.
• It stores 0 to 65,534 (64K) Global Symbol Table
characters. Name Value
• The length is dynamically set TYPE Truck
each time a value is assigned.
HP 250

37
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Truck
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=;
%let sum=3+4; Macro variables
%let varlist=Make Model Type; don't have a type of
character or
numeric. All values
are stored as text.

38
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-19

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Sports
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=;
%let sum=3+4;
%let varlist=Make Model Type;

Leading and trailing spaces are


removed. The value of an existing
macro variable is replaced.
39
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Sports
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=; ORIGIN " Europe "
%let sum=3+4;
%let varlist=Make Model Type;

Quotation marks are stored as


part of the value.

40
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-20 Lesson 2 SAS® Macro Facility

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Sports
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=; ORIGIN " Europe "
%let sum=3+4; VALUE
%let varlist=Make Model Type;

A null value is stored.

41
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Sports
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=; ORIGIN " Europe "
%let sum=3+4; VALUE
%let varlist=Make Model Type; SUM 3+4

Mathematical expressions
are not evaluated.

42
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-21

Creating Macro Variables with %LET

Global Symbol Table


%let type=Truck; Name Value
%let hp=250; TYPE Sports
%let type= Sports ; HP 250
%let origin=" Europe ";
%let value=; ORIGIN " Europe "
%let sum=3+4; VALUE
%let varlist=Make Model Type; SUM 3+4
VARLIST Make Model Type

The variable list is stored


as a text string.

43
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.03 Activity
What would be stored as the value of Mylib?

%let mylib=libname mc1 "s:/workshop";

Global Symbol Table


Name Value
MYLIB

44
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-22 Lesson 2 SAS® Macro Facility

Creating Macro Variables with %LET

Global Symbol Table


Name Value
Macro variables TYPE Sports
remain in the global HP 250
symbol table for the
ORIGIN " EUROPE "
duration of the SAS
session. VALUE
SUM 3+4
VARLIST Make Model Type

46
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Deleting Macro Variables


• explicitly deletes variables from the
%SYMDEL list of variable names; global symbol table
• accepts a list of macro variable names
• releases memory back to the system

Global Symbol Table


Name Value
TYPE Sports
%symdel type hp;
HP 250
ORIGIN " EUROPE "
VALUE
SUM 3+4
VARLIST Make Model Type
47
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-23

Creating Macro Variables with %LET

Global Symbol Table


Name Value
When the SAS ORIGIN " EUROPE "
session ends, the VALUE
global symbol table is SUM 3+4
deleted. VARLIST Make Model Type

48
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables

&name substitutes the macro variable


value into the program
Global Symbol Table
Name Value
TYPE Truck
%let type=Truck; HP 250
%let hp=250;

proc print data=sashelp.cars;


var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;

49
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-24 Lesson 2 SAS® Macro Facility

Resolving Macro Variables

Compiler

Macro Processor

Word
Scanner

%let type=Truck; Global Symbol Table


Input %let hp=250; Name Value
Stack proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;
50
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables

Compiler

Macro Processor

Word
Scanner
special %
name let

type=Truck; Global Symbol Table


Input %let hp=250; Name Value
Stack proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;
51
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-25

Resolving Macro Variables


%let type=Truck;
%let hp=250;
Compiler

Macro Processor

Word
Scanner

proc print data=sashelp.cars; Global Symbol Table


Input var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp; Name Value
Stack run; TYPE Truck
HP 250
52
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables


proc print data=sashelp.cars; &type
var Make Model MSRP Horsepower;
where Type=
Compiler

Macro Processor

Word
Scanner "
literal start
special &
name type

" and Horsepower>&hp; Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
53
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-26 Lesson 2 SAS® Macro Facility

Resolving Macro Variables


proc print data=sashelp.cars; &type
var Make Model MSRP Horsepower;
where Type="
Compiler

Macro Processor

Word
Scanner "
literal start

Truck" and Horsepower>&hp; Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
54
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables


proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck"
Compiler

Macro Processor

Word
Scanner "
literal start
name Truck
literal end "

and Horsepower>&hp; Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
55
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-27

Resolving Macro Variables


proc print data=sashelp.cars; &hp
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>
Compiler

Macro Processor

Word
Scanner
special &
name hp

; Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
56
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables


proc print data=sashelp.cars; &hp
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>
Compiler

Macro Processor

Word
Scanner

250; Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
57
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-28 Lesson 2 SAS® Macro Facility

Resolving Macro Variables


proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="Truck" and Horsepower>250;
Compiler

Macro Processor

Word
Scanner
number 250
special ;

Global Symbol Table


Input run;
Name Value
Stack
TYPE Truck
HP 250
58
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Resolving Macro Variables


proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
Compiler where Type="Truck" and Horsepower>250; Execute
run;

Word
Scanner

Global Symbol Table


Input
Name Value
Stack
TYPE Truck
HP 250
59
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-29

Resolving Macro Variables


Why is &type in
quotation
%let type=Truck; marks and &hp
%let hp=250; is not?
title1 "Car Type: &type";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;

60
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Resolving Macro Variables


The compiled
statement must
%let type=Truck; include proper
%let hp=250; syntax.
title1 "Car Type: &type";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;

where Type="Truck" and Horsepower>250;


character numeric
expression expression
61
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-30 Lesson 2 SAS® Macro Facility

Resolving Macro Variables

Typically, macro variable


%let type=Truck; values don't include
%let hp=250; quotation marks.
title "Car Type: &type";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;

Use double quotation marks


where necessary when
resolving macro variables.
62
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Troubleshooting Macro Variable References

OPTIONS SYMBOLGEN|NOSYMBOLGEN; The SYMBOLGEN


option writes
options symbolgen; information to the
%let type=Truck; log when macro
%let hp=250; variable references
title1 "Car Type: &type"; resolve.
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and Horsepower>&hp;
run;
80 where Type="&type" and Horsepower>&hp;
SYMBOLGEN: Macro variable TYPE resolves to Truck
SYMBOLGEN: Macro variable HP resolves to 250
63
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-31

2.04 Activity
Open m102a04.sas from the activities folder and perform the following tasks:
1. Notice that the program includes two TITLE statements, each referencing
a macro variable.
2. At the top of the program, turn on the SYMBOLGEN option.
At the bottom of the program, turn off SYMBOLGEN.
options symbolgen; options nosymbolgen;

3. Run the program and review the log and results. What is printed as the
second title?
4. In the TITLE2 statement, change the single quotation marks to double
quotation marks and run the program again. How do the results
and the log differ?
64
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Quotation Marks in Literal Tokens

title1 "Car Type: &type";


title2 'Car&Power Report';

Macro triggers in
Macro triggers in
single quotation
double quotation
marks are treated as
marks are sent to the
regular text and are
macro processor.
not resolved.

66
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-32 Lesson 2 SAS® Macro Facility

Delimiting Macro Variable References

...
%let type=Truck;
title "&types with Horsepower > &hp";
...
What happens if a
macro variable
reference is
concatenated with
trailing text?

desired results

67
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Delimiting Macro Variable References

...
%let type=Truck;
title "&types with Horsepower > &hp";
...
Global Symbol Table
Name Value
TYPES is not found. TYPE Truck
HP 250

74 %let type=Truck;
75 %let hp=250;
WARNING: Apparent symbolic reference TYPES not resolved.
SYMBOLGEN: Macro variable HP resolves to 250
76 title "&types with Horsepower > &hp";
68
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-33

Delimiting Macro Variable References

...
%let type=Truck;
title "&type.s with Horsepower > &hp";
...
Use a period to delimit the macro
variable name from the text.

title "Trucks with Horsepower > 250";

The period does not appear


in the resolved text.

69
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.05 Activity
Open m102a05.sas from the activities folder and perform the following tasks:
1. Modify the TITLE statement reference to &type by adding a period before
the 's'.
2. Replace the hardcoded text sashelp in the FOOTNOTE and PROC
statements with a reference to the Lib macro variable (&lib).
footnote "Data Source: &lib.CARS";
proc print data=&lib.cars;

3. Run the program and examine the log and the error statements.
Why did the program fail to run?

70
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-34 Lesson 2 SAS® Macro Facility

Delimiting Macro Variable References

footnote "Data Source: &lib..CARS";


proc print data=&lib..cars;

The first period is a


Use two periods delimiter and is removed
between the macro when &lib resolves. The
variable and table name. second period remains
as text.

72
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Displaying Macro Variables


%PUT _USER_; lists all macro variables created by
the user or application (SAS Studio
or SAS Enterprise Guide)

74 %put _user_;
%PUT is a simple
...
GLOBAL CLIENTMACHINE L12345 way to view macro
GLOBAL HP 250 variable names and
GLOBAL LIB sashelp values in the log.
GLOBAL PATH s:/workshop
GLOBAL SYSUSERNAME John Smith
GLOBAL TYPE Truck
GLOBAL _CLIENTAPP 'SAS Studio'
GLOBAL _CLIENTAPPVERSION 3.8
...
73
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-35

Displaying Macro Variables


%PUT &=name;

73 %put &=type;
TYPE=Truck

%PUT <text> &name <text>;

75 %put The value of Horsepower is &hp;


The value of Horsepower is 250

74
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.06 Activity
1. Open a new program and submit a %PUT statement to list all
user-defined macro variables.
2. Find the Path macro variable in the log. Path was created with
a %LET statement in the libname.sas program, and it stores the
location of the course files. Submit the following statements to
view the value of Path. How are the messages in the log different?

%put NOTE: &=path;


%put ERROR- Course files are in &path;

75
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-36 Lesson 2 SAS® Macro Facility

Automatic Macro Variables


%PUT _AUTOMATIC_; lists all automatic macro
variables created by SAS

Several useful
73 %put _automatic_;
...
automatic macro
AUTOMATIC SYSDATE 01NOV19 variables are defined
AUTOMATIC SYSDATE9 01NOV2019 when you start a SAS
AUTOMATIC SYSDAY Friday
session.
AUTOMATIC SYSENCODING wlatin1
AUTOMATIC SYSUSERID msmith
AUTOMATIC SYSVER 9.4
...

77
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Automatic macro variables are available throughout the SAS session. Values can be updated by
SAS and, in some cases, can be assigned values by the user.

2.07 Activity
Open m102a07.sas from the activities folder and perform the following tasks:
1. Review the program and notice that the DATA step creates a table named
Avg_MPG. Highlight the DATA step and %PUT statement, and run the
selected code. Review the log to see all automatic macro variables stored
in the global symbol table.
2. Identify the macro variables that store the date and the last table created.
3. Use macro variable references in the TITLE2 and FOOTNOTE statements
to insert the table name and date into the program.
title2 "Data Source: <table>";
footnote "Created on <date>";

78
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-37

Selected Automatic Macro Variables


Global Symbol Table
Name Description
SYSDAY Day of the week on which the SAS session was initiated
SYSDATE9 Date on which the SAS session was initiated
SYSTIME Time at which the SAS session was initiated
SYSHOSTNAME Name of the machine on which the SAS session is executing
SYSLAST Name of the last table created
SYSUSERID User ID under which the SAS session is executing
SYSSCP Operating system abbreviated name
SYSSCPL Operating system detail
SYSVLONG SAS version and maintenance release
Returns a 0 if a step completes successfully and without
SYSERR
warning messages, returns an error code otherwise
80
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Updating Macro Variables


%let type=Truck;
%let hp=250;
title "&type.s with Horsepower > &hp";
footnote "Report Created on &sysday, &sysdate";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and
Horsepower>&hp; What must be modified in
run; the program to generate a
list of SUVs with
horsepower greater than
300, and then print the
date in the footnote?

81
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m102d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-38 Lesson 2 SAS® Macro Facility

Updating Macro Variables


%let type=SUV;
%let hp=300;
title "&type.s with Horsepower > &hp";
footnote "Report Created on &sysday, &sysdate";
proc print data=sashelp.cars;
var Make Model MSRP Horsepower;
where Type="&type" and
Horsepower>&hp;
run;

Simply update the


%LET statements!

82
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.2 Creating and Using Macro Variables 2-39

Practice

Level 1

1. Defining and Using Macro Variables for Substitution


a. Open m102p01.sas from the practices folder. Submit the program and review the log and
output. Verify that the title is US Customers Ages 18 to 24 and that 127 rows were read.
b. Create a macro variable named Country and assign the value US. Replace all occurrences
of US with references to Country. Submit the program and verify that the results are the
same as step a.
c. Modify the value of Country to FR. Resubmit the program and verify that the title
is FR Customers ages 18 to 24 and that 46 rows were read.
d. Create additional macro variables, Age1 and Age2. Set Age1 to 25, Age2 to 34, and
Country to AU. Replace all occurrences of 18 and 24 with references to Age1 and Age2.
Submit the program.
• What is the report title?
• How many observations were read?

Level 2

2. Using Macro Variable References with Delimiters

a. Open m102p02.sas from the practices folder. Submit the program and review the results.
Verify that the report contains 17 rows.
b. Create macro variables Lib, Dsn, and Var and assign the values mc1, newhires, and
Employee respectively. Modify the program so that every occurrence of mc1, newhires,
and Employee are replaced by references to the corresponding macro variable. Submit
the program.

Note: Be sure to include the ‘s’ in Employees as part of the title text.
• What is the report title?
• How many rows are in the report?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-40 Lesson 2 SAS® Macro Facility

2.3 Solutions
Solutions to Practices
1. Defining and Using Macro Variables for Substitution
/* Part b. */
%let Country=US;
title "&Country Customers Ages 18 to 24";
proc print data=mc1.customers;
var Name Age Type;
where Country = "&Country"
and Age between 18 and 24;
run;
title;

/* Part c. */
%let Country=FR;
title "&Country Customers Ages 18 to 24";
proc print data=mc1.customers;
var Name Age Type;
where Country = "&Country"
and Age between 18 and 24;
run;
title;

/* Part d. */
%let Country=AU;
%let age1=25;
%let age2=34;
title "&Country Customers Ages &age1 to &age2";
proc print data=mc1.customers;
var Name Age Type;
where Country = "&Country"
and Age between &age1 and &age2;
run;
title;
What is the report title? AU Customers Ages 25 to 34
How many observations were read? 10

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.3 Solutions 2-41

2. Using Macro Variable References with Delimiters


%let lib=mc1;
%let dsn=newhires;
%let var=Employee;
title "Listing of All &var.s From &lib..&dsn";
proc print data=&lib..&dsn;
var &var._Name &var._ID;
run;
title;
What is the report title? All Employees from mc1.newhires
How many rows are in the report? 17

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-42 Lesson 2 SAS® Macro Facility

Solutions to Activities and Questions

2.01 Activity – Correct Answer


How many tokens are in each statement?

title "Trucks with Horsepower > 250"; __


3
proc print data=sashelp.cars; __
8
var Make Model MSRP Horsepower; __
6
where Type="Truck" and Horsepower>250; __
9
run; __
2

14
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.02 Activity – Correct Answer


1. Name the possible stages involved in the SAS program flow.
Input stack, word scanner, compiler, and macro processor
2. What are the four types of tokens recognized by the word scanner?
Name, number, literal, and special
3. How does the word scanner detect the end of a token?
A space or the beginning of a new type of token
4. What token sequence triggers interaction with the macro processor
during the tokenization process?
&name or %name
5. What macro statement writes a message to the log?
%PUT
30
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.3 Solutions 2-43

2.03 Activity – Correct Answer


What would be stored as the value of Mylib?

%let mylib=libname mc1 "s:/workshop";

Global Symbol Table The semicolon is treated as


Name Value the conclusion of the %LET
MYLIB libname mc1 "s:/workshop" statement and is not stored
in the macro variable value.

45
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.04 Activity – Correct Answer


3. What is printed as the second title?
SYMBOLGEN: Macro variable TYPE resolves to Truck
76 title1 "Car Type: &type";
77 title2 'Horsepower > &hp';
The macro variable does not resolve
with single quotation marks.
4. How do the results and the log differ?
SYMBOLGEN: Macro variable TYPE resolves to Truck
76 title1 "Car Type: &type";
SYMBOLGEN: Macro variable HP resolves to 250
77 title2 "Horsepower > &hp";
The macro variable resolves
with double quotation marks.
65
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-44 Lesson 2 SAS® Macro Facility

2.05 Activity – Correct Answer


3. Run the program and examine the log and the error statements.
Why did the program fail to run?

The period between &lib and cars was interpreted as a macro delimiter,
so the table name incorrectly resolved to SASHELPCARS.

80 proc print data=&lib.cars;


SYMBOLGEN: Macro variable LIB resolves to SASHELP
ERROR: File WORK.SASHELPCARS.DATA does not exist.

71
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

2.06 Activity – Correct Answer


How are the messages in the log different?

The colon includes the word NOTE and prints


the message in the default color for notes.

73 %put NOTE: &=path; The path for


NOTE: PATH=s:/workshop your course
74 %put ERROR- Course files are in &path; files might
Course files are in s:/workshop differ.

The hyphen changes the color of the


text but does not print the prefix.

76
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

The default colors for notes, errors, and warnings might be different in your environment.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2.3 Solutions 2-45

2.07 Activity – Correct Answer


3. Use macro variable references in the TITLE2 and FOOTNOTE statements
to insert the table name and date into the program.
title2 "Data Source: &syslast";
footnote "Created on &sysdate9";

79
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
2-46 Lesson 2 SAS® Macro Facility

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
Lesson 3 Storing and Processing
Text
3.1 Macro Functions ..................................................................................................................... 3-3
Demonstration: Macro Functions ......................................................................................... 3-19
Practice ................................................................................................................................. 3-21

3.2 Using SQL to Create Macro Variables ................................................................................ 3-23


Demonstration: Creating Macro Variables with a PROC SQL Query .................................. 3-28
Practice ................................................................................................................................. 3-32

3.3 Using the DATA Step to Create Macro Variables ............................................................... 3-34
Demonstration: Creating Macro Variables with the DATA Step ........................................... 3-48
Practice ................................................................................................................................. 3-52

3.4 Indirect References to Macro Variables ............................................................................. 3-53


Demonstration: Indirect References to Macro Variables ..................................................... 3-61
Practice ................................................................................................................................. 3-63

3.5 Solutions ................................................................................................................................ 3-64


Solutions to Practices ........................................................................................................... 3-64
Solutions to Activities and Questions ................................................................................... 3-72
3-2 Lesson 3 Storing and Processing Text

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-3

3.1 Macro Functions

SAS Functions
data cars_subset;
set sashelp.cars; SAS functions
where upcase(DriveTrain)="FRONT";
run; manipulate data
values during the
Sashelp.cars (partial) execution phase.
Make Model DriveTrain
Acura MDX ... All
Acura TSX 4dr ... Front
Acura RSX Type S 2dr ... Front

3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Processing Text with Macro Functions

data cars_subset;
set sashelp.cars;
where upcase(DriveTrain)="FRONT";
run;

title "Front Wheel Drive Cars";


footnote "Listing from CARS_SUBSET Table";
proc print data=&syslast;
run; Can a single macro
variable supply the
value Front in
different cases?

4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-4 Lesson 3 Storing and Processing Text

Processing Text with Macro Functions

%let dt=front;
data cars_subset;
set sashelp.cars; UPCASE
where upcase(DriveTrain)="&dt";
run;
PROPCASE
title "&dt Wheel Drive Cars";
footnote "Listing from CARS_SUBSET Table";
proc print data=&syslast; Can functions
run; manipulate
program text?

5
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d01.sas

Selected Macro Functions

%UPCASE Converts values to uppercase.


%SUBSTR Extracts a substring from
a character string. Macro functions
manipulate text in a
%SCAN Extracts a word from program rather
a character string. than data values.
%SYSFUNC Executes SAS functions.

%SYSEVALF Performs arithmetic and


evaluates logical expressions.

6
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-5

Regular and Macro Functions

Compiler

Macro Processor

Word
Scanner

%let dt=front; Global Symbol Table


Input data cars_subset;
Stack set sashelp.cars; Name Value
where upcase(DriveTrain)="%upcase(&dt)";
run;

7
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Regular and Macro Functions


data cars_subset; %upcase(&dt)
set sashelp.cars;
where upcase(DriveTrain)=
Compiler

Macro Processor

Word
literal start "
Scanner special %
name upcase
...

"; Global Symbol Table


Input run;
Stack Name Value
DT front

8
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-6 Lesson 3 Storing and Processing Text

Regular and Macro Functions


data cars_subset; %upcase(front)
set sashelp.cars;
where upcase(DriveTrain)=
Compiler

Macro Processor

Word
literal start "
Scanner

"; Global Symbol Table


Input run;
Stack Name Value
DT front

9
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Regular and Macro Functions


data cars_subset; %upcase(front)
set sashelp.cars;
where upcase(DriveTrain)=
Compiler

Macro Processor

Word
literal start "
Scanner

FRONT"; Global Symbol Table


Input run;
Stack Name Value
DT front

10
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-7

Regular and Macro Functions


data cars_subset;
set sashelp.cars;
where upcase(DriveTrain)="FRONT";
Compiler

Macro Processor

Word
literal start "
Scanner name FRONT
literal end "
special ;

run; Global Symbol Table


Input
Stack Name Value
DT front

11
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Regular and Macro Functions


data cars_subset;
set sashelp.cars;
where upcase(DriveTrain)="FRONT";
Compiler run; Execute
UPCASE processes the
data values during the
Word execution phase.
Scanner

Input
Stack

12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-8 Lesson 3 Storing and Processing Text

Processing Text with Macro Functions


%let dt=front;
...
where upcase(DriveTrain)=upcase("&dt");
Both of these
expressions work.
What is the
difference
%let dt=front; between using
...
where upcase(DriveTrain)="%upcase(&dt)"; UPCASE and
%UPCASE?

13
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Processing Text with Macro Functions


%let dt=front;
...
where upcase(DriveTrain)=upcase("&dt");

resulting statement

where upcase(DriveTrain)=upcase("front");

The UPCASE function is evaluated in the


execution phase. It executes for each iteration
of the DATA step.

14
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-9

Processing Text with Macro Functions


%let dt=front;
...
where upcase(DriveTrain)="%upcase(&dt)";

resulting statement
The %UPCASE function
where upcase(DriveTrain)="FRONT"; converts front to FRONT once
in the macro processor before
the statement is compiled.

15
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.01 Activity
Open m103a01.sas from the activities folder and perform the following
tasks:
1. Examine the TITLE statement. What text will appear as the title? Run
the program and view the results.
2. Add % before the UPCASE function in the TITLE statement. Run the
program. What text appears as the title?

16
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103a01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-10 Lesson 3 Storing and Processing Text

Processing Text with Macro Functions

Global Symbol Table Which macro


Name Value functions could be
SYSLAST WORK.CARS_SUBSET used to provide the
table name in the
footnote?

footnote "Listing from CARS_SUBSET Table";

18
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Processing Text with Macro Functions

Global Symbol Table


Name Value
SYSLAST WORK.CARS_SUBSET
%SCAN returns the
second word.

footnote "Listing from %scan(&syslast,2) Table";

footnote "Listing from %substr(&syslast,6) Table";

%SUBSTR returns all characters


starting at position 6.
19
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-11

Processing Text with Macro Functions


Expression Value
%upcase(front) FRONT Because all macro
functions process
%let dt=front; FRONT text, arguments are
%upcase(&dt) not quoted.
%scan(sashelp.cars, 2, .) cars
%substr(CA123, 1, 2) CA
%substr("CA123", 1, 2) "C

If quotation marks are included,


they are treated as part of the value.
20
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Processing Text with Macro Functions

• This enables regular functions to


%SYSFUNC(function(argument(s))<,format>)
be used by the macro processor.
• An optional argument can
provide a format that is applied
to the result.

21
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-12 Lesson 3 Storing and Processing Text

Processing Text with Macro Functions

%let dt=front;
...

title "&dt Wheel Drive Cars";


footnote "Listing from %scan(&syslast,2) Table";
proc print data=&syslast;
run;
How can I
substitute Front
in proper case
for the title?

22
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d01.sas

3.02 Activity
Open m103a02.sas from the activities folder and perform the following tasks:
1. Run the program and examine the output and the log. SAS does not have
a %PROPCASE macro function, so it does not successfully resolve and the
title is incorrect.
2. Modify the TITLE statement to use the %SYSFUNC macro function in
combination with the PROPCASE function.
title "%sysfunc(propcase(&dt)) Wheel Drive Cars";

3. Run the program and confirm that the title is correct.

23
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-13

Evaluate Arithmetic Expressions

%let season=2019;
%let nextseason=&season+1; How can I ask the
macro processor to
evaluate arithmetic
Global Symbol Table expressions?
Name Value
SEASON 2019
NEXTSEASON 2019+1

25
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Evaluate Arithmetic Expressions

%let season=2019;
%let nextseason=%sysevalf(&season+1);
Use the
%SYSEVALF
macro function!
Global Symbol Table
Name Value
evaluates an arithmetic
SEASON 2019 or logical expression
NEXTSEASON 2020 and returns a text value

26
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%SYSEVALF performs precise numeric calculations. %EVAL is a legacy macro function that performs
simple integer arithmetic.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-14 Lesson 3 Storing and Processing Text

Controlling Precision in %SYSEVALF Results

%SYSEVALF(expression<,conversion-type>)

Expression Value
%sysevalf(10/3.5) 2.85714285714285
%sysevalf(10/3.5,ceil) 3
%sysevalf(10/3.5,floor) 2
%sysevalf(10/3.5,integer) 2
%sysevalf(1.2<3,boolean) 1

27
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Using Special Characters


%let clear=title;footnote;; Is the quotation mark the start of
a literal string or an apostrophe?
Are the semicolons part of the
macro variable value or the end
of the %LET statement? %let title=Joan's Report;

Are these special


characters SAS syntax %let dept=R&D;
or part of the text
value?
Is this a macro variable reference
or a regular ampersand?
28
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-15

Using Special Characters

%let clear=title;footnote;;
%put &=clear;

Why doesn’t this


The first semicolon is program cause a
interpreted as the end syntax error?
of the %LET statement.

73 %let clear=title;footnote;;
74 %put &=clear;
CLEAR=title

30
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Using Special Characters

%STR(character-string) %STR masks all special


characters except % and & so
that they are treated as regular
text by the macro processor.

Global Symbol Table


Name Value
%let clear=%str(title;footnote;);
CLEAR title;footnote;

31
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-16 Lesson 3 Storing and Processing Text

Using Special Characters


Single characters normally
encountered in pairs, such
as parentheses and double
or single quotation marks,
%let title=%str(Joan%'s Report); can be problematic.

Global Symbol Table


Name Value Use % to designate
that the next
TITLE Joan’s Report
character is text.

32
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Using Special Characters


%let location=Winston-Salem NC;
%let city=%scan(&location, 1, <delimiters> );
%put &=city;

The optional third If macro function


argument in %SCAN arguments are not
can specify delimiters. quoted, how can I
specify a space as the
third argument?

33
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-17

Using Special Characters


%let location=Winston-Salem NC; Use %STR to mask
%let city=%scan(&location, 1, %str( ));
%put &=city; special symbols as
arguments.

73 %let location=Winston-Salem NC;


74 %let city=%scan(&location, 1, %str( ));
75 %put &=city;
CITY=Winston-Salem

34
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.03 Activity
Open m103a03.sas from the activities folder and perform the following tasks:
1. The intent of the %SCAN function is to return the city from the Location
macro variable using only the comma as a delimiter. Run the program and
examine the log. Why does the program fail?
2. Use %STR to mask the comma in the appropriate places so that the value
of the City macro variable is Buenos Aires.

35
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-18 Lesson 3 Storing and Processing Text

Using Special Characters

%STR still attempts to


%let dept=%str(R&D);
resolve macro variable
references.

76 %put &=dept;
DEPT=RDenmark
Global Symbol Table
Name Value
D Denmark
DEPT R&D

38
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Using Special Characters

%NRSTR(character-string) %NRSTR masks all special


characters including % and &
so that they are treated as
regular text.

%let dept=%nrstr(R&D);
Global Symbol Table
Name Value
The & is treated as D Denmark
regular text rather DEPT R&D
than a macro trigger.

39
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Several macro functions have an alternative “Q” function that manipulates text and returns a result
that masks special characters and mnemonic operators:
• %QUPCASE
• %QSCAN
• %QSUBSTR
• %QSYSFUNC

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-19

Macro Functions

Scenario
This demonstration illustrates using macro statements and macro functions to create and populate
macro variables.

Files
• m103d02.sas
• mc1.storm_final

Syntax

%SYSEVALF(argument)
%SYSFUNC(function(argument(s))<,format>)
%STR(argument)

Notes
• Macro functions can be used to manipulate the text in a SAS program.
• The %SYSFUNC macro function enables the macro processor to execute most DATA step
functions. The first argument is a DATA step function, and the optional second argument is a format
to display the value returned by the first argument.

Demo
1. Open m103d02.sas from the demos folder and review the program.
a. Two macro variables, Year and WindM (miles per hour), are created and assigned values.
b. The values of these macro variables are used in the TITLE and WHERE statements.
c. Two automatic macro variables, Sysdate9 and Systime, are used in the FOOTNOTE
statement to print the day and time the SAS session began.
d. Run the program and confirm that six rows are printed. Verify that the macro variable values
are substituted in the title and footnote.
%let year=2015;
%let windm=150;

title1 "&year Storms";


title2 "Winds Exceeding &windm M/H";
footnote "Report Created on &sysdate9 at &systime";
proc print data=mc1.storm_final noobs;
where Season=&year and MaxWindMPH>=&windm;
run;
title;footnote;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-20 Lesson 3 Storing and Processing Text

2. Modify the TITLE2 statement to include the WindM value converted to kilometers per hour. This
value can be calculated by multiplying the value of the WindM macro variable by 1.61. The
%SYSEVALF macro function must be used to perform the calculation and insert the resulting
value as text. Run the program and confirm that six rows are returned and that the title is correct.
title2 "Winds Exceeding &windm M/H or %sysevalf(&windm*1.61) KM/H";
3. Notice that the date and time in the footnote represent when the SAS session started rather than
the current date and time. Modify the FOOTNOTE statement to use %SYSFUNC in combination
with the TODAY() and TIME() functions to insert the date and time at which the program executes.
Use the second argument in %SYSFUNC to apply an appropriate format. Run the program and
confirm that the date and time in the footnote are current.
footnote "Report Created on %sysfunc(today(), date9.) at
%sysfunc(time(), timeampm.)";
4. The FOOTNOTE statement can be stored in a macro variable so that it can be easily reused in
other parts of the program. Use a %LET statement to assign the full FOOTNOTE statement to a
macro variable named dtfoot. Surround the FOOTNOTE statement with the %STR function to
mask special characters but still resolve macro triggers.
%let dtfoot=%str(footnote "Report Created on
%sysfunc(today(),date9.) at %sysfunc(time(),timeampm.)";);
5. Replace the previous FOOTNOTE statement with the &dtfoot macro variable reference. Run the
program and confirm the footnote is correct.
Note: A semicolon is not needed after &dtfoot because it is included as part of the macro
variable value. It might cause the color coding in your editor to appear as if there is a
syntax error in the PROC PRINT step.
%let year=2015;
%let windM=150;
%let dtfoot=%str(footnote "Report Created on %sysfunc(today(),
date9.) at %sysfunc(time(), timeampm.)";);

title1 "&year Storms";


title2 "Winds Exceeding &windm M/H or %sysevalf(&windm*1.61) KM/H";
&dtfoot
proc print data=mc1.storm_final noobs;
where MaxWindMPH>=&windm and Season=&year;
run;
title;footnote;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.1 Macro Functions 3-21

Practice

Level 1
1. Using the %UPCASE and %SCAN Functions
a. Open m103p01.sas from the practices folder. Add a %LET statement to convert the value of
FullName to uppercase and assign the result to FullName. Write a single %PUT statement to
display FullName in a sentence using both its current form and proper case, as shown below.
Submit the program and view the log to verify the results.
Note: Use %SYSFUNC to execute the PROPCASE function.
ANTHONY MILLER in proper case is Anthony Miller.

b. Modify and submit the program.


• Add a %LET statement to extract the first name from FullName, convert it to proper case,
and assign the result to a macro variable named First.
• Add another %LET statement to extract the last name from FullName, convert it to proper
case, and assign the result to a macro variable named Last.
• Display the values of FullName, First, and Last in the log as shown below.
FULLNAME=ANTHONY MILLER FIRST=Anthony LAST=Miller

c. Add a %SYMDEL statement to delete FullName, First, and Last from the global symbol
table. Use a %PUT statement to write the values of all user-defined macro variables to the
log. Submit the two statements and verify that that FullName, First, and Last are no longer
listed.

Level 2
2. Using Macro Quoting Functions
a. Open m103p02.sas from the practices folder and review the code. Submit the program and
review the results. Note that the footnote includes the date and time that the SAS session
started.
b. Create a macro variable named Product and assign the value R&D. Reference Product in
the TITLE and WHERE statements, replacing Jacket. Modify the FOOTNOTE statement to
display the current date and time, using the DATE9 and TIMEAMPM9 formats respectively.
Submit the program and verify that the title is Product Names Containing 'R&D' and that the
current date and time are displayed in the footnote.
• How many rows are in the report?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-22 Lesson 3 Storing and Processing Text

Challenge
3. Using Macro Functions to Perform Calculations
a. Assign your birthdate to a macro variable named Birthdate in the form DDMONYYYY (for
example, 01Jan1990). Use %SYSEVALF to calculate your age by subtracting your birthdate
from today’s date and dividing the difference by 365.25. Write the result to the log.
For example, if your birthday is January 1, 1990, and today is April 3, 2019, the results would
appear as shown below. Hint: Reference Birthdate as a SAS date constant ("&birthdate"d).
Note: The value of age depends on the current date.
My age is 29.2183436002737

b. Use the second argument to %SYSEVALF to return just the integer portion of your age and
write the results to the log.
For example, if your birthday is January 1, 1990, and today is April 3, 2019, the results would
appear as shown below.
My age is 29

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-23

3.2 Using SQL to Create Macro Variables

Creating Macro Variables

%LET
statement %LET is an easy
way to create a
macro variable and
%let type=Sedan; assign a value.

44
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables

%LET PROC SQL can create


statement and assign macro
variables based on
your data.
PROC SQL

45
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-24 Lesson 3 Storing and Processing Text

PROC SQL Syntax (Review)


query
PROC SQL;
SELECT <DISTINCT> item-1 < , item-2, …>
FROM clause
<WHERE clause> proc sql;
<ORDER BY clause>; select Model, MPG_Highway
from sashelp.cars
QUIT; where MPG_Highway>50
order by MPG_Highway;
quit;

46
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables with PROC SQL


PROC SQL; The INTO clause assigns
SELECT <DISTINCT> item-1 < , item-2, …> values produced by the query
<INTO : macvar-1 < …, : macvar-n> to macro variables.
FROM clause
<WHERE clause>
<ORDER BY clause>; Be sure to precede
QUIT; each macro
variable name with
a colon.

47
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-25

Creating Macro Variables with PROC SQL


proc sql; Count the number of rows
select count(*) returned by the query and store
into :total
from sashelp.cars; in a macro variable named Total.
quit;

Global Symbol Table Leading spaces are


Name Value included in the value.
TOTAL 428
SQLOBS 1 SQLOBS is created
automatically and stores
the number of rows
returned by the query.
48
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d03.sas

Creating Macro Variables with PROC SQL


proc sql;
select count(*)
into :total trimmed
from sashelp.cars;
quit; Use TRIMMED to remove
spaces before values are
Global Symbol Table stored in the macro variable.
Name Value
TOTAL 428
SQLOBS 1

49
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-26 Lesson 3 Storing and Processing Text

Creating Macro Variables with PROC SQL


proc sql noprint; suppresses the report
select distinct Origin
into :origin1-:origin3
from sashelp.cars;
quit; creates a series of macro
variables for the three
distinct values of Origin
Global Symbol Table
Name Value
ORIGIN1 Asia
ORIGIN2 Europe
ORIGIN3 USA
SQLOBS 3

50
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d03.sas

When capturing multiple rows of values into a series of macro variables, unwanted blanks
are automatically trimmed before the values are stored. Use of the TRIMMED modifier is not
necessary and will generate an error.

Creating Macro Variables with PROC SQL


proc sql noprint;
select distinct Type
into :type1- If you don’t know
from sashelp.cars; how many macro
quit; variables to create,
you can omit the
upper bound.
Global Symbol Table
Name Value
TYPE1 Hybrid
TYPE2 SUV
...
TYPE6 Wagon
SQLOBS 6 51
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-27

Creating Macro Variables with PROC SQL


proc sql noprint;
select distinct Origin
into :originlist separated by ", "
from sashelp.cars;
quit;
Use SEPARATED BY to assign
multiple values to a single
Global Symbol Table
macro variable.
Name Value
ORIGINLIST Asia, Europe, USA
SQLOBS 3

52
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-28 Lesson 3 Storing and Processing Text

Creating Macro Variables with a PROC SQL Query

Scenario
This demonstration uses the INTO clause in PROC SQL to write SQL query results into macro
variables.

Files
• m103d04.sas
• mc1.storm_damage
• mc1.storm_type_codes

Syntax

SELECT column INTO :macvar <TRIMMED>


SELECT column INTO :macvar SEPARATED BY “characters”

Notes
• PROC SQL can be used to load data values from table columns or values calculated in a query into
one or more macro variables.
• The INTO clause assigns values produced by PROC SQL to macro variables.

Demo
1. Open m103d04.sas from the demos folder. In Section 1 of the program, note that the PROC SQL
step calculates the mean of the Cost column and writes the result to a macro variable named
Avgcost. The %PUT statements write the values of the Avgcost and Sqlobs macro variables to
the log.
proc sql;
select mean(cost)
into :avgcost
from mc1.storm_damage;
quit;

%put &=avgcost;
%put &=sqlobs;
2. Highlight the code in Section 1 and submit the selected program. Note that the SQL query
produces a report that shows the mean of Cost from the storm_damage table, which is
formatted using scientific notation. View the log to confirm that the value is also stored in the
macro variable Avgcost. The value of the Sqlobs macro variable is 1 because one row was
returned by the query.
79 %put &=avgcost;
AVGCOST=2.238E10
80 %put &=sqlobs;
SQLOBS=1

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-29

3. Modify the query to suppress the report and format the result.
a. Add the NOPRINT option to the PROC SQL statement.
b. Add the FORMAT=DOLLAR20. column modifier to format the mean of Cost.
proc sql noprint;
select mean(cost) format=dollar20.
into :avgcost
...
c. Highlight the code in Section 1, submit the selected program, and review the log and results.
Note that a report is no longer produced and that the value stored in the macro variable
Avgcost is formatted with a dollar sign and commas. There are leading spaces in the macro
variable’s value.
80 %put &=avgcost;
AVGCOST= $22,381,578,947

d. Add the TRIMMED modifier after the Avgcost variable name in the INTO clause. Submit the
modified code and review the log. Note that the value of Avgcost no longer contains the
leading spaces.
proc sql noprint;
select mean(cost) format=dollar20.
into :avgcost trimmed
...

79 %put &=avgcost;
AVGCOST=$22,381,578,947
80 %put &=sqlobs;
SQLOBS=1

4. Modify the query to create multiple macro variables.


a. In the SELECT list of the query, add a column definition to calculate the median of Cost,
formatted with DOLLAR20.
b. In the INTO clause, add the macro variable name Medcost and apply the TRIMMED modifier.
c. Add a %PUT statement to write the value of Medcost to the log.
proc sql noprint;
select mean(cost) format=dollar20.,
median(cost) format=dollar20.
into :avgcost trimmed,
:medcost trimmed
from mc1.storm_damage;
quit;

%put &=avgcost;
%put &=medcost;
%put &=sqlobs;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-30 Lesson 3 Storing and Processing Text

d. Highlight the PROC SQL step and %PUT statements, and submit the selected code. Confirm
in the log that the macro variable values are all formatted with leading spaces trimmed.
81 %put &=avgcost;
AVGCOST=$22,381,578,947
82 %put &=medcost;
MEDCOST=$8,600,000,000
83 %put &=sqlobs;
SQLOBS=1

5. Examine the SQL query in Section 2. The query selects all columns from the
mc1.storm_type_codes table. Highlight the code in Section 2 and submit the selected program.
Notice that the report displays five values for Type and StormType.
proc sql;
select *
from mc1.storm_type_codes;
quit;
6. Modify the query to suppress the printed report and load each value of StormType into a
numbered series of macro variables starting with Type1. Uncomment the %PUT statements to
write the values of the macro variables to the log.
Note: You do not need to specify the name of final macro variable in the range.
proc sql noprint;
select StormType
into :type1-
from mc1.storm_type_codes;
quit;

%put &=type1 &=type2 &=type3 &=type4 &=type5;


%put &=sqlobs;
7. Highlight the code in Section 2 and submit the selected program. Confirm in the log that the
values of StormType are stored in the Type1 through Type5 macro variables.
79 %put &=type1 &=type2 &=type3 &=type4 &=type5 &=sqlobs;
TYPE1=Disturbance TYPE2=Extratropical TYPE3=Not Reported TYPE4=Subtropical TYPE5=Tropical
SQLOBS=5

8. Modify the query to load all values of StormType into a single macro variable named TypeList.
Separate each value with a comma and a space. Write the value of TypeList in the log.
proc sql noprint;
select StormType
into :typelist separated by ", "
from mc1.storm_type_codes;
quit;

%put &=typelist;
%put &=sqlobs;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-31

9. Highlight the code in Section 2 and submit the selected program. Note in the log that all five
values of StormType are stored in TYPELIST as a comma-delimited list.
79 %put &=typelist;
TYPELIST=Disturbance, Extratropical, Not Reported, Subtropical, Tropical
80 %put &=sqlobs;
SQLOBS=5

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-32 Lesson 3 Storing and Processing Text

Practice

Level 1
4. Using PROC SQL to Generate Macro Variables for Use in a Report Title
a. Open m103p04.sas from the practices folder. Review the code and submit the %LET
statements and the PROC SQL step. Verify that Qty (the mean for Quantity) is 1.43 and
Price (the mean for Total_Retail_Price) is 137.72.
b. In the TITLE2 statement, replace xxx with the mean for Quantity (1.43), and replace yyy with
the mean for Total_Retail_Price (137.72). Submit the TITLE statements and the PROC
PRINT step, and review the log and results.
• How many rows were read from the input table?
c. In the PROC SQL step, add an INTO clause to assign the mean for Quantity to a macro
variable named Qty, and the mean for Total_Retail_Price to a macro variable named Price.
In the TITLE2 statement, replace the hardcoded mean values with references to Qty and
Price.
Submit the entire program and review the log and results. Verify that the title displayed
correctly.
• How many rows were read from the input table?
• Why is the average price displayed with a leading dollar sign in the title?
d. Modify the %LET statements to assign 01Feb2019 to start and 28Feb2019 to stop. Submit
the program again.
• How many rows were read from the input table?
• What are the resolved values of qty and price in TITLE2?

Level 2
5. Using PROC SQL to Generate Macro Variables for Use in Subsequent Steps
a. Open m103p05.sas from the practices folder. Review and submit the code in part a. Verify
that the reported average wind speed is 79.
b. Review the code in part b. Replace every occurrence of XX with the average wind speed from
step a. Submit the code in part b and review the results.
• How many rows are in the table?
• Which bar has the highest frequency?
c. Modify the PROC SQL step.
• Suppress the PROC SQL output.
• Store the calculated value in a macro variable named AvgWind with no leading spaces.
• Add another SELECT statement to select the BasinName value from
mc1.storm_basin_codes where Basin is equal to the basincode macro variable. Write
the value to a macro variable named BasinName.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.2 Using SQL to Create Macro Variables 3-33

d. Modify the report code.


• Replace all hardcoded values of 79 with a reference to AvgWind.
• Replace all hardcoded text values of North Atlantic with a reference to BasinName.
• Submit the modified code and verify that the report contains the same information as the
report generated in step b.
e. Modify the %LET statements to assign 2015 to Year and EP to BasinCode. Submit the entire
program, including the modified %LET statements and the PROC SQL step. Review the log to
ensure that there are no errors or warnings. Verify that the report title is East Pacific Storms in
2015 Season Max Wind > Season Average of 92 MPH.
• How many rows are in the table?
• Which bar has the highest frequency?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-34 Lesson 3 Storing and Processing Text

3.3 Using the DATA Step to Create Macro


Variables

Creating Macro Variables

%LET The DATA step can


statement also be used to create
macro variables
based on your data.
PROC SQL

DATA step

57
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Scenario

The footnote should be


assigned based on values
in the Type column.
58
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-35

Creating Macro Variables with the DATA Step


%let make=Honda; END= creates a variable that is
1 when the last row is
data &make; processed and 0 otherwise.
set sashelp.cars end=lastrow;
where upcase(Make)="%upcase(&make)";
retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
%let foot=&make Offers Hybrid Cars;
end;
else do;
%let foot=&make Does Not Have a Hybrid Car;
end;
end;
run;
59
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Creating Macro Variables with the DATA Step


%let make=Honda;

data &make; If Type is Hybrid, then


set sashelp.cars end=lastrow; HybridFlag will be 1. The
where upcase(Make)="%upcase(&make)"; value is retained until the
retain HybridFlag; last row is processed.
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
%let foot=&make Offers Hybrid Cars;
end;
else do;
%let foot=&make Does Not Have a Hybrid Car;
end;
end;
run;
60
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-36 Lesson 3 Storing and Processing Text

Creating Macro Variables with the DATA Step


%let make=Honda; Can I conditionally
execute a %LET
data &make; statement based on
set sashelp.cars end=lastrow;
where upcase(Make)="%upcase(&make)"; a value generated
retain HybridFlag; during DATA step
if Type="Hybrid" then HybridFlag=1; execution?
if lastrow then do;
if HybridFlag=1 then do;
%let foot=&make Offers Hybrid Cars;
end;
else do;
%let foot=&make Does Not Have a Hybrid Car;
end;
end;
run;
61
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

3.04 Activity
Open m103a04.sas from the activities folder and perform the following tasks:
1. Run the program with Acura as the value of Make. First, examine the
output data and confirm that the value of HybridFlag is missing for the
last row because there are no hybrid cars. Second, confirm that the
footnote for the report is correct.
2. Modify the %LET statement to assign Honda as the value of the Make
macro variable. Run the program and view the output data. Confirm that
the value of HybridFlag is 1 for the last row.
3. Examine the report. Is the footnote correct?

62
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-37

DATA Step versus Macro Execution Timing


data Honda;
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
Macro Processor
Global Symbol Table
Word Name Value
Scanner MAKE Honda
special %
name let
foot=&make Offers Hybrid Cars;
end;
Input else do;
%let foot=&make Does Not Have a Hybrid Car;
Stack end;
end;
run;
64
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

DATA Step versus Macro Execution Timing


data Honda; %let foot=&make Offers Hybrid Cars;
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
Macro Processor
Global Symbol Table
Word Name Value
Scanner MAKE Honda
FOOT Honda Offers Hybrid Cars

end;
else do;
Input %let foot=&make Does Not Have a Hybrid Car;
end;
Stack end;
run;

65
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-38 Lesson 3 Storing and Processing Text

DATA Step versus Macro Execution Timing


data Honda;
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
Macro Processor
Global Symbol Table
Word name end Name Value
special ;
Scanner name else MAKE Honda
special do
;
FOOT Honda Offers Hybrid Cars
name
%let foot=&make Does Not Have a Hybrid Car;
end;
Input end;
run;
Stack

66
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

DATA Step versus Macro Execution Timing


data Honda;
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
end; Macro Processor
else do;
Global Symbol Table
Word Name Value
Scanner MAKE Honda
special %
FOOT Honda Offers Hybrid Cars
name let
foot=&make Does Not Have a Hybrid Car;
end;
Input end;
run;
Stack

67
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-39

DATA Step versus Macro Execution Timing


data Honda; %let foot=&make Does Not Have a
set sashelp.cars end=lastrow; Hybrid Car;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1; FOOT is
if lastrow then do;
if HybridFlag=1 then do;
Macro Processor
overwritten.
end;
else do;
Global Symbol Table
Word Name Value
Scanner MAKE Honda
Honda Does Not Have a
FOOT
Hybrid Car
end;
end;
Input run;
Stack

68
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

DATA Step versus Macro Execution Timing


data Honda;
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA";
Compiler retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
Macro Processor
end;
else do; Global Symbol Table
end; Name Value
end;
MAKE Honda
Honda Does Not Have a
• Before the DATA step compiles and executes, FOOT
Hybrid Car
all macro code has been executed.
• The DO groups are empty. Therefore, FOOT
will not change based on the value of
HybridFlag.
69
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-40 Lesson 3 Storing and Processing Text

DATA Step versus Macro Execution Timing

How can I delay the


creation of macro
variables until the
Execution DATA step executes?

Compilation

%LET statements create or


Word Scanning update macro variables.

70
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Creating Macro Variables in a DATA Step

CALL SYMPUTX(macro-variable, value); Execution

CALL SYMPUTX is a DATA


step CALL routine, not a
macro statement, so it is
processed in the
execution phase.

71
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-41

Creating Macro Variables in a DATA Step

CALL SYMPUTX(macro-variable, value); Execution

• This creates macro variables and assigns


values during DATA step execution.
• Leading and trailing blanks are removed
from both arguments.
• Arguments can be literal strings, columns
from the data, or expressions.
• Values of numeric columns are converted
automatically to text.

72
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Note: We discuss and demonstrate the uses of an optional third argument, <scope>,
in a subsequent lesson.

Creating Macro Variables in a DATA Step


call symputx("foot", "&make Offers Hybrid Cars");

fixed macro fixed macro


variable name variable value Because CALL SYMPUTX is
executed in the DATA step,
quotation marks help
distinguish literal strings
from column names.

73
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-42 Lesson 3 Storing and Processing Text

Original DATA Step


data &make; Word Scanning
set sashelp.cars end=lastrow;
where upcase(Make)="%upcase(&make)";
retain HybridFlag;
if Type="Hybrid" then HybridFlag=1;
if lastrow then do;
if HybridFlag=1 then do;
call symputx("foot", "&make Offers Hybrid Cars");
end;
else do;
call symputx("foot", "&make Does Not Have a Hybrid Car");
end;
end;
run;

74
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Compiled DATA Step


data Honda; Compilation
set sashelp.cars end=lastrow;
where upcase(Make)="HONDA"; Macro triggers have
retain HybridFlag; been resolved by the
if Type="Hybrid" then HybridFlag=1; macro processor.
if lastrow then do;
if HybridFlag=1 then do;
call symputx("foot", "Honda Offers Hybrid Cars");
end;
else do;
call symputx("foot", "Honda Does Not Have a Hybrid Car");
end;
end;
run; CALL SYMPUTX routines are included
because they are not macro statements.
75
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-43

Creating Macro Variables in a DATA Step


... true Execution
if HybridFlag=1 then do;
call symputx("foot", "Honda Offers Hybrid Cars");
end;
else do;
call symputx("foot", "Honda Does Not Have a Hybrid Car");
end;
...

Global Symbol Table


Name Value
MAKE Honda
FOOT Honda Offers Hybrid Cars

76
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Creating Macro Variables in a DATA Step


... false Execution
if HybridFlag=1 then do;
call symputx("foot", "Acura Offers Hybrid Cars");
end;
else do;
call symputx("foot", "Acura Does Not Have a Hybrid Car");
end;
...

Global Symbol Table


Name Value
MAKE Acura
FOOT Acura Does Not Have a Hybrid Car

77
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-44 Lesson 3 Storing and Processing Text

3.05 Multiple Choice Question


What is the value of foot after execution of the DATA step?
a. No Hybrid Cars
b. Some Hybrid Cars

data _null_;
call symputx('foot', 'No Hybrid Cars');
%let foot=Some Hybrid Cars;
run;

78
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

The DATA _NULL_ statement enables you to read the input table and execute DATA step code
without creating an output table.

Scenario

How can I insert a value


derived from the data
into the footnote?

80
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-45

Creating Macro Variables in a DATA Step

%let make=Honda;

data &make;
set sashelp.cars end=lastrow;
where upcase(Make)="%upcase(&make)";
if Type="Hybrid" then HybridCount+1;
if lastrow=1 then do;
call symputx("hybridnum", HybridCount);
end;
run;
fixed macro DATA step
variable name variable

81
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Creating Macro Variables in a DATA Step


...
if Type="Hybrid" then HybridCount+1;
if lastrow=1 then do;
call symputx("hybridnum", HybridCount);
end;
run;

footnote "&make offers &hybridnum Hybrid Cars";


...

PDV Global Symbol Table


Make ... LastRow HybridCount Name Value
MAKE Honda
Honda 1 2
HYBRIDNUM 2

82
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-46 Lesson 3 Storing and Processing Text

Creating Macro Variables in a DATA Step


data _null_;
set mc1.storm_basin_codes; You can use columns
call symputx(Basin, BasinName); from the input data
run; to provide both
macro variable macro variable macro variable
names values names and values.
mc1.storm_basin_codes Global Symbol Table
Basin BasinName Name Value
NA North Atlantic NA North Atlantic
WP West Pacific WP West Pacific
EP East Pacific EP East Pacific
SP South Pacific SP South Pacific
NI North Indian NI North Indian
SI South Indian SI South Indian
83
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Creating Macro Variables in a DATA Step


data _null_;
set mc1.storm_cat;
call symputx(cats('wind',Category),MinWind);
run;

mc1.storm_cat Global Symbol Table


You can use functions
Category MinWind Name Value
or expressions to 1 74 WIND1 74
manipulate the CALL 2 96 WIND2 96
SYMPUTX arguments. WIND3 111
3 111
4 130 WIND4 130
5 157 WIND5 157

84
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-47

3.06 Activity
Open m103a06.sas from the activities folder and perform the following tasks:
1. Highlight the %LET statement and PROC MEANS step and run the
selection. Examine the output data.
2. Complete the CALL SYMPUTX statement to create a macro variable
named AvgMSRP and load the value of the Mean column from the
CarsStat table.
3. Run the completed program. What is the value of the second title?

85
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-48 Lesson 3 Storing and Processing Text

Creating Macro Variables with the DATA Step

Scenario
This demonstration uses the SYMPUTX CALL routine in the DATA step to create and populate macro
variables.

Files
• m103d06.sas
• mc1.storm_damage
• mc1.storm_type_codes

Syntax

CALL SYMPUTX(macro-variable-name, value <,scope>)

Notes
• CALL SYMPUTX can be used to create macro variables and assign values during DATA step
execution.
• SYMPUTX automatically trims leading and trailing spaces from values assigned to macro variables.

Demo
1. Open m103d06.sas from the demos folder. In Section 1, the PROC MEANS step calculates the
mean and median for Cost from mc1.storm_damage and stores the results in an output table
named sumdata. Highlight the PROC MEANS step, run the selected code, and examine the
output table.
proc means data=mc1.storm_damage noprint;
var Cost;
output out=work.sumdata mean= median= /autoname;
run;
2. In the DATA _NULL_ step, add CALL SYMPUTX statements to create macro variables named
AvgCost and MedCost, and assign the values from the variables cost_mean and cost_median.
Highlight the code in Section 1, submit the selection, and examine the log. Notice that leading
blanks are automatically trimmed. However, the values are not formatted.
...
data _null_;
set sumdata;
call symputx("avgcost", cost_mean);
call symputx("medcost", cost_median);
run;
%put &=avgcost &=medcost;

AVGCOST=22381578947.3684 MEDCOST=8600000000

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-49

3. Modify the program to use the PUT function to write numeric values with the DOLLAR20. format.
Highlight the code in Section 1, submit the selection, and review the log. The macro variable
values are now formatted.
...
call symputx("avgcost", put(cost_mean, dollar20.));
call symputx("medcost", put(cost_median, dollar20.));
...

AVGCOST=$22,381,578,947 MEDCOST=$8,600,000,000

4. Find Section 2 in the program. Highlight the PROC PRINT step and run the selected code to view
the mc1.storm_type_codes table.
5. Notice that the DATA _NULL_ step creates a macro variable named Type and assigns the value
from the StormType column. Highlight the DATA step and %PUT statement, and run the selected
code. The log shows that the value of Type is Tropical, which is the last value from the
StormType column.
81 %put &=type;
TYPE=Tropical

6. Create a numbered series of macro variables starting with Type1 that will store each of the values
of the StormType column. Modify the first argument in the CALL SYMPUTX routine to
concatenate the prefix Type with the value of _N_. Delete the previous %PUT statement and
uncomment the %PUT statement that will display the Typen macro variables and values.
proc print data=mc1.storm_type_codes;
run;

data _null_;
set mc1.storm_type_codes;
call symputx(cats("type", _n_), StormType);
run;

%put &=type1 &=type2 &=type3 &=type4 &=type5;


7. Submit the modified program and review the log. Note that five macro variables were created and
populated with the values of the StormType.
TYPE1=Disturbance TYPE2=Extratropical TYPE3=Not Reported TYPE4=Subtropical TYPE5=Tropical

8. Recall that in the mc1.storm_type_codes table, the Type column contains a two-letter code that
uniquely identifies the StormType values. Type values are valid as macro variable names. Modify
the DATA step to create a series of macro variables with the value of Type as the name and the
value of StormType as the macro variable value. Delete the previous %PUT statement and
uncomment the %PUT statement that will write the values of the macro variables DS, ET, NR,
SS, and TS to the log.
data _null_;
set mc1.storm_type_codes;
call symputx(Type, StormType);
run;

%put &=DS &=ET &=NR &=SS &=TS;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-50 Lesson 3 Storing and Processing Text

9. Submit the modified program and review the log. Note that the DATA step read five observations
and created a series of macro variables named DS, ET, NR, SS, and TS.
DS=Disturbance ET=Extratropical NR=Not Reported SS=Subtropical TS=Tropical
10. The Sqlobs macro variable is not populated when creating macro variables with the DATA step.
Modify the DATA step to record the number of macro variables produced.
a. Add the END=LAST option to the SET statement.
b. Add IF-THEN logic to execute CALL SYMPUTX to write the value of _N_ to a macro variable
named Dsobs when the last row of the table is being processed.
c. Add Dsobs to the %PUT statement.
data _null_;
set mc1.Storm_Type_Codes end=last;
call symputx(Type,StormType);
if last then call symputx('dsobs',_n_);
run;

%put &=DS &=ET &=NR &=SS &=TS &=dsobs;


d. Execute the program and review the log. Note that DSOBS indicates that five rows were
processed.
DS=Disturbance ET=Extratropical NR=Not Reported SS=Subtropical TS=Tropical DSOBS=5

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.3 Using the DATA Step to Create Macro Variables 3-51

Comparing the DATA Step and SQL


DATA step PROC SQL

• can create a series of macro • can summarize data and load values
variables with both names and into a macro variable in one step
values based on columns • can load a delimited list into a
• can manipulate either the macro macro variable
variable names or values • can create a numbered series of
macro variables storing the distinct
values of a column
89
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-52 Lesson 3 Storing and Processing Text

Practice

Level 1
6. Creating Macro Variables with the SYMPUTX Routine
a. Open m103p06.sas from the practices folder. Review and submit the program. Verify that
the report title is New Staff: Administration Department and that the sum of Salary is
$221,618.
b. Add a %LET statement to assign the value Administration to a new macro variable named
dept, and replace every occurrence of Administration with a reference to dept. Submit the
modified program and verify that the title and report are the same as in part a.
c. Change the value of dept to Sales and submit the program. Verify that the report title is New
Staff: Sales Department.
• What is the sum of Salary?
d. Modify the DATA step to create a macro variable named avg to store the average salary on
the last iteration. Hint: Use the PUT function and the DOLLAR9. format when assigning the
value to avg.
Add a FOOTNOTE statement before the PROC PRINT step to display the value of avg as
shown below. Submit the program and review the results.
Average Salary: $xx,xxx
• What text is displayed in the footnote?

Level 2
7. Using a DATA _NULL_ Step to Create a Series of Macro Variables
a. Open m103p07.sas from the practices folder and review the program. The sashelp.vmacro
data source is a dynamic view that contains the name and value of all macro variables in the
current SAS session. Run the program and view the report.
b. Insert a DATA _NULL_ step before the PROC PRINT step to create a series of macro
variables using the values stored in the mc1.Storm_Ocean_Codes table. Use the values in
Ocean to name the macro variables. Use the values in OceanName as the macro variable
values.
c. Modify the PROC PRINT step to display only macro variables that are one character. Submit
the entire program and verify that five macro variables were created.
• What is the value of the macro variable, S?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-53

3.4 Indirect References to Macro


Variables

Scenario

%let cat=3;
%put NOTE: Category &cat storms >= 111 MPH;

mc1.storm_cat
Category MinWind How can I automatically
1 74 substitute the wind speed
2 96 into the program based
3 111 on the category value?
4 130
5 157

93
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Indirect References to Macro Variables

proc sql noprint; Either the DATA step or PROC SQL can
select MinWind create a series of macro variables that store
into :wind1-
minimum wind speeds for each category.
from mc1.storm_cat;
quit;
Global Symbol Table
OR Name Value
WIND1 74
data _null_; WIND2 96
set mc1.storm_cat;
WIND3 111
call symputx(cats("wind",_n_), MinWind);
run; WIND4 130
WIND5 157

94
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d07.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-54 Lesson 3 Storing and Processing Text

Indirect References to Macro Variables


%let cat=3;
%put NOTE: Category &cat storms >= &wind3 MPH;

Global Symbol Table


Suppose I want
Category 4 storms. The
Name Value
CAT 3
program would need to
WIND1 74
be modified in two
places.
WIND2 96
WIND3 111
WIND4 130
WIND5 157

95
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Indirect References to Macro Variables


%let cat=4;
%put NOTE: Category &cat storms >= &wind&cat MPH;

Global Symbol Table


Name Value Could we just use
CAT 4 &wind&cat?
WIND1 74
WIND2 96
WIND3 111
WIND4 130
WIND5 157

96
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-55

Indirect References to Macro Variables


%let cat=4;
%put NOTE: Category &cat storms >= &wind&cat MPH;

Global Symbol Table Macro Processor


Name Value %put NOTE: Category 4 storms >= &wind&cat MPH;
CAT 4
WIND1 74
WIND2 96
WIND3 111
WIND4 130
WIND5 157

97
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Indirect References to Macro Variables


%let cat=4;
%put NOTE: Category &cat storms >= &wind&cat MPH;

Global Symbol Table Macro Processor


Name Value %put NOTE: Category 4 storms >= &wind&cat MPH;
CAT 4
WIND1 74
WIND2 96
&wind is not in the global symbol
WIND3 111
table, so it remains as text.
WIND4 130
WARNING: Apparent symbolic reference WIND not resolved
WIND5 157

98
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-56 Lesson 3 Storing and Processing Text

Indirect References to Macro Variables


%let cat=4;
%put NOTE: Category &cat storms >= &wind&cat MPH;

Global Symbol Table Macro Processor


Name Value %put NOTE: Category 4 storms >= &wind4 MPH;
CAT 4
WIND1 74
WIND2 96
WIND3 111
NOTE: Category 4 storms >= &wind4 MPH
WIND4 130
WIND5 157

99
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.07 Activity
Open m103a07.sas from the activities folder and perform the following tasks:
1. Notice that the wind values have been replaced with &wind&cat. Run
the program and review the log.
2. Change &wind&cat to &&wind&cat. Run the program and review the
log. Does the program run successfully?

100
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-57

Indirect References to Macro Variables

Forward Rescan Rule


Multiple ampersands
can be used to change
the sequence in which
• Multiple ampersands followed by a name macro variables are
token denote an indirect reference. resolved.
• Two ampersands (&&) resolve to one
ampersand (&).
• A single ampersand followed by a name
token is resolved.
• The macro processor rescans the text until
no more references can be resolved.

102
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Indirect References to Macro Variables

• && resolves to &.


&&wind&cat • wind carries over as a name token. Global Symbol Table
• &cat resolves to 4.
Name Value
CAT 4
WIND1 74
&wind4 rescan
WIND2 96
WIND3 111
WIND4 130
WIND5 157

103
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-58 Lesson 3 Storing and Processing Text

Indirect References to Macro Variables

• && resolves to &.


&&wind&cat • wind carries over as a name token. Global Symbol Table
• &cat resolves to 4.
Name Value
CAT 4
WIND1 74
• &wind4
&wind4 resolves to 130. WIND2 96
WIND3 111
WIND4 130
WIND5 157
130

104
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Indirect References to Macro Variables


%let year=2017;
%let cat=2;
%let basin=SI;

title1 "South Indian &year Category &cat+ Storms";


...
How can we use the
mc1.storm_basin_codes
storm_basin_codes
Basin BasinName table to substitute the
NA North Atlantic
basin name into the
WP West Pacific
title?
EP East Pacific
SP South Pacific
NI North Indian
SI South Indian
105
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d07.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-59

Indirect References to Macro Variables


Step
1
data _null_; Create a macro variable
set mc1.storm_basin_codes; for each value of Basin
call symputx(Basin, BasinName); that will store the
run; BasinName value.

mc1.storm_basin_codes Global Symbol Table


Basin BasinName Name Value
NA North Atlantic NA North Atlantic
WP West Pacific WP West Pacific
EP East Pacific EP East Pacific
SP South Pacific SP South Pacific
NI North Indian NI North Indian
SI South Indian SI South Indian
106
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d07.sas

The values of the column named in the first argument must be unique and valid macro variable
names.

Indirect References to Macro Variables


Step
2 %let year=2017; Use an indirect reference
%let cat=2; to return South Indian.
%let basin=SI;

title1 "&&&basin &year Category &cat+ Storms";


...
Global Symbol Table
Name Value How would
BASIN SI &&&basin
NA North Atlantic resolve?
WP West Pacific
EP East Pacific
SP South Pacific
NI North Indian
SI South Indian 107
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d07.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-60 Lesson 3 Storing and Processing Text

Indirect References to Macro Variables


%let year=2017;
%let cat=2;
%let basin=SI;

title1 "&&&basin &year Category &cat+ Storms";


...
Global Symbol Table
•&& resolves to &.
Name Value &&&basin •&basin resolves to SI.
BASIN SI
NA North Atlantic
WP West Pacific &SI •&SI resolves to South Indian.
EP East Pacific
SP South Pacific
South
NI North Indian Indian
SI South Indian 108
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103d07.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-61

Indirect References to Macro Variables

Scenario
This demonstration uses a series of macro variables as lookup tables with indirect referencing.

Files
• m103d08.sas
• mc1.storm_final
• mc1.storm_cat
• mc1.storm_basin_codes

Syntax

&&prefix&varname
&&&varname

Notes
• Use indirect referencing to look up values stored in a series of macro variables.
• Two ampersands (&&) resolve to one ampersand (&).
• A single ampersand followed by a name token is resolved.
• The macro processor then rescans the text until no more references can be resolved.

Demo
1. Open program m103d08.sas from the demos folder. Review the program:
a. The %LET statements create macro variables Year, Cat, and Basin.
%let year=2016;
%let cat=2;
%let basin=SI;
b. The PROC SQL step creates a numbered series of macro variables, Wind1 through Wind5,
with values assigned from the MinWind column in the mc1.storm_cat table. For example,
the minimum wind speed for a Category 2 storm is captured in the Wind2 macro variable.
proc sql noprint;
select MinWind
into :wind1-
from mc1.storm_cat;
quit;
c. The DATA step creates a series of macro variables with names derived from the Basin
column and values assigned from the BasinName column. For example, the macro variable
SI has a value of South Indian.
data _null_;
set mc1.storm_basin_codes;
call symputx(Basin, BasinName);
run;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-62 Lesson 3 Storing and Processing Text

d. The TITLE statement and PROC PRINT step include direct macro variable references,
&basin, &year, and &cat.
e. The WHERE statement includes an indirect macro variable reference, &&wind&cat, which
resolves to Wind1, Wind2, and so on, up to Wind5, depending on the value of &cat.
title1 "&basin &year Category &cat+ Storms";
proc print data=mc1.storm_final noobs;
where Basin="&basin" and
MaxWindMPH>=&&wind&cat and
Season=&year;
run;
2. Submit the program and review the output and log. Confirm that three storms are returned and
the title includes the Basin, Year, and Cat macro variable values.
3. Replace &basin in the TITLE statement with &&&basin. If the value of the macro variable Basin
is SI, then &&&basin first resolves to &SI, which then resolves to South Indian. Run the program
and confirm that the title includes South Indian.
4. Change the value of Year to 2014, Cat to 3, and Basin to NA. Submit the program and confirm
that two storms are returned and the title is updated.
5. Open the mc1.storm_cat table. Notice that the Damage column contains a descriptive label for
each value of Category.
6. In the program, modify the SQL query to select an additional column, Damage, and load values
into a range of macro variables, Damage1 through Damage5.
proc sql noprint;
select MinWind, Damage
into :wind1-, :damage1-
from mc1.storm_cat;
quit;
7. Add a FOOTNOTE statement before the PROC PRINT step that includes the selected storm
category and the corresponding damage description. Run the program and observe the results.
footnote "Category &cat storms typically cause &&damage&cat";

8. The resolved value of &&damage&cat has the first letter capitalized. Use the %LOWCASE
function to change the case of the returned text string in the TITLE statement. Run the program
and confirm that the footnote is correct.
footnote "Category &cat storms typically cause
%lowcase(&&damage&cat)";

9. Change the values of Year to 2015, Cat to 2, and Basin to WP. Confirm that the report, title, and
footnote are all updated.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.4 Indirect References to Macro Variables 3-63

Practice

Level 1
8. Using Indirect References to Macro Variables
a. Open m103p08.sas from the practices folder. Submit the code and review the results.

b. Explore the mc1.order_type_codes table. The Order_Type_Code column contains the


values 1, 2, and 3, and the Order_Type column identifies the type of order associated with
the code. Close the table.
c. At the top of the program, insert an SQL query to access mc1.order_type_codes and create
a series of macro variables named Type1, Type2, and Type3. Assign the value of the
Order_Type variable associated with each order type. Suppress the PROC SQL output, and
add a %PUT statement to write the values of Type1, Type2, and Type3 to the log.
d. Submit the PROC SQL step and the %PUT statement. Review the log. Verify that the log
contains TYPE1=Retail Store TYPE2=Catalog TYPE3=Internet.
e. Modify the TITLE statement to use an indirect macro variable reference to the Type variable
that corresponds to the value of code. Submit the entire program and review the results.
Verify that the report contains the same two rows generated by the original report and that the
title is High Profit Products for Retail Store Orders.
f. Modify the %LET statement to assign a value of 3 to the macro variable, code. Resubmit the
program and review the results.
• What is the report title?

Level 2
9. Using Indirect References to Macro Variables
a. Open m103p09.sas from the practices folder and review the code. Submit the program and
review the results. Verify that the report is titled Customers Residing in LU and that there are
three rows in the report.
b. At the top of the program, insert a DATA _NULL_ step to create a series of macro variables
from the mc1.country_codes table. Use the value in the CountryCode column as the macro
variable name, and use the value of the corresponding CountryName column as the macro
variable's value. Submit the DATA _NULL_ step to create the macro variables.
c. Modify the TITLE statement to include the country name based on the value of the code
macro variable. Verify that the title is Customers Residing in Luxembourg.
d. Modify the %LET statement to assign a value of ZA to the macro variable, code. Submit the
program and review the results.
• How many customers are from ZA, and what is the country name?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-64 Lesson 3 Storing and Processing Text

3.5 Solutions
Solutions to Practices
Section 3.1
1. Using the %UPCASE and %SCAN Functions
/* Part a. */
%let fullname=AnTHoNY MilLeR;
%put &fullname;

%let fullname=%upcase(&fullname);
%put &fullname in proper case is
%sysfunc(propcase(&fullname)).;

/* Part b. */
%let first=%sysfunc(propcase(%scan(&fullname,1)));
%let last=%sysfunc(propcase(%scan(&fullname,-1)));
%put &=fullname &=first &=last;

/* Part c. */
%symdel fullname first last;
%put _user_;
2. Using Macro Quoting Functions
%let product=%nrstr(R&D);
title "Product Names Containing '&product'";
footnote "Report Produced %sysfunc(date(), date9.)
%sysfunc(time(),timeampm9.)";
proc print data=mc1.products;
where Product_Name contains "&product";
var Product_Name Product_ID Supplier_Name;
run;
title;
footnote;
How many rows are in the report? Eight rows
3. Using Macro Functions to Perform Calculations
/* Part a. */
%let birthdate=01Jan1990;
%put My age is %sysevalf((%sysfunc(today())-
"&birthdate"d)/365.25);

/* Part b. */
%put My age is %sysevalf((%sysfunc(today())-
"&birthdate"d)/365.25, int);

Section 3.2

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-65

4. Using PROC SQL to Generate Macro Variables for Use in a Report Title
/* Part b. */
%let start=01Jan2019;
%let stop=31Jan2019;
proc sql noprint;
select mean(Quantity) format=4.2 as qty,
mean(Total_Retail_Price) format=dollar7.2 as price
from mc1.orders
where Order_Date between "&start"d and "&stop"d;
quit;

title1 " Orders from &start to &stop";


title2 "Average Quantity: 1.43 Average Price: 137.72";
proc print data=mc1.orders;
where Order_Date between "&start"d and "&stop"d;
var Order_ID Order_Date Quantity Total_Retail_Price;
sum Quantity Total_Retail_Price;
format Total_Retail_Price dollar8.;
run;
title;
How many rows were read from the input table? 278 rows
/* Part c. */
%let start=01Jan2019;
%let stop=31Jan2019;
proc sql noprint;
select mean(Quantity) format=4.2,
mean(Total_Retail_Price) format=dollar7.2
into :qty, :price
from mc1.orders
where Order_Date between "&start"d and "&stop"d;
quit;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-66 Lesson 3 Storing and Processing Text

title1 " Orders from &start to &stop";


title2 "Average Quantity: &qty Average Price: &price";
proc print data=mc1.orders;
where Order_Date between "&start"d and "&stop"d;
var Order_ID Order_Date Quantity Total_Retail_Price;
sum Quantity Total_Retail_Price;
format Total_Retail_Price dollar8.;
run;
title;
How many rows were read from the input table? 278 rows
Why is the average price displayed with a leading dollar sign in the title? The DOLLAR7.2
format is applied to the mean of Total_Retail_Price before it is assigned to the macro
variable, price.
/* Part d. */
%let start=01Feb2019;
%let stop=28Feb2019;
proc sql noprint;
select mean(Quantity) format=4.2,
mean(Total_Retail_Price) format=dollar7.2
into :qty, :price
from mc1.orders
where Order_Date between "&start"d and "&stop"d;
quit;

title1 " Orders from &start to &stop";


title2 "Average Quantity: &qty Average Price: &price";
proc print data=mc1.orders;
where Order_Date between "&start"d and "&stop"d;
var Order_ID Order_Date Quantity Total_Retail_Price;
sum Quantity Total_Retail_Price;
format Total_Retail_Price dollar8.;
run;
title;
• How many rows were read from the input table? 219 rows
• What are the resolved values of qty and price in TITLE2? Average Quantity: 1.30
Average Price: $104.43
5. Using PROC SQL to Generate Macro Variables for Use in a Subsequent Step
/* Part b. */
title1 "North Atlantic Basin Storms in &year Season";
title2 "Max Wind > Season Average of 79 MPH";
proc print data=mc1.storm_final noobs;
var Name StartDate EndDate MaxWindMPH MinPressure;
where MaxWindMPH>79 and Season=&Year and Basin="&basinCode";
run;
title;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-67

proc sgplot data=mc1.storm_final;


where MaxWindMPH>79 and Season=&year and Basin="&basincode";
vbar StormType;
yaxis display=(noline) grid;
run;
How many rows are in the table? Seven rows
Which bar has the highest frequency? Extratropical
/* Parts c. and d. */
proc sql noprint;
select round(mean(MaxWindMPH)) as AvgWind
into :avgwind trimmed
from mc1.storm_final
where Season=&year and Basin="&basincode";
select BasinName
into :basinname
from mc1.storm_basin_codes
where basin="&basinCode";
quit;

title1 "&basinName Storms in &year Season";


title2 "Max Wind > Season Average of &avgwind MPH";
proc print data=mc1.storm_final noobs;
var Name StartDate EndDate MaxWindMPH MinPressure;
where MaxWindMPH>&avgwind and Season=&Year
and Basin="&basincode";
run;
title;

proc sgplot data=mc1.storm_final;


where MaxWindMPH>&avgwind and Season=&year
and Basin="&basincode";
vbar StormType;
yaxis display=(noline) grid;
run;

/* Part e. */
%let year=2015;
%let basincode=EP;

proc sql noprint;


select round(mean(MaxWindMPH)) as AvgWind
into :avgwind trimmed
from mc1.storm_final
where Season=&Year and Basin="&basincode";

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-68 Lesson 3 Storing and Processing Text

select BasinName
into :basinname
from mc1.storm_basin_codes
where basin="&basincode";
quit;

title1 "&basinname Storms in &year Season";


title2 "Max Wind > Season Average of &avgwind MPH";
proc print data=mc1.storm_final noobs;
var Name StartDate EndDate MaxWindMPH MinPressure;
where MaxWindMPH>&avgwind and Season=&Year
and Basin="&basincode" ;
run;
title;

proc sgplot data=mc1.storm_final;


where MaxWindMPH>&avgwind and Season=&year and
Basin="&basincode";
vbar StormType;
yaxis display=(noline) grid;
run;
How many rows are in the table? 11 rows
Which bar has the highest frequency? Disturbance

Section 3.3
6. Creating Macro Variables with the SYMPUTX Routine
/* Part b. */
%let dept=Administration;
data staff;
keep Employee_ID Department Job_Title Salary;
set mc1.newhires;
where Department="&dept";
run;

title "New Staff: &dept Department";


proc print data=staff;
sum salary;
run;
title;
Verify that the report title is New Staff: Administration Department and that the sum of Salary is
$221,618.
/* Part c. */
%let dept=Sales;
data staff;
keep Employee_ID Department Job_Title Salary;
set mc1.newhires;
where Department="&dept";

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-69

run;

title "New Staff: &dept Department";


proc print data=staff;
sum salary;
run;
title;
What is the sum of Salary? $257,245
/* Part d. */
%let dept=Sales;
data staff;
keep Employee_ID Department Job_Title Salary;
set mc1.newhires end=last;
where Department="&dept";
total+salary;
if last=1 then
call symputx("avg",put(total/_n_,dollar9.));
run;

footnote "Average Salary: &avg";


title "New Staff: &dept Department";
proc print data=staff;
sum salary;
run;
title;footnote;
What text is displayed in the footnote? Average Salary: $36,749
7. Using a DATA _NULL_ Step to Create a Series of Macro Variables
data _null_;
set mc1.Storm_Ocean_Codes;
call symputx(Ocean,OceanName);
run;
proc print data=sashelp.vmacro;
var name value;
where name like "_";
run;
What is the value of the macro variable, S? Southern (Antarctic)

Section 3.4
8. Using Indirect References to Macro Variables
/* Parts c. and d. */
proc sql noprint;
select Order_Type
into :type1-
from mc1.order_type_codes;
quit;
%put &=type1 &=type2 &=type3;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-70 Lesson 3 Storing and Processing Text

/* Part e. */
%let code=1;
title "High Profit Products for &&type&code Orders";
proc sql number;
select Product_ID format=z12.,
Sum(Total_Retail_Price) format=dollar10.2 as GrossSales,
Sum(Total_Retail_Price-CostPrice_Per_Unit)
format=dollar10.2 as Profit
from mc1.orders
where Order_Type=&code
group by Product_ID
having profit /grosssales > .95
order by Profit desc;
quit;
title;

/* Part f. */
%let code=3;
title "High Profit Products for &&type&code Orders";
proc sql number;
select Product_ID format=z12.,
Sum(Total_Retail_Price) format=dollar10.2 as GrossSales,
Sum(Total_Retail_Price-CostPrice_Per_Unit)
format=dollar10.2 as Profit
from mc1.orders
where Order_Type=&code
group by Product_ID
having profit /grosssales > .95
order by Profit desc;
quit;
title;
What is the report title? High Profit Products for Internet Orders
9. Using Indirect References to Macro Variables
/* Part b. */
data _null_;
set mc1.country_codes;
call symputx(CountryCode,CountryName);
run;

/* Part c. */
%let code=LU;
title "Customers Residing in &&&code";
proc print data=mc1.customers;
id ID;
var Name Age_Group;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-71

where Country="&code";
run;
title;

/* Part d. */
%let code=ZA;
title "Customers Residing in &&&code";
proc print data=mc1.customers;
id ID;
var Name Age_Group;
where Country="&code";
run;
title;

How many customers are from ZA, and what is the country name? There are seven customers
from South Africa.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-72 Lesson 3 Storing and Processing Text

Solutions to Activities and Questions

3.01 Activity – Correct Answer


1. Examine the TITLE statement. What text will appear as the title? Run
the program and view the results.
%let text=class list;
title "upcase(&text)";
proc print data=sashelp.class;
run;

2. Add % before the UPCASE function in the TITLE statement. Run the
program. What text appears as the title?
%let text=class list;
title "%upcase(&text)";
proc print data=sashelp.class;
run;
17
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m103a01.sas

3.02 Activity – Correct Answer


%let dt=front;
data cars_subset;
set sashelp.cars;
where upcase(DriveTrain)="%upcase(&dt)";
run;

title "%sysfunc(propcase(&dt)) Wheel Drive Cars";


footnote "Listing from %scan(&syslast,2) Table";
proc print data=&syslast;
run;

24
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-73

3.03 Activity – Correct Answer


1. Why does the program fail?

%let location=Buenos Aires, Argentina;


%let city=%scan(&location, 1,,);
%put &=city;

A comma is embedded This comma should be the


in the first argument. value of the third argument.

%scan(Buenos Aires, Argentina, 1,,)

ERROR: Macro function %SCAN has too many arguments.

36
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.03 Activity – Correct Answer


2. Use %STR to mask the comma in the appropriate places so that the
value of the City macro variable is Buenos Aires.

%let location=%str(Buenos Aires, Argentina);


%let city=%scan(&location, 1, %str(,));
%put &=city;

CITY=Buenos Aires Commas are treated as


plain text instead of
separating arguments.

37
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-74 Lesson 3 Storing and Processing Text

3.04 Activity – Correct Answer


Is the footnote correct?

Even though HybridFlag is


1 for the last row, the
footnote is not correct.

63
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.05 Multiple Choice Question – Correct Answer


What is the value of foot after execution of the DATA step?
a. No Hybrid Cars
b. Some Hybrid Cars

data _null_;
call symputx('foot', 'No Hybrid Cars’);
%let foot=Some Hybrid Cars;
run;

1) The %LET statement goes to the


2) CALL SYMPUTX is executed as
macro processor before the DATA
part of the DATA step.
step executes.
79
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3.5 Solutions 3-75

continued...
3.06 Activity – Correct Answer
What is the value of the second title?

data _null_;
set CarsStat;
call symputx("avgmsrp",Mean);
run; Which DATA step
function can convert
title "&make Cars"; a number to a
title2 "Average MSRP: &avgmsrp";
proc print data=sashelp.cars noobs; formatted character
where Make="&make"; string?
run;
title;

86
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

3.06 Activity – Correct Answer


What is the value of the second title?

call symputx("avgmsrp", put(Mean, dollar8.));

The PUT function


can be used to
format the number
before it is stored in
the macro variable.

87
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
3-76 Lesson 3 Storing and Processing Text

3.07 Activity – Correct Answer


1. Notice that the wind values have been replaced with &wind&cat. Run
the program and review the log.
79 %let cat=4;
80 %put NOTE: Category &cat storms >= &wind&cat MPH;
WARNING: Apparent symbolic reference WIND not resolved.
NOTE: Category 4 storms >= &wind4 MPH

2. Change &wind&cat to &&wind&cat. Run the program and review the


log. Does the program run successfully? Yes
79 %let cat=4;
80 %put NOTE: Category &cat storms >= &&wind&cat MPH;
NOTE: Category 4 storms >= 130 MPH

101
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
Lesson 4 Working with Macro
Programs

4.1 Defining and Calling a Macro ................................................................................................ 4-3


Demonstration: Creating a Macro Definition with Parameters ............................................. 4-14

Practice ................................................................................................................................. 4-20

4.2 Macro Variable Scope ........................................................................................................... 4-22


Practice ................................................................................................................................. 4-42

4.3 Conditional Processing ........................................................................................................ 4-44


Demonstration: Conditional Processing ............................................................................... 4-58

Practice ................................................................................................................................. 4-61

4.4 Iterative Processing .............................................................................................................. 4-63


Demonstration: Iterative %DO Loops .................................................................................. 4-67

Demonstration: %DO Loops with Indirect References ........................................................ 4-72

Practice ................................................................................................................................. 4-82

4.5 Solutions ................................................................................................................................ 4-84


Solutions to Practices ........................................................................................................... 4-84

Solutions to Activities and Questions ................................................................................... 4-93


4-2 Lesson 4 Working with Macro Programs

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-3

4.1 Defining and Calling a Macro

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

Let's use the first


three steps of the
process to create a
macro application.

3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

proc print data=sashelp.cars(obs=5);


run;

4
Copy ri ght © S AS Insti tute Inc . Al l ri ghts reserved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-4 Lesson 4 Working with Macro Programs

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

%let dsn=sashelp.cars;
%let obs=5;
proc print data=&dsn(obs=&obs);
run;

5
Copy ri ght © S AS Insti tute Inc . Al l ri ghts reserved.

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

How can I turn this


%let dsn=sashelp.cars; program into a
%let obs=5;
proc print data=&dsn(obs=&obs); reusable macro
run; definition?

6
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-5

Macro Definitions

%MACRO macro-name </ DES="description">; macro-text can include


macro-text • macro language statements
%MEND <macro-name>; or expressions
• complete or partial SAS
program statements or
program steps.
%let dsn=sashelp.cars;
%let obs=5;
%macro printtable / des="Print a table";
proc print data=&dsn(obs=&obs);
run;
%mend printtable;

7
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d01.sas

Macro names must start with a letter or an underscore, and remaining characters can be letters,
numbers, or underscores.

Macro Definitions

PRINTTABLE Compiled macro


definitions are
stored in catalogs in
work.sasmacr (default) a SAS library.

%macro printtable / des="Print a table";


proc print data=&dsn(obs=&obs);
run;
%mend printtable;

8
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-6 Lesson 4 Working with Macro Programs

Macro Definitions
PROC CATALOG
proc catalog catalog=work.sasmacr; can be used to list
contents;
the contents of a
run;
catalog.

9
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d01.sas

continued...
4.01 Activity
Open m104a01.sas from the activities folder and perform the following tasks:
1. Notice that there is a missing semicolon after the PROC PRINT statement.
Run the program and confirm that an error is generated in the log. Do not
correct the error.
2. Modify the code to create a macro program named PrintTable. Run the
program and notice that there are no notes, warnings, or errors in the log.
%macro printtable;
proc print data=&dsn(obs=&obs)
run;
%mend printtable;

10
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-7

4.01 Activity
3. Add the following OPTIONS statements at the start of the program to
set the MCOMPILENOTE=ALL option.
options mcompilenote=all;

4. Submit the program. The log includes a note indicating that the
PrintTable macro compiled without errors.
5. Why does the macro program compile successfully even though there is
a syntax error in the PROC PRINT step?

11
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Definitions

OPTIONS MCOMPILENOTE=ALL|NONE; Use


MCOMPILENOTE=ALL to
confirm that your macro
%let dsn=sashelp.cars; definition compiled
%let obs=5; successfully.
options mcompilenote=all;

%macro printtable;
proc print data=&dsn(obs=&obs);
run;
%mend printtable;

options mcompilenote=none;
NOTE: The macro PRINTTABLE completed
compilation without errors.

13
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-8 Lesson 4 Working with Macro Programs

Calling a Macro
A macro call
%macro-name
executes the code
stored in the macro
definition.
%let dsn=sashelp.cars;
%let obs=5;

%printtable

Do not include a
semicolon after
the macro call.

14
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Calling a Macro

Compiler

Macro Processor

%LET statements Global Symbol Table


Word
created macro variables Name Value
Scanner
and assigned values. DSN sashelp.cars
OBS 5

%printtable
work.sasmacr
Input
Name Stored Code
Stack
proc print data=&dsn(obs=&obs);
PRINTTABLE run;

15
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-9

Calling a Macro
%printtable

Compiler

Macro Processor

Global Symbol Table


Word
Name Value
Scanner
special % DSN sashelp.cars
name printtable OBS 5

work.sasmacr
Input
Name Stored Code
Stack
proc print data=&dsn(obs=&obs);
PRINTTABLE run;

16
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Calling a Macro
%printtable

Compiler

Macro Processor

Global Symbol Table


Word
Name Value
Scanner
DSN sashelp.cars
OBS 5

work.sasmacr
Input
Name Stored Code
Stack
proc print data=&dsn(obs=&obs);
PRINTTABLE run;

17
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-10 Lesson 4 Working with Macro Programs

Calling a Macro

Compiler

Macro Processor

Global Symbol Table


Word
Name Value
Scanner
DSN sashelp.cars
OBS 5

proc print data=&dsn(obs=&obs);


run; work.sasmacr
Input
Name Stored Code
Stack
proc print data=&dsn(obs=&obs);
PRINTTABLE run;

18
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Calling a Macro
&dsn
The program is
Compiler
tokenized and macro
references are resolved.
Macro Processor
name proc
name print Global Symbol Table
Word name data
Name Value
Scanner special =
special & DSN sashelp.cars
name dsn OBS 5

(obs=&obs);
run; work.sasmacr
Input
Name Stored Code
Stack
proc print data=&dsn(obs=&obs);
PRINTTABLE run;

19
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-11

Calling a Macro
proc print data=sashelp.cars(obs=5);
run;
Compiler

Execute
Word
Scanner

Input
Stack

20
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.02 Activity
Open m104a02.sas from the activities folder and perform the following tasks:
1. Run the program and verify in the log that the %PrintTable macro
compiled successfully.
2. Add a line of code at the bottom of the program to call the %PrintTable
macro.
%printtable

3. Highlight the macro call and run the selected code. Based on only what
you see in the log, can you tell where in the SAS program the error
occurred?

21
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-12 Lesson 4 Working with Macro Programs

Troubleshooting a Macro
options mprint;
%printtable OPTIONS MPRINT;
options nomprint;

84 %printtable
MPRINT(PRINTTABLE): proc print data=sashelp.clas(obs=5);
ERROR: File SASHELP.CLAS.DATA does not exist.
MPRINT(PRINTTABLE): run;
The displayed
code has all macro
triggers already
name of the SAS code
resolved.
macro generating generated by
the code the macro

23
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Parameters

In order for the


%macro printtable; %PrintTable macro to run
proc print data=&dsn(obs=&obs); successfully, values must
run;
%mend printtable; first be assigned to the
included macro variables.

%let dsn=sashelp.cars;
%let obs=5;

%printtable

24
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-13

Macro Parameters
Create a macro
definition with
parameters

%macro printtable(dsn,obs); Using macro parameters is


proc print data=&dsn(obs=&obs); a practical alternative to
run; assigning macro variable
%mend printtable;
values using %LET.

%printtable(sashelp.cars,5)

25
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d01.sas

Macro Positional Parameters


%MACRO macro-name(parameter-1, … parameter-n);

%macro-name(value-1, … value-n)

In a macro definition,
%macro printtable(dsn,obs); positional parameter names
are provided in an ordered list.

In a macro call, positional


%printtable(sashelp.cars,5)
parameter values must be
listed in the same order.
26
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-14 Lesson 4 Working with Macro Programs

Creating a Macro Definition with Parameters

Scenario
We have a SAS program that produces a report about storms in the 2016 season in the North
Atlantic basin with maximum winds greater than 80 MPH. We want to be able to produce the same
report for other seasons, basins, and wind speeds.

Files
• m104d02.sas

Syntax

%macro-name(parameter1,…parameterN)

Notes
• Macro definitions can be created to accept parameters.
• Macro parameters are resolved as macro variables during macro execution.
• Parameters are named in a comma-separated list in parentheses in the %MACRO statement.
• When the macro is called, parameter values are supplied in parentheses as a comma-delimited
list.
• Because these parameters are positional, parameter values must be supplied in the proper order.

Demo
1. Open m104d02.sas from the demos folder. This program produces a bar chart to examine the
frequency of StormType by Basin. It includes storms in the NA basin (North Atlantic) during the
2016 season with maximum wind speed greater than 80 MPH. Run the program and confirm the
results.

2. Add %LET statements to create macro variables named Basin, Season, and MaxWind,
and assign values of NA, 2016, and 80 respectively. Replace hardcoded values in the SAS
program with the appropriate macro variable references. Run the program and verify that it
reproduces the original report with no errors or warnings in the log.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-15

%let Basin=NA;
%let Season=2016;
%let MaxWind=80;

title1 "Storm Frequency by Type";


title2 "&Basin Basin, &Season Season, Max Wind > &MaxWind MPH";
proc sgplot data=mc1.storm_final;
vbar StormType / dataskin=pressed;
where Basin="&Basin" and Season=&Season and
MaxWindMPH>&MaxWind;
run;
title;
3. Test the generalized program by modifying the %LET statements for Basin, Season, and
MaxWind to assign values of EP, 2015, and 125 respectively. Run the program and verify that it
runs without producing errors or warnings in the log.
%let Basin=EP;
%let Season=2015;
%let MaxWind=125;

4. Modify the program to create a macro named StormChart. Replace the three %LET statements
with positional parameters for Basin, Season, and MaxWind. Add an OPTIONS statement to
change the MCOMPILENOTE= option to ALL. Run the program and verify that the macro
compiled without error.
options mcompilenote=all;
%macro stormchart(Basin, Season, MaxWind);
title1 "Storm Frequency by Type";
title2 "&Basin Basin, &Season Season, Max Wind > &MaxWind MPH";
...
title;
%mend stormchart;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-16 Lesson 4 Working with Macro Programs

5. Call the %StormChart macro with parameter values EP for Basin, 2015 for Season, and 125
for MaxWind. Turn on the MPRINT option to view the submitted macro code in the log and turn
off the MPRINT option after the macro executes. Highlight the statements and run the selected
code. Review the results to verify that the results match the previous report. Confirm in the log
that the executed code is printed.
options mprint;
%stormchart(EP,2015,125)
options nomprint;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-17

Macro Positional Parameters

%macro printtable(dsn,obs); If a positional parameter is


proc print data=&dsn(obs=&obs); not assigned a value in the
run; macro call, it is assigned a
%mend printtable; null value, which can cause
syntax errors.
%printtable(sashelp.cars)

75 proc print data=&dsn(obs=&obs); run;


...
MPRINT(PRINTTABLE): proc print data=sashelp.cars(obs= );
MPRINT(PRINTTABLE): run;
ERROR 23-7: Invalid value for the OBS option.
28
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Keyword Parameters


%MACRO macro-name(name=value, …, name=value);

%macro printtable(dsn=sashelp.cars,obs=5);

Keyword parameters in a Keyword parameters


macro definition are listed enable you to assign
as name=value pairs. default values.

29
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-18 Lesson 4 Working with Macro Programs

Macro Keyword Parameters

%macro-name(name=value, …, name=value)

Keyword parameters in a macro call %printtable()


• include name=value pairs
• can be listed in any order %printtable(dsn=sashelp.heart)
• require parentheses after the
macro name even if no parameter %printtable(obs=10,
values are provided. dsn=mc1.storm_final)
If keyword parameters are omitted,
the default value from the macro
definition is assigned.

30
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.03 Activity
Open m104a03.sas from the activities folder and perform the following tasks:
1. Modify the %MACRO statement to use keyword parameters. Assign
default values of NA to Basin, 2016 to Season, and 20 to MaxWind. Run
the program and verify that the macro compiles successfully.
%macro stormchart(basin=NA, season=2016, maxwind=20);

2. Call the %StormChart macro with no parameter values provided. Confirm


in the log that the default parameter values are used.
%stormchart()

3. Call the %StormChart macro with Season as 2015 and Basin as EP. View
the log. Is the table subset by MaxWind, even though it is not included as
a parameter in the macro call? 31
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-19

Mixed Parameter Lists

%macro stormchart(Basin, Season=2016, MaxWind=111);

It is possible to mix
positional and keyword
%stormchart(WP) parameters in a list, but
positional parameters
%stormchart(NA, Season=2015) must always come first.

%stormchart(SI, MaxWind=100, Season=2014)

33
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Mixed Parameter Lists

%macro stormchart(Basin, Season=2016, MaxWind=111);

Basin does not have a default value


as a positional parameter, so a value
must be provided in each macro call.
%stormchart(WP)

%stormchart(NA, Season=2015)

%stormchart(SI, MaxWind=100, Season=2014)

34
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-20 Lesson 4 Working with Macro Programs

Practice

Level 1
1. Defining and Using a Macro with Parameters

a. Open m104p01.sas from the practices folder. Review and submit the program. Verify that it
generates a report for Gold customers that contains 680 rows.
b. Convert the code to a macro named Customers that accepts a positional parameter named
Type. Submit the macro definition and review the log to verify that the macro compiled
successfully.
• Call the %Customers macro with the parameter value Gold. Verify that the title is Gold
Customers and that there are 680 rows in the report.
• Call %Customers again with the parameter value High Activity. No rows were selected
due to a case difference.
c. Modify the macro to convert the value of the parameter Type to uppercase and modify the
WHERE clause to make the string comparison case insensitive. Submit the macro definition
and verify that it compiled correctly.
• Call the macro with the parameter value High Activity. Verify that the title is HIGH
ACTIVITY Customers and that the report contains 461 rows.
d. Change the positional parameter to a keyword parameter with a default value of inactive.
• Call %Customers with the value high activity for the keyword parameter. Verify that the
title is HIGH ACTIVITY Customers and that the report contains 461 rows.
• Call %Customers without passing a parameter value. Verify that title is INACTIVE
Customers. How many rows are in the report?

Level 2
2. Using a Macro to Generate PROC MEANS Code
a. Open m104p02.sas from the practices folder. Submit the program and review the results.
Verify that the mean value of Total_Retail_Price for orders submitted by customer 51 is
314.74.
b. Convert the code to a macro named Orderstats that accepts the keyword parameters listed
below. Set default values for all parameters so that the code reproduces the original report
when called without parameter values. Modify the PROC MEANS code to reference the
parameters.
• var for the VAR statement variable list
• class for the CLASS statement variable list
• stats for the statistics to be calculated
• decimals for the MAXDEC= value
c. Call the %Orderstats macro without passing parameter values. Verify that the mean value of
Total_Retail_Price for Customer 51 is the same as in part a.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.1 Defining and Calling a Macro 4-21

d. Call the macro again, with the parameter values listed below.
• var=CostPrice_Per_Unit
• decimals=0
• stats=mean median
• class=order_type
What is the median value for Order_type 3?

Challenge
3. Using Parameters That Contain Special Characters

a. Open m104p03.sas from the practices folder. Review and submit the program. The macro
completes compilation without errors, but six warning messages are displayed because the
parameter contains a special character. Macro quoting functions are needed to eliminate the
unresolved references.
b. Modify the macro call to protect the parameter value at compile time and call the macro
again. Verify that four warning messages are displayed in the log.
c. You protected the special character during compilation, but during execution, the resolved
value of prodline contains an unprotected special character. The Q macro quoting functions
mask special characters in the result and return quoted text. The function names begin with
%Q (for example, %QSCAN).

Modify the macro definition to use Q functions where needed to eliminate all warning
messages from the log. Submit the modified code and verify that there are no error or
warning messages in the log.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-22 Lesson 4 Working with Macro Programs

4.2 Macro Variable Scope

Macro Variable Scope

Every macro
variable has a scope.
Global or local scope
impacts where the
macro variable is stored
and how long it exists.

global local

38
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Global Symbol Table


Global Symbol Table
Name Value
DSN sashelp.cars
OBS 5
global symbol table SYSDATE 01DEC2019 global macro variables

• created when SAS is invoked


• deleted when the SAS session ends

39
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-23

Global Symbol Table


Global Symbol Table
Name Value
DSN sashelp.cars
OBS 5
global symbol table SYSDATE 01DEC2019 global macro variables

• available during SAS session


• created outside a macro definition using
- %LET statement
- CALL SYMPUTX routine
- SQL INTO clause
- %GLOBAL statement

40
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope

%GLOBAL var1 var2…; • creates macro variables in the global symbol table
• does not assign or modify values
• is valid anywhere in a program
If the variable already exists, its value is unchanged.

CALL SYMPUTX(macro-variable-name, value , 'G') Optional third argument


creates macro variables in
the global symbol table.

41
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

To create a read-only macro variable, specify the READONLY option in the %GLOBAL statement.
The READONLY option both creates a new macro variable in the global symbol table and assigns a
value. Variables created with the READONLY option cannot be modified or deleted for the duration
of the SAS session. When the READONLY option is used, you can list only one macro variable in
the %GLOBAL statement.
%global / readonly var=5;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-24 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope: %GLOBAL


Global Symbol Table
%global name x; Name Value
NAME John Doe
X

If the macro variable


doesn’t exist, it is added
to the global symbol
table with a null value.

42
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Local Symbol Tables


Local Symbol Table
Name Value
DSN sashelp.cars
local symbol table OBS 5 local macro variables

• created when
- a macro with parameters is called
- a local macro variable is created
• deleted when the macro stops execution

43
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-25

Local Symbol Tables


Local Symbol Table
Name Value
DSN sashelp.cars
local symbol table OBS 5 local macro variables

• available only during macro execution


• created within a macro definition using
- parameters
- %LET statement
- CALL SYMPUTX routine
- SQL INTO clause
- %LOCAL statement

44
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope

%LOCAL var1 var2 …; • creates macro variables in the local symbol table
• does not assign or modify values
• is valid only inside a macro definition
If the variable already exists, its value is unchanged.

CALL SYMPUTX(macro-variable-name, value , 'L') Optional third argument


creates macro variables in
the local symbol table.

45
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-26 Lesson 4 Working with Macro Programs

Macro Variable Scope

Macro variables inside a


macro definition can have
either global or local scope.

global local

46
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Implicit Scope when Creating Macro Variables


%macro test; Is X in LOCAL
%let x=1; symbol table? Yes Set LOCAL X to 1
%mend test;
No
%test

Is X in GLOBAL
symbol table? Yes Set GLOBAL X to 1

No

Create X in LOCAL
table, set value to 1

47
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-27

Implicit Scope when Creating Macro Variables


%macro test; Global Symbol Table
%let x=1; Name Value
%mend test; NAME John Doe
%test
Local Symbol Table
If X doesn't exist in the Name Value
global symbol table, then X 1
it would be created in
the local symbol table.

48
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Implicit Scope when Creating Macro Variables


%macro test; Global Symbol Table
%let x=1; Name Value
%mend test; NAME John Doe
%test
Local Symbol Table
When the %Test macro Name Value
finishes execution, the X 1
local symbol table is
deleted.

49
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-28 Lesson 4 Working with Macro Programs

4.04 Activity
Open m104a04.sas from the activities folder and perform the following
tasks:
1. Notice that the %LET statement outside the %Test macro program sets
the value of X to OutsideMacro. Then the %LET statement inside the
%Test macro program sets the value of X to InsideMacro.
2. Submit the program and examine the log. What is the value of X before,
during, and after macro execution?

50
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Implicit Scope when Creating Macro Variables


%let x=0; Global Symbol Table
Name Value
%macro test; NAME John Doe
%let x=1; If X does exist in the
%mend test; global symbol table, then X 0 1
%LET updates the value.
%test
Local Symbol Table
Name Value
A local symbol table is
not created.

52
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-29

Controlling Macro Variable Scope

%macro test; Global Symbol Table (SAS Session)


%global x; Name Value
%let x=InsideMacro;
%mend test;

%test
What happens if X
is explicitly defined
as global scope?

53
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.05 Question
When the %Test macro executes, will it have a local symbol table?
 Yes
 No

%macro test;
%global x;
%let x=InsideMacro;
%mend test;

%test

54
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-30 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope

%macro test; Global Symbol Table (SAS Session)


%global x; Name Value
%let x=InsideMacro; X InsideMacro
%mend test;

%test
This %LET statement
explicitly creates or updates
X in the global symbol table.

56
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope

%let x=OutsideMacro; Global Symbol Table (SAS Session)


Name Value
%macro test; X OutsideMacro
%local x;
%let x=InsideMacro;
%mend test;

%test What happens if X


is explicitly defined
as local scope?

57
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-31

Controlling Macro Variable Scope

%let x=OutsideMacro; Global Symbol Table (SAS Session)


Name Value
%macro test; X OutsideMacro
%local x;
%let x=InsideMacro; Local Symbol Table (Test Macro)
%mend test;
Name Value
%test X

58
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope

%let x=OutsideMacro; Global Symbol Table (SAS Session)


Name Value
%macro test; X OutsideMacro
%local x;
%let x=InsideMacro; Local Symbol Table (Test Macro)
%mend test;
Name Value
%test X InsideMacro

59
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-32 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope

%let x=OutsideMacro; Global Symbol Table (SAS Session)


Name Value
%macro test; X OutsideMacro
%local x; The value of X is
%let x=InsideMacro; unchanged.
%mend test;

%test
The local symbol table is
deleted when the macro
ends execution.

60
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Viewing Symbol Tables

%let x=OutsideMacro; 73 %let x=OutsideMacro;


74
%macro test; 75 %macro test;
76 %local x;
%local x;
77 %let x=InsideMacro;
%let x=InsideMacro; 78 %put _local_;
%put _local_; 79 %mend test; %PUT statements can
%mend test; 80 be used to view the
81 %test
%test TEST X InsideMacro
contents of the local
%put _global_; 82 %put _global_; or global symbol table.
...
GLOBAL X OutsideMacro
...

61
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-33

4.06 Activity
Open m104a06.sas from the activities folder and perform the following
tasks:
1. Review the program. Notice that the %Test macro includes a parameter
named X. X is assigned different values before and during the macro
call.
2. Submit the program and examine the log to view the value of X before,
during, and after macro execution.
3. What is the scope of the X parameter in the %Test macro?
4. Add a %GLOBAL statement before the %PUT statement in the %Test
macro definition to explicitly declare X as global scope. Does the
program run successfully?
62
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Variable Scope

The scope of a macro


variable also determines
how the macro
processor resolves
references to it.

global local

65
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-34 Lesson 4 Working with Macro Programs

Resolving Macro Variables


%macro test; Is X in LOCAL Resolve LOCAL X
%put &x; symbol table? Yes
value
%mend test;
No

Is X in GLOBAL Resolve GLOBAL X


symbol table? Yes
value

No

Return tokens to Word WARNING: Apparent symbolic


Scanner, WARNING in log reference X not resolved.

66
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x);
%inner(&x)
%put _user_;
%mend outer;
%macro inner(y); What is the impact of
%let x=2; macro variable scope
%let z=1; when calling a macro
%put _user_;
%mend inner; within another macro?

67
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-35

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2;
%let z=1;
%put _user_;
%mend inner;
%let x=1;

68
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2;
%let z=1;
%put _user_;
%mend inner;
%let x=1;
%outer(&x)

69
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-36 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 1
%mend inner;
%let x=1;
%outer(1)

70
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 1
%mend inner;
%let x=1;
%outer(1)

71
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-37

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(1) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 1
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1

72
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 1
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
No X here

73
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-38 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
Found X here!

74
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
No Z here

75
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-39

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
No Z here

76
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
No Z here

77
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-40 Lesson 4 Working with Macro Programs

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
Create Z here Z 1

78
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1; Local Symbol Table (Inner Macro)
%outer(1) Name Value
Y 1
INNER Y 1
Z 1
INNER Z 1
OUTER X 2
...
GLOBAL X 1 79
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-41

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2; Local Symbol Table (Outer Macro)
%let z=1; Name Value
%put _user_; X 2
%mend inner;
%let x=1;
%outer(1)

OUTER X 2
...
GLOBAL X 1

80
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Controlling Macro Variable Scope


%macro outer(x); Global Symbol Table (SAS Session)
%inner(&x) Name Value
%put _user_;
X 1
%mend outer;
%macro inner(y);
%let x=2;
%let z=1;
%put _user_;
%mend inner;
%let x=1;
%outer(1)
%put _user_;

GLOBAL X 1

81
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-42 Lesson 4 Working with Macro Programs

Practice

Level 1

4. Understanding Symbol Tables

Without submitting the programs, identify in which symbol table the macro variable Zip is
located. Assume that each example is submitted in its own SAS session.
a.
%let Zip=27513;
%macro whereis;
%let state=%sysfunc(zipnamel(&Zip));
%put The Zip Code &Zip is in &state;
%mend whereis;

%whereis
b.
%macro whereis;
%let Zip=10312;
%let state=%sysfunc(zipnamel(&Zip));
%put The Zip Code &Zip is in &state;
%mend whereis;

%whereis
c.
%macro whereis(Zip);
%let state=%sysfunc(zipnamel(&Zip));
%put The Zip Code &Zip is in &state;
%mend whereis;

%whereis(91219)

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.2 Macro Variable Scope 4-43

Level 2

5. Controlling Macro Variable Scope


a. Open m104p05.sas from the practices folder. Notice that macro variables are created
inside the %Scope macro using %LET statements. Highlight the code in Section 1, run the
selection, and review the log.
Note: The log labels global macro variables as GLOBAL and local macro variables as
SCOPE.
• In which symbol table were the macro variables created?
b. Find Section 2 in the program. Notice that macro variables are created inside the %Scope
macro using the SQL INTO clause. Highlight the code in Section 2, run the selection, and
review the log.
• In which symbol table were the macro variables created?
c. Find Section 3 in the program. Notice that macro variables are created inside the %Scope
macro using the CALL SYMPUTX routine in a DATA step. Highlight the code in Section 3,
being sure to include the %SYMDEL statement. Run the selection, and review the log.
• In which symbol table were the macro variables created?
d. Add a %LOCAL statement before the DATA step to define a macro variable named x.
Highlight the code in Section 3, run the selection, and review the log.
• In which symbol table were the macro variables created?
e. Delete the %LOCAL statement and modify the CALL SYMPUTX statement to specify macro
variables should be created in the local symbol table. Highlight the code in Section 3, run the
selection, and review the log.
Note: The %SYMDEL statement generates warnings because the macro variables listed
are not currently in the global symbol table.
• In which symbol table were the macro variables created?

Challenge

6. Debugging Macro Variable Scope Issues


a. Open m104p06.sas from the practices folder. Review and submit the program. Why does it
fail?
b. Fix the program and resubmit.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-44 Lesson 4 Working with Macro Programs

4.3 Conditional Processing

Conditional Processing of Data


data Europe USA Asia;
set sashelp.cars;
if Origin="Europe" then output Europe;
else if Origin="USA" then output USA;
else output Asia;
run; IF-THEN statements in the
DATA step enable us to
execute code conditionally
for each row processed in
the data.

85
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Conditional Processing of Text


How can I compile
data sports; and execute parts of
set sashelp.cars; my program
where Type="Sports";
AvgMPG=mean(MPG_City, MPG_Highway); conditionally?
run;

title "Sports Cars";


proc print data=sports noobs;
var Make Model AvgMPG MSRP EngineSize;
run;
title;
IF the DATA step THEN run the
proc sgplot data=sports; rest of the
scatter x=MSRP y=EngineSize; runs successfully program
run;

86
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-45

Conditional Processing of Text

%IF <expression> %THEN <action>

Macro conditional
statements can be
used either inside or
outside a macro
definition.

87
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Conditional Processing of Text


%IF expression %THEN action-1;
%ELSE action-2; • %IF-%THEN can be used to execute
one statement.
• Use a %DO group to execute more
%IF expression %THEN %DO; than one statement conditionally.
action-1 • %ELSE %IF nested conditions are
%END; allowed.
%ELSE %IF expression %THEN %DO; • %ELSE or %ELSE %DO is optional.
action-2
%END;
%ELSE %DO; inside a
action-3 macro
definition
%END;
88
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-46 Lesson 4 Working with Macro Programs

Conditional Processing of Text

%IF expression %THEN %DO; • must use a %DO group


action-1 • cannot use %ELSE %IF nested
%END; conditions
%ELSE %DO; • %ELSE %DO is optional.
action-2
%END;
outside a
macro
definition

89
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

You must be running SAS 9.4M5 or later to use %IF outside of a macro definition.
Note: You cannot use the macro IN operator as part of an %IF statement outside of a macro
definition.

Conditional Processing of Text

data sports; If the DATA step runs


set sashelp.cars; without error, compile and
where Type="Sports"; execute the rest of the
AvgMPG=mean(MPG_City, MPG_Highway); program.
run;

title "Sports Cars";


proc print data=sports noobs;
var Make Model AvgMPG MSRP EngineSize;
run;
title;
proc sgplot data=sports;
scatter x=MSRP y=EngineSize;
run;

90
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-47

Conditional Processing of Text


If the DATA step generates an
data sports; error, write a custom error
set sashlp.cars;
where Type="Sports"; message to the log and do not
AvgMPG=mean(MPG_City, MPG_Highway); execute the rest of the program.
run;

title "Sports Cars";


proc print data=sports noobs;
ERROR:
var Make Model AvgMPG Libref
MSRP SASHLP is not assigned.
EngineSize;
run; ERROR: The rest of the program will
title; not execute.
proc sgplot data=sports;
scatter x=MSRP y=EngineSize;
run;

91
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Conditional Processing of Text


The automatic macro
data sports; variable Syserr can
set sashlp.cars;
where Type="Sports"; help determine
AvgMPG=mean(MPG_City, MPG_Highway); whether the DATA step
run; runs without error.

title "Sports Cars";


proc print data=sports noobs;
var Make Model AvgMPG MSRP EngineSize;
run;
title;
proc sgplot data=sports; SYSERR=0 if the step ran
scatter x=MSRP y=EngineSize; without errors. SYSERR≠0 if
run; the step generated an error.

92
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-48 Lesson 4 Working with Macro Programs

Conditional Processing of Text


data sports; syntax error
set sashlp.cars;
where Type="Sports";
AvgMPG=mean(MPG_City, MPG_Highway);
run;

%if &syserr ne 0 %then %do;


%put ERROR: The rest of the program will not execute;
%end;
%else %do;
title "Sports Cars";
proc print data=sports noobs;
...
run; ERROR: The rest of the program will not execute
%end;

93
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d03.sas

Conditional Processing of Text


data sports;
set sashelp.cars;
where Type="Sports";
AvgMPG=mean(MPG_City, MPG_Highway);
run;

%if &syserr ne 0 %then %do;


%put ERROR: The rest of the program will not execute;
%end;
%else %do;
title "Sports Cars";
proc print data=sports noobs;
...
run;
%end;

94
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-49

4.07 Activity
Open m104a07.sas from the activities folder and perform the following tasks:
1. Notice that there is a missing semicolon after the DATA statement, which
causes a syntax error. If there is a syntax error in the first DATA step, then
the %PUT statement should execute and write a custom error message to
the log, and the remaining PROC steps should not execute.
2. Run the program and look at the log. Notice that although there was an
error in the DATA step, SAS still attempted to execute PROC PRINT and
PROC SGPLOT.
3. Identify the syntax error in the macro %IF statement. Fix the error and run
the program again to confirm that the %PUT statement is executed.

95
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Scenario: Nested Conditional Processing

miles per
USA
hour
Origin
Asia or kilometers
Europe per liter
We want to calculate
fuel efficiency
differently depending
on the value of Origin.

97
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-50 Lesson 4 Working with Macro Programs

Scenario: Nested Conditional Processing


if &loc is %put ERROR: Provide a value for Origin.;
%put ERROR- Valid values: Asia, Europe, USA;
null

data fuel_&loc; AvgMPG: Average


set sashelp.cars; miles per gallon
where Origin="&loc";
else if &loc AvgMPG=mean(MPG_City, MPG_Highway);
keep Make Model Type AvgMPG;
is USA run;

data fuel_&loc; AvgKmL: Average


set sashelp.cars; kilometers per liter
else if &loc where Origin="&loc";
is Asia or AvgKmL=mean(MPG_City, MPG_Highway)*.425;
Europe keep Make Model Type AvgKmL;
run;
98
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a08.sas

Scenario: Nested Conditional Processing


%macro avgfuel(loc);

if &loc is null
Nested
conditional steps
else if &loc is must be included
USA inside a macro
definition.
else if &loc is
Asia or Europe

%mend avgfuel;

99
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-51

Conditional Processing of Program Steps


&macro-var= is null
&macro-var EQ It is a good
practice to account
&macro-var ~= is not null for possible null
values.
&macro-var NE

%macro avgfuel(loc);
%if &loc= %then %do;
%put ERROR: Provide a value for Origin.;
%put ERROR- Valid values: Asia, Europe, USA;
%end;
...

100
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a08.sas

Conditional Processing of Program Steps

%RETURN; terminate macro


execution

%macro avgfuel(loc);
%if &loc= %then %do;
%put ERROR: Provide a value for Origin.;
%put ERROR- Valid values: Asia, Europe, USA;
%return;
%end;
...
proc print data=fuel_&loc;
run;

101
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-52 Lesson 4 Working with Macro Programs

Conditional Processing of Program Steps

Remember that text


%macro avgfuel(loc); is not quoted in
... macro comparisons.
%else %if &loc=USA %then %do;
data fuel_&loc;
set sashelp.cars;
where Origin="&loc";
AvgMPG=mean(MPG_City, MPG_Highway);
keep Make Model Type AvgMPG;
run;
%end;
... If &loc is USA, this step
is tokenized, compiled,
and executed.

102
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a08.sas

Conditional Processing of Program Steps

If &loc is not null or USA, this


... step is tokenized, compiled,
%else %do; and executed.
data fuel_&loc;
set sashelp.cars;
where Origin="&loc";
AvgKmL=mean(MPG_City, MPG_Highway)*.425;
keep Make Model Type AvgKmL;
run;
%end;
%mend avgfuel;

103
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-53

4.08 Activity
Open m104a08.sas from the activities folder and perform the following
tasks:
1. Review the program and notice that different DATA steps run,
depending on the value of the loc parameter. The %avgfuel macro call
at the end of the program assigns Europe to the loc parameter.
2. Run the program and view the log. Notice the MPRINT messages
displaying the final program that was compiled and executed.
3. Call the %avgfuel macro with usa as the parameter value. View the log.
Which DATA step was compiled and executed?

104
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Macro Logic
OPTIONS MLOGIC|NOMLOGIC; MLOGIC prints detailed
messages in the log regarding
73 options mprint mlogic; the flow of the macro logic.
74 %avgfuel(usa)
MLOGIC(AVGFUEL): Beginning execution.
MLOGIC(AVGFUEL): Parameter LOC has value usa
MLOGIC(AVGFUEL): %IF condition &loc=USA is FALSE
MPRINT(AVGFUEL): data fuel_usa;
MPRINT(AVGFUEL): set sashelp.cars;
MPRINT(AVGFUEL): where Origin="usa";
MPRINT(AVGFUEL): AvgKmL=mean(MPG_City, MPG_Highway)*.425;
MPRINT(AVGFUEL): keep Make Model Type AvgKmL;
MPRINT(AVGFUEL): run;
106
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-54 Lesson 4 Working with Macro Programs

%IF Expressions

Convert the parameter


%macro avgfuel(loc); value to uppercase at
%let loc=%upcase(&loc); the beginning of the
... macro to remove case
%if &loc=USA %then %do; sensitivity.
data fuel_&loc;
set sashelp.cars;
where upcase(Origin)="&loc";
...

Global Symbol Table


%avgfuel(usa)
Name Value
LOC USA
107
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%IF Expressions
How can I explicitly
specify if &loc is
either Asia or
Europe? AND or OR can be used
to build compound
expressions.

%else %if &loc=ASIA or &loc=EUROPE %then %do;

108
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-55

%IF Expression

How can I specify if To enable the macro IN


&loc is either Asia operator, add the
or Europe? MINOPERATOR option.

%macro avgfuel(loc) / minoperator;


...
%else %if &loc in ASIA EUROPE %then %do;

List the possible values


separated by spaces without
quotes or parentheses.
109
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

A null value cannot be provided in the list of values after the macro IN operator. Null values must be
processed first with a separate %IF condition.
To enable the macro IN operator in open code, you must submit the following OPTIONS statement.
It is recommended that you disable the macro IN operator after it is used.
options minoperator;
%if &sysday in Saturday Sunday %then %do;
%put It is the weekend;
%end;
options nominoperator;
If you do not include the MINOPERATOR option, you likely will see a similar error message:
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: &loc in Asia Europe

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-56 Lesson 4 Working with Macro Programs

%IF Expressions
How can I specify if
&loc is any value
other than Asia or Use parentheses to
Europe? isolate the IN
expression.

%macro avgfuel(loc) / minoperator;


...
%else %if not (&loc in ASIA EUROPE) %then %do;

Use the NOT operator


to reverse the logic of
the expression.
110
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Conditional Processing of Statements


%macro avgfuel(loc);
%if &loc=USA %then %do;
data fuel_&loc;
set sashelp.cars; Notice that only the
where Origin="&loc"; assignment and
AvgMPG=mean(MPG_City, MPG_Highway);
keep Make Model Type AvgMPG; KEEP statements
run; differ between the
%end;
two DATA steps.
%else %do;
data fuel_&loc;
set sashelp.cars;
where Origin="&loc";
AvgKmL=mean(MPG_City, MPG_Highway)*.425;
keep Make Model Type AvgKmL;
run;
%end;
...
%mend avgfuel;

111
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-57

Conditional Processing of Statements


%IF-%THEN can
conditionally execute
data fuel_&loc; statements within a step.
set sashelp.cars;
where upcase(Origin)="&loc";
%if &loc=USA %then %do;
AvgMPG=mean(MPG_City, MPG_Highway);
keep Make Model Type AvgMPG;
%end; OR
%else %do;
AvgKmL=mean(MPG_City, MPG_Highway)*.425;
keep Make Model Type AvgKmL;
%end;
run;

112
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d04.sas

Conditional Processing within a Statement


%IF-%THEN can also conditionally
insert text within a statement.

format format AvgMGP 4.1;


%if &loc=USA %then %do;
AvgMGP USA
%end;
%else %do;
AvgKmL Other
%end;
4.1; format AvgKml 4.1;

113
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d04.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-58 Lesson 4 Working with Macro Programs

Conditional Processing

Scenario
In this demonstration, we use macro conditional processing to select which program steps are
generated, select which individual statements within a SAS program step are executed, and
conditionally modify portions of a SAS statement.

Files
• m104d05.sas

Syntax

%IF expression %THEN %DO;


action-1
%END;
%ELSE %IF expression %THEN %DO;
action-2
%END;
%ELSE %DO;
action-3
%END;

Notes
• Conditional processing can be used to selectively generate entire program steps, individual
program statements, or portions of a program statement.

Demo

1. Open m104d05.sas from the demos folder. This program creates the %StormChart macro
definition and accepts three parameters (Basin, Season, and MaxWind). When executed, the
macro produces a bar chart. Run the program to compile the macro and call %StormChart with
parameter values NA, 2016, and 80. Review the results and log to confirm that the macro runs
successfully.
2. Modify the macro to provide a storm category rather than maximum wind speed as an input
parameter. Use macro conditional processing to assign the appropriate value to a macro variable
named MaxWind based on the value of Cat.

a. Replace the MaxWind parameter with Cat.

b. Add a %LOCAL statement to create MaxWind as a local macro variable.


c. Add conditional logic to examine the value of the Cat macro variable and assign the
appropriate value to MaxWind.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-59

Note: Copy and paste the statements from the comment block at the bottom of the
program.
%macro stormchart(basin, season, cat);
%local maxwind;
%if &cat=5 %then %let maxwind=157;
%else %if &cat=4 %then %let maxwind=130;
%else %if &cat=3 %then %let maxwind=111;
%else %if &cat=2 %then %let maxwind=96;
%else %if &cat=1 %then %let maxwind=74;
d. Run the %StormChart macro definition and review the log to verify that it compiled properly.
e. Add the MLOGIC and MPRINT options to the OPTIONS statement to enable detailed
messages in the log. Highlight the statement and run the selection.
options mcompilenote=all mlogic mprint;
f. Call %StormChart for NA, 2016, and 3. Run the selected code, and then review the log and
output to verify that the chart includes four storms.
%stormchart(NA,2016,3)
g. Modify the %StormChart macro call to specify values for only the first two parameters.
Highlight the macro call and run the selected code. Note that several errors are in the log
because no value is provided for the Cat or MaxWind macro variables.
%stormchart(EP,2015)
3. Modify the %StormChart macro program so that if no value is provided for the Cat parameter,
all storms are included for the selected Basin and Season and the footnote is All Storms
Included.
a. Add %IF and %END statements around the FOOTNOTE statement so that it executes only if
the macro variable Cat value is assigned a value. Add %ELSE and %END statements to
submit an alternative FOOTNOTE statement that prints All Storms Included.
%if &cat ne %then %do;
footnote "Max Wind > &maxwind MPH";
%end;
%else %do;
footnote "All Storms Included";
%end;
b. Modify the WHERE statement in the PROC SGPLOT step so that the MaxWindMPH
criterion is specified only if the Cat parameter is specified.
where Basin="&basin" and Season=&season
%if &cat ne %then %do;
and MaxWindMPH>&maxwind
%end;
;
c. Submit the macro definition to recompile the macro.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-60 Lesson 4 Working with Macro Programs

d. Call the %StormChart macro for EP, 2015. Review the log and results. Verify that the report
includes 26 storms and that the titles and footnote are correct.
%stormchart(EP,2015)
e. Call the %StormChart macro for SI, 2014, 2. Review the log and results. Verify that the
report includes seven storms and that the titles and footnote are correct.
%stormchart(SI,2014,2)
4. Submit an OPTIONS statement to reinstate the NOMLOGIC and NOMPRINT options.

options nomprint nomlogic;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.3 Conditional Processing 4-61

Practice

Level 1

7. Using Macro Conditional Processing to Choose Which SAS Statements Are Generated

a. Open m104p07.sas from the practices folder.


b. Modify the CustomerList macro to test the country parameter. If the value is null, insert the
following statements into the PROC PRINT step:
title "All Customers";
var ID Name Country Type Age_Group;
If the value is not null, insert the following statements into the PROC PRINT step:
title "Customers from Country: &country";
where Country="&country";
var ID Name Type Age_Group;
c. Submit the macro definition and call the macro using a null value. Verify that the title is
correct and 1800 rows were included in the report.

d. Submit the macro call again with a value of AU for the country parameter. How many
customers are included in the report?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-62 Lesson 4 Working with Macro Programs

Level 2

8. Using Macro Conditional Processing in Open Code


a. Open m104p08.sas from the practices folder. Run the program and verify that a temporary
table named Profit and a bar chart are created.
b. Add a LIBNAME statement to create a library named Orion that points to the practices
folder in the course files. Modify the CREATE TABLE statement to write the Profit table to
the Orion library.
c. Add a %PUT statement to write the value of the automatic macro variable Syslibrc to the
log. If the LIBNAME statement ran successfully, the value of Syslibrc is zero. Otherwise, it is
a value other than zero. Run the LIBNAME and %PUT statements.
d. Add macro conditional statements to evaluate the value of Syslibrc. If it is not equal to zero,
then write a custom error to the log indicating the rest of the program will not execute
because of the failure of the LIBNAME statement. Otherwise, run the PROC SQL and
SGPLOT steps.
e. Test the program with and without an error in the LIBNAME statement. If the graph is created
successfully, which Product_Category value has the highest sum of Profit?

Challenge

9. Using Macro Conditional Processing to Test Parameter Values


a. Open m104p09.sas from the practices folder. Examine the %SalesSummary macro
program. Notice that it accepts a single parameter, ot, that indicates the OrderType. Valid
values for OrderType are 1, 2, and 3. Run the program and verify that the macro call runs
successfully when ot is 1, 2, or 3.
b. Use conditional macro statements to test the value of ot. If it is not equal to 1, 2, or 3, then
write the following custom error message to the log. Otherwise, run the rest of the macro
program.
ERROR: <ot value> is not a valid order type. Order type values include 1 (Retail), 2
(Catalog), and 3 (Internet).

c. Call the %SalesSummary macro with a parameter value of 4. Confirm that the error
message is displayed.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-63

4.4 Iterative Processing

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

title "3-Cylinder Cars";


proc print data=sashelp.cars noobs;
where Cylinders=3;
var Cylinders Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;

118
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

%let num=3;
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;

119
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-64 Lesson 4 Working with Macro Programs

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

%macro cylreport(num);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%mend cylreport;

%cylreport(3)
120
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

%macro cylreport(num);
title "&num-Cylinder Cars"; How can I generate
proc print data=sashelp.cars noobs; the report for each
where Cylinders=&num; Cylinder value
var Make Model Type Origin between 3 and 12?
MSRP MPG_City MPG_Highway;
run;
%mend cylreport;

%cylreport(3)
121
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-65

%DO Iterative Statement

%DO index=start %TO stop <%BY increment>;


text and macro language statements %DO loops are
%END; valid only within a
macro definition.
• index is a macro variable.
• start, stop, and increment must be integer values.
• The default for increment is 1.
• index is incremented at %END.
• At the top of the loop, if index > stop, the loop
terminates.

122
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO Iterative Statement Method


#1
%macro allcylinders(start,stop);
%do num=&start %to &stop;
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%end;
%mend allcylinders;
Use a %DO loop inside the macro to
%allcylinders(3,6) execute the program for each value
of Cylinder, 3 through 6.

123
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d06.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-66 Lesson 4 Working with Macro Programs

%DO Iterative Statement


85 %allcylinders(3,6)
MLOGIC(ALLCYLINDERS): Beginning execution.
MLOGIC(ALLCYLINDERS): Parameter START has value 3
MLOGIC(ALLCYLINDERS): Parameter STOP has value 6
MLOGIC(ALLCYLINDERS): %DO loop beginning; index variable NUM; start value is 3;
stop value is 6; by value is 1.
MPRINT(ALLCYLINDERS): title "3-Cylinder Cars";
MPRINT(ALLCYLINDERS): proc print data=sashelp.cars noobs;
MPRINT(ALLCYLINDERS): where Cylinders=3;
MPRINT(ALLCYLINDERS): var Make Model Type Origin MSRP MPG_City MPG_Highway;
MPRINT(ALLCYLINDERS): run;
NOTE: There were 1 observations read from the data set SASHELP.CARS.
WHERE Cylinders=3;
...
MLOGIC(ALLCYLINDERS): %DO loop index variable NUM is now 4; loop will
iterate again.
MPRINT(ALLCYLINDERS): title "4-Cylinder Cars";
...

124
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO Iterative Statement Method


#2
%macro cylreport(num);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%mend cylreport;

%macro allcylinders(start,stop);
%do num=&start %to &stop;
%cylreport(&num)
%end; Create a driver macro to call
%mend allcylinders; the %CylReport macro once for
each value, 3 through 6.
%allcylinders(3,6)
125
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d06.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-67

Iterative %DO Loops

Scenario
In this demonstration, we use macro %DO iterative processing to produce the storm report for
a range of years.

Files
• m104d07.sas

Syntax

%DO index = start %TO stop;


text to be generated
%END;

Notes
• Iterative processing can be used to generate repetitive program statements.
• A macro can call another macro for execution.

Demo
1. Open m104d07.sas from the demos folder. This program creates the %StormChart macro
definition, which accepts two parameters: Basin and Season. The macro generates a bar chart
representing the number of storms by storm type for the selected Basin and Season.
2. Run the macro definition and the macro call with Basin as NA and Season as 2015. Verify that
the bar chart is created and includes 12 storms.
3. Create a driver macro named StormChartRange that calls the %StormChart macro for a range
of years.

a. Start with a %MACRO statement that includes the parameters Basin, Start, and Stop.
b. Add a %DO loop with an index variable named Season that ranges from the Start macro
variable value to the Stop macro variable value. Inside the %DO loop, call the %StormChart
macro with the parameter values provided by Basin and Season.
c. Add a %MEND statement to complete the macro definition.

d. Compile the %StormChartRange macro.


%macro stormchartrange(Basin, Start, Stop);
%local Season;
%do Season=&Start %to &Stop;
%stormchart(&Basin, &Season)
%end;
%mend stormchartrange;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-68 Lesson 4 Working with Macro Programs

4. Test the %StormChartRange macro, generating reports for a range of seasons for different
basins.
a. Submit the following macro call and verify the results:
%stormchartrange(EP,2011,2013)
b. Submit the following macro call and verify the results:
%stormchartrange(NA,2010,2016)

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-69

4.09 Activity
Open m104a09.sas from the activities folder and perform the following tasks:
1. Run the program and examine the log. Identify and correct the syntax
error and rerun the program. Verify that the macro compiled successfully.
2. Call the %AllCylinders macro with a start value of 3 and stop value of 12.
%allcylinders(3,12)

3. Examine the reports and log. Why are there some values between
3 and 12 that did not produce reports?

127
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Iterative Processing for a List

How can I process


title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs; a list of values in a
where Cylinders=&num; %DO loop?
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
Valid values for Cylinders are
3, 4, 5, 6, 8, 10, and 12.

130
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-70 Lesson 4 Working with Macro Programs

%DO Loop with Indirect References Method


#1
%macro allcylinders; Local Symbol Table
proc sql noprint; Name Value
select distinct Cylinders VAL1 3
into :val1-
from sashelp.cars VAL2 4
where Cylinders ne .; VAL3 5
quit; VAL4 6
...
VAL5 8
VAL6 10
Use PROC SQL to create a VAL7 12
numbered series of macro SQLOBS 7
variables to store each
unique value in the list.
131
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

%DO Loop with Indirect References


...
%local i; Local Symbol Table
%do i=1 %to &sqlobs; Name Value
VAL1 3
title "&&val&i-Cylinder Cars";
proc print data=sashelp.cars noobs; VAL2 4
where Cylinders=&&val&i; VAL3 5
var Make Model Type Origin VAL4 6
MSRP MPG_City MPG_Highway;
run; VAL5 8
VAL6 10
%end; Use a %DO loop with
VAL7 12
%mend allcylinders; indirect references to
process each VALn SQLOBS 7
macro variable.

132
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-71

%DO Loop with Indirect References


...
%local i; Local Symbol Table
%do i=1 %to &sqlobs; Name Value
VAL1 3
title "&&val&i-Cylinder Cars";
proc print data=sashelp.cars noobs; VAL2 4
where Cylinders=&&val&i; VAL3 5
var Make Model Type Origin VAL4 6
MSRP MPG_City MPG_Highway;
run; VAL5 8
VAL6 10
%end; VAL7 12
%mend allcylinders;
SQLOBS 7
&&val&i &val1 3 I 1

133
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

%DO Loop with Indirect References


...
%local i; Local Symbol Table
%do i=1 %to &sqlobs; Name Value
VAL1 3
title "&&val&i-Cylinder Cars";
proc print data=sashelp.cars noobs; VAL2 4
where Cylinders=&&val&i; VAL3 5
var Make Model Type Origin VAL4 6
MSRP MPG_City MPG_Highway;
run; VAL5 8
VAL6 10
%end; VAL7 12
%mend allcylinders;
SQLOBS 7
&&val&i &val2 4 I 2

134
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-72 Lesson 4 Working with Macro Programs

%DO Loops with Indirect References

Scenario
In this demonstration, we use macro %DO iterative processing to produce the storm report for
a range of years.

Files
• m104d09.sas

Syntax

%DO index = start %TO stop;


text to be generated
%END;

Notes
• Macro %DO loops can be used along with indirect macro variable references to execute code for
a list of values.
• Use PROC SQL to generate a numbered sequence of macro variables to store the unique values
within a column for processing in the %DO loop.

Demo
1. Open m104d09.sas from the demos folder. This program creates the %StormChart macro
definition, which accepts two parameters: Basin and Season. The macro generates a bar chart
representing the number of storms by storm type for the selected Basin and Season.
2. Run the macro definition and the macro call with Basin as NA and Season as 2015. Verify that
the bar chart is created and includes 12 storms.

3. Create a driver macro named AllBasins that executes the %StormChart macro for each
individual Basin value. Include a positional parameter named Year. Use %LOCAL to explicitly
define i as a local macro variable.
%macro allbasins(year);
%local i;
4. Add a PROC SQL step to select the Basin column from the mc1.storm_basin_codes table.
Load each value into a numbered series of macro variables starting with Basin1.
proc sql noprint;
select basin
into :basin1-
from mc1.storm_basin_codes;
quit;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-73

5. Use a %DO loop to create an index variable I that ranges from 1 to the value of &sqlobs. Inside
the loop, call the %StormChart macro. The Basin parameter uses an indirect reference of
&&Basin&i. The second parameter is the value of &year. Close the %DO loop and the macro
definition. Run the macro definition and confirm that it compiles successfully.
%do i=1 %to &sqlobs;
%stormchart(&&basin&i, &year)
%end;
%mend allbasins;
6. Call the %AllBasins macro with 2015 as the parameter value. Run the macro call and confirm
that six bar charts are produced.
%allbasins(2015)
7. View the log and carefully read the MLOGIC messages. Notice that in the first iteration of the
macro %DO loop when &I is 1, &&Basin&i first resolves to &Basin1, which then resolves to NA.
In the second iteration, &&Basin&i resolves to WP.
...
MLOGIC(ALLBASINS): %DO loop beginning; index variable I; start value is 1;
stop value is 6; by value is 1.
MLOGIC(STORMCHART): Beginning execution.
MLOGIC(STORMCHART): Parameter BASIN has value NA
MLOGIC(STORMCHART): Parameter SEASON has value 2015
...
MLOGIC(ALLBASINS): %DO loop index variable I is now 2; loop will iterate again.
MLOGIC(STORMCHART): Beginning execution.
MLOGIC(STORMCHART): Parameter BASIN has value WP
...

8. Call the %AllBasins macro again with 2009 as the parameter value. Confirm that six charts are
generated.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-74 Lesson 4 Working with Macro Programs

%DO %WHILE Statement Method


#2

%DO %WHILE (condition);


text and macro program statements
%END;

• condition is a macro expression that resolves to TRUE or FALSE.


• condition is evaluated at the top of the loop (at %DO).
• If condition is true, statements between %DO and %END are executed.
• If condition is false, the loop terminates.
• If condition is false when entering the loop, statements between %DO
and %END never execute.

136
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list); The list parameter will be
%local i; a delimited list of values
%let i=1; provided in the macro call.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12)
137
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-75

%DO %WHILE Statement


%macro cyllist(list);
%local i; I is a local macro variable that will
%let i=1; start with a value of 1.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 1
138
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

%DO %WHILE Statement


%macro cyllist(list);
%local i; %SCAN examines the &List
%let i=1; TRUE string and returns the first
%do %while (%scan(&list, &i) ne ); value, 3. The loop executes.
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 1
139
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104d08.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-76 Lesson 4 Working with Macro Programs

%DO %WHILE Statement


%macro cyllist(list);
%local i; The first value in &List is assigned
%let i=1; to the Num macro variable.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 1
140 NUM 3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list);
%local i; The report is generated for
%let i=1; Cylinders=3.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 1
141 NUM 3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-77

%DO %WHILE Statement


%macro cyllist(list);
%local i;
%let i=1; Increment I by 1.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 2
142 NUM 3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list); %SCAN examines the &List
%local i; string and returns the
%let i=1; TRUE
second value, 4. The loop
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i); executes again.
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 2
143 NUM 3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-78 Lesson 4 Working with Macro Programs

%DO %WHILE Statement


%macro cyllist(list);
%local i; The second value in &List is
%let i=1; assigned to the Num macro
%do %while (%scan(&list, &i) ne ); variable.
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 2
144 NUM 4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list);
%local i; The report is generated for
%let i=1; Cylinders=4.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 2
145 NUM 4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-79

%DO %WHILE Statement


%macro cyllist(list);
%local i;
%let i=1; Increment &I by 1.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 3
146 NUM 4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list);
%local i; When &I is 7, &Num is the last
%let i=1; value in &List. The report is
%do %while (%scan(&list, &i) ne ); generated for Cylinders=12.
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 7
147 NUM 12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-80 Lesson 4 Working with Macro Programs

%DO %WHILE Statement


%macro cyllist(list);
%local i;
%let i=1; Increment &I by 1.
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i);
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 8
148 NUM 12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

%DO %WHILE Statement


%macro cyllist(list); %SCAN returns a null value
%local i; because there are only
%let i=1; FALSE
seven values in &List. The
%do %while (%scan(&list, &i) ne );
%let num=%scan(&list, &i); loop stops executing.
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%let i=%sysevalf(&i+1); Local Symbol Table
%end; Name Value
%mend cyllist;
LIST 3 4 5 6 8 10 12
%cyllist(3 4 5 6 8 10 12) I 8
149 NUM 12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-81

4.10 Question
Complete the query to generate a macro variable named List that includes
a space-delimited list of the distinct values of Cylinders.

proc sql noprint;


select distinct Cylinders

from sashelp.cars
where Cylinders ne .;
quit;

%put &=list;

%cyllist(&list)

150
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m104a10.sas

%DO %UNTIL Statement

%DO %UNTIL (condition);


text and macro program statements
%END;

• condition is a macro expression that resolves to TRUE or FALSE.


• condition is evaluated at the bottom of the loop (at %END).
• If condition is false, statements between %DO and %END are executed.
• If condition is true, the loop terminates.
• If condition is true when entering the loop, statements between %DO
and %END are executed once.

152
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-82 Lesson 4 Working with Macro Programs

Practice

Level 1
10. Using Iterative Processing and Indirect Referencing
a. Open m104p10.sas from the practices folder. Review and submit the program. Verify that it
generates a PROC MEANS report for Type 1 orders.
b. Convert the code to a macro named Orders that uses a %DO loop to generate a separate
PROC MEANS step for order types 1, 2, and 3. Add a call to the %Orders macro. Submit the
program and verify that it generates three PROC MEANS reports, one for each order type.
Confirm that the mean of Total_Retail_Price for type 2 orders is 162.43.
c. Modify the program.
• Insert a DATA _NULL_ step after the %MACRO statement to create a series of macro
variables, type1 to typen, where n is the number of order types found in the
mc1.order_type_codes table. For each macro variable name, concatenate the prefix
type with the value of order_type_code. Assign the corresponding value of Order_Type
to the macro variable.
• Create a macro variable named numTypes and assign it the number of type macro
variables created. Hint: Use the END= option in the SET statement.
• Use numTypes as the stop value for the loop.
• Use an indirect reference to include the order type in the title as shown below.
Order Type: Retail Store

d. Submit the program. What is the title of the last report?

Level 2

11. Using a %DO %UNTIL Loop

a. Open m104p11.sas from the practices folder. Review and submit the program. Verify that
the maximum wind speed for the 2015 season was 213 MPH.
b. Modify the %Storms macro to accept a space-separated list of years. Use a %DO %UNTIL
loop and the %SCAN macro function to generate a report for each year in the list. Submit the
macro definition and verify that it completed compilation without errors.
c. Call the %Storms macro to generate a report for the 2011 and 2014 seasons as shown
below.
%storms(2011 2014)
• What was the maximum wind speed in each year?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.4 Iterative Processing 4-83

Challenge

12. Using Iterative Processing in One Macro to Call Another Macro


a. Open m104p12.sas from the practices folder. Review and submit the program. The %Print
macro accepts three parameters and generates a PROC PRINT step that lists the requested
number of rows from the table specified in the parameter values. The macro call requests the
first 10 rows of mc1.orders. Submit the code in Part a and review the results.

b. Part b contains starter code for the %Printlib macro, which accepts a libref and the number
of rows as parameters. The PROC SQL step creates a series of macro variables that contain
the names of the tables in the specified library.
Complete the %Printlib macro by adding an iterative %DO loop that calls the %Print macro
repetitively to print the first numrows rows of every table in the specified library. If the
numrows parameter is not specified, the %Print macro should use the default value for its
keyword parameter.
c. Call %Printlib to list the first 10 rows of every table in the mc1 library.
• What is the name of table in the last PROC PRINT report?
• How many rows are in the last report?

d. Call %Printlib to list every table in the mc1 library. Do not specify a value for numrows.
• What is the name of table in the first PROC PRINT report?
• How many rows are displayed in each report?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-84 Lesson 4 Working with Macro Programs

4.5 Solutions
Solutions to Practices

Section 4.1

1. Defining and Using a Macro with Parameters


/* Part b. */
%macro customers(type);
title "&type Customers";
proc sql number;
select Name, Age_Group, Type
from mc1.customers
where Type contains "&type";
quit;
title;
%mend customers;

%customers(Gold)
%customers(High Activity)

/* Part c. */
%macro customers(type);
%let type=%upcase(&type);
title "&type Customers";
proc sql number;
select Name, Age_Group, Type
from mc1.customers
where upcase(Type) contains "&type";
quit;
title;
%mend customers;

%customers(High Activity)

/* Part d. */
%macro customers(type=inactive);
%let type=%upcase(&type);
title "&type Customers";
proc sql number;
select Name, Age_Group, Type
from mc1.customers
where upcase(Type) contains "&type";
quit;
title;
%mend customers;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-85

%customers(type=High Activity)
%customers()

How many rows are in the final report? The report contains 209 rows.
2. Using a Macro to Generate PROC MEANS Code
%macro orderstats(var=Total_Retail_Price, class=Customer_ID,
stats=mean, decimals=2);
options nolabel;
title 'Order Stats';
proc means data=mc1.orders maxdec=&decimals &stats;
var &var;
class &class;
run;
title;
options label;
%mend orderstats;

%orderstats()

%orderstats(var=CostPrice_Per_Unit, decimals=0,
stats=mean median, class=order_type)
What is the median value for internet (type 3) orders? The median is 26.

3. Using Parameters That Contain Special Characters


/* Part b. */
%prodlist(%nrstr(clothes&shoes))

/* Part c. */
%macro prodlist(prodline);
%let prodline=%qupcase(&prodline);
title "Listing of %qsysfunc(propcase(&prodline, %str( &)))";
proc print data=mc1.products;
where upcase(Product_Line)="&prodline";
var Product_ID Product_name Product_Line;
run;
title;
%mend prodlist;

%prodlist(%nrstr(clothes&shoes))

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-86 Lesson 4 Working with Macro Programs

Section 4.2

4. Understanding Symbol Tables


a. The %LET statement is outside the macro definition, so Zip is stored in the global
symbol table.
b. The %LET statement is inside the macro definition, so Zip is stored in the local
symbol table.
c. The %whereis macro is defined with a parameter, so a local symbol table is created,
and Zip is stored in this local table.
5. Controlling Macro Variable Scope
/* Part a. */
/* Section 1: Macro variables created with %LET */
%macro scope;
%let stormtype1=Some damage;
%let stormtype2=Extensive damage;
%let stormtype3=Devastating damage;
%let stormtype4=Catastrophic damage;
%let stormtype5=Widespread catastrophic damage;
%put _user_;
%mend scope;

%scope

In which symbol table were the macro variables created? Local symbol table

/* Part b. */
/* Section 2: Macro variables created with SQL INTO */
%macro scope;
proc sql noprint;
select damage into :stormtype1-
from mc1.storm_cat
order by category;
quit;

%let num = &sqlobs;


%put _user_;
%mend scope;

%scope

In which symbol table were the macro variables created? Local symbol table

/* Part c. */
/* Section 3: Macro variables created with CALL SYMPUTX */
%macro scope;
data _null_;
set mc1.storm_cat end=last;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-87

call symputx(cat('stormtype',_n_),Damage);
if last=1 then
call symputx('num',_n_);
run;
%put _user_;
%mend scope;

%scope

%symdel stormtype1 stormtype2 stormtype3 stormtype4 stormtype5


num;
In which symbol table were the macro variables created? Global symbol table
The %scope macro does not accept parameters or include any %LET statements, so no
local symbol table is created. Because there is no local symbol table, CALL SYMPUTX
creates the macro variables in the global symbol table.

/* Part d. */
/* Section 3: Macro variables created with CALL SYMPUTX */
%macro scope;
%local x;
data _null_;
set mc1.storm_cat end=last;
call symputx(cat('stormtype',_n_),Damage);
if last=1 then
call symputx('num',_n_);
run;
%put _user_;
%mend scope;

%scope

%symdel stormtype1 stormtype2 stormtype3 stormtype4 stormtype5


num;
In which symbol table were the macro variables created? Local symbol table

/* Part e. */
/* Section 3: Macro variables created with CALL SYMPUTX */
%macro scope;
data _null_;
set mc1.storm_cat end=last;
call symputx(cat('stormtype',_n_),Damage,"L");
if last=1 then
call symputx('num',_n_,"L");
run;
%put _user_;
%mend scope;

%scope

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-88 Lesson 4 Working with Macro Programs

%symdel stormtype1 stormtype2 stormtype3 stormtype4 stormtype5


num;
In which symbol table were the macro variables created? Local symbol table
6. Debugging Macro Variable Scope Issues
A local symbol table is created by the %number_of_rows macro because it includes a
parameter. Therefore, the CALL SYMPUTX routine writes the Numrows macro variable to
the local symbol table, and it is deleted when the macro finishes execution.
%macro number_of_rows(table);
options nonotes;
data _null_;
call symputx("numrows", number, "g");
stop;
set &table nobs=number;
run;
%mend number_of_rows;

%number_of_rows(mc1.customers)
%put mc1.customers has &numrows rows.;

%symdel numrows;
options notes;

Section 4.3

7. Using Macro Conditional Processing to Choose Which SAS Statements Are Generated
%macro customerlist(country);
proc print data=mc1.customers noobs;
%if &country= %then %do;
title "All Customers";
var ID Name Country Type Age_Group;
%end;
%else %do;
title "Customers from Country: &country";
where Country="&country";
var ID Name Type Age_Group;
%end;
run;
%mend customerlist;

%customerlist()
%customerlist(AU)
How many customers are included in the report? 90

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-89

8. Using Macro Conditional Processing in Open Code


libname orion "&path/practices";
%put &=syslibrc;

%if &syslibrc ne 0 %then %do;


%put ERROR: Because of the error in the LIBNAME statement,
the rest of the program will not execute.;
%end;

%else %do;
proc sql;
create table orion.profit as
select o.product_id, Product_Name, Product_Category,
(Total_Retail_Price-(CostPrice_per_Unit*Quantity))
as Profit format=dollar12.2
from mc1.orders as o inner join mc1.products as p
on o.product_id=p.product_id;
quit;

proc sgplot data=orion.profit noautolegend;


hbar Product_Category / response=Profit fillType=gradient
categoryorder=respdesc;
run;
%end;
If the graph is created successfully, which Product_Category value has the highest sum of
Profit? Outdoors

9. Using Macro Conditional Processing to Test Parameter Values


%macro SalesSummary(ot) / minoperator;
%if not (&ot in 1 2 3) %then %do;
%put ERROR: &ot is not a valid order type. Order type values
include 1 (Retail), 2 (Catalog), and 3 (Internet).;
%end;

%else %do;
%if &ot=1 %then %let otdesc=Retail;
%else %if &ot=2 %then %let otdesc=Catalog;
%else %if &ot=3 %then %let otdesc=Internet;

title "Total Retail Price by Year for &OTDesc Sales";


proc means data=mc1.orders sum mean median maxdec=0;
where Order_Type=&ot;
var Total_Retail_Price;
class Order_Date;
format Order_Date year4.;
run;
%end;

%mend SalesSummary;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-90 Lesson 4 Working with Macro Programs

%SalesSummary(1)
%SalesSummary(2)
%SalesSummary(3)
%SalesSummary(4)

Section 4.4

10. Using Iterative Processing and Indirect Referencing


/* Part b. */
%macro orders;
%do i=1 %to 3;
title "Order Type: &i";
proc means data=mc1.orders sum mean maxdec=2;
where Order_Type=&i;
var Total_Retail_Price CostPrice_Per_Unit;
run;
%end;
%mend orders;

%orders

/* Part c. */
%macro orders;
data _null_;
set mc1.order_type_codes end=last;
call symputx(cats("type",Order_type_code),Order_type);
if last=1 then call symputx("numTypes", _n_);
run;
%do i=1 %to &numTypes;
title "Order Type: &&type&i";
proc means data=mc1.orders sum mean maxdec=2;
where Order_Type=&i;
var Total_Retail_Price CostPrice_Per_Unit;
run;
%end;
%mend orders;

%orders

What is the title of the last report? Order Type: Internet

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-91

11. Using a %DO %UNTIL Loop


/* Part b. */
%macro storms(years);
%let i=1;
%let yr=%scan(&years,&i);
%do %until(&yr eq );
title "&yr Storms";
proc means data=mc1.storm_final n min mean max
maxdec=0;
var MaxWindMPH MinPressure;
where season=&yr;
run;
%let i=%eval(&i+1);
%let yr=%scan(&years,&i);
%end;
title;
%mend storms;

/* Part c. */
%storms(2011 2014)
What was the maximum wind speed in each year?
The maximum wind speed was 155 MPH in 2011 and 161 MPH in 2014.
12. Using Iterative Processing in One Macro to Call Another Macro
/* Part b. */
%macro printlib(lib,numrows);
%let lib=%upcase(&lib);
proc sql noprint;
select memname
into :tbl1-
from dictionary.tables
where libname="&lib";
quit;
/* add the %DO loop here */
%do i=1 %to &sqlobs;
%if &numrows= %then
%print(lib=&lib,tbl=&&tbl&i);
%else
%print(lib=&lib,tbl=&&tbl&i,rows=&numrows);
%end;
%mend printlib;

/* Part c. */
%printlib(mc1,10)

/* Part d. */
%printlib(mc1)

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-92 Lesson 4 Working with Macro Programs

c. Call %Printlib to list the first 10 rows of every table in the mc1 library.
• What is the name of table in the last PROC PRINT report? mc1.storm_type_codes
• How many rows are in the last report? Five
d. Call %Printlib to list every table in the mc1 library. Do not specify a value for numrows.
• What is the name of table in the first PROC PRINT report? mc1.country_codes
• How many rows are displayed in each report? Three

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-93

Solutions to Activities and Questions

4.01 Activity – Correct Answer


Why does the macro program compile successfully even though there is a
syntax error in the PROC PRINT step?
Compiling a macro
73 options mcompilenote=all; program verifies the
74 syntax for only macro
75 %let dsn=sashelp.cars; statements.
76 %let obs=5;
77
78 %macro printtable;
79 proc print data=&dsn(obs=&obs)
80 run;
81 %mend printtable;
NOTE: The macro PRINTTABLE completed compilation
without errors.

12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.02 Activity – Correct Answer


Based on only what you see in the log, can you tell where in the SAS program
the error occurred?

74 %printtable
ERROR: File SASHELP.CLAS.DATA does not exist.
NOTE: The SAS System stopped processing this
step because of errors.
The error is displayed
in the log, but the code
is not displayed.

22
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-94 Lesson 4 Working with Macro Programs

4.03 Activity – Correct Answer


Is the table subset by MaxWind, even though it is not included as a
parameter in the macro call? Yes

%stormchart(season=2015, basin=EP)

The default value for the


MaxWind parameter is used
in the WHERE statement.

NOTE: There were 26 observations read from the data set


MC1.STORM_FINAL.
WHERE (Basin='EP') and (Season=2015) and (MaxWindMPH>20);

32
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.04 Activity – Correct Answer


• What was the value of X before Is X in LOCAL
%Test macro execution began? symbol table?
OutsideMacro
No
• What was the value of X during
%Test macro execution?
Is X in GLOBAL Set GLOBAL X to
InsideMacro symbol table? Yes
InsideMacro
• What was the value of X after
%Test macro execution ended?
InsideMacro X was in the global symbol table,
so the %LET statement inside
%Test updated the global value.

51
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-95

4.05 Question – Correct Answer


When the %Test macro executes, will it have a local symbol table?
 Yes
 No

%macro test; The %Test macro


%global x; has no parameters
%let x=InsideMacro; and does not create
%mend test; any local variables.
%test

55
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.06 Activity – Correct Answer


3. What is the scope of the X parameter in the %Test macro? Local

80 %let X=OutsideMacro;
81 %put NOTE: &=X before TEST macro execution.;
NOTE: X=OutsideMacro before TEST macro execution.
...
83 /* Execute the test macro */ Macro parameters create
84 %test(InsideMacro) and update macro variables
NOTE: X=InsideMacro during TEST macro execution.
in the local symbol table.
85
86 /* Check the value to X after execution */
87 %put NOTE: &=X after TEST macro execution.;
NOTE: X=OutsideMacro after TEST macro execution.

63
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-96 Lesson 4 Working with Macro Programs

4.06 Activity – Correct Answer


4. Add a %GLOBAL statement before the %PUT statement in the %Test
macro definition to explicitly declare X as global scope. Does the
program run successfully? No

85 %test(InsideMacro)
ERROR: Attempt to %GLOBAL a name (X)
which exists in a local environment.

Parameters cannot
be global.

64
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.07 Activity – Correct Answer


3. Identify the syntax error in the macro %IF statement. Fix the error and run
the program again to confirm that the %PUT statement is executed.
ERROR: Expected %THEN statement not found.
78
79 %if &syserr ne 0 then do;
80 %put ERROR: The rest of the program will not execute;
81 %end;

Be sure to always include


the percent sign in front
of macro keywords %IF,
%THEN, %ELSE, and %DO.

96
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4.5 Solutions 4-97

4.08 Activity – Correct Answer


Which DATA step was compiled and executed?

%avgfuel(usa)
The second DATA
74 %avgfuel(usa) step executes.
MPRINT(AVGFUEL): data fuel_usa;
MPRINT(AVGFUEL): set sashelp.cars;
MPRINT(AVGFUEL): where Origin="usa";
MPRINT(AVGFUEL): AvgKmL=mean(MPG_City, MPG_Highway)*.425;
MPRINT(AVGFUEL): keep Make Model Type AvgKmL;
MPRINT(AVGFUEL): run;

105
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.09 Activity – Correct Answer


1. Run the program and examine the log. Identify and correct the syntax
error and rerun the program. Verify that the macro compiled successfully.
ERROR: There were 1 unclosed %DO statements.
The macro ALLCYLINDERS will not be compiled.

%macro allcylinders(start,stop);
%do num=&start %to &stop;
title "&num-Cylinder Cars";
proc print data=sashelp.cars noobs;
where Cylinders=&num;
var Make Model Type Origin
MSRP MPG_City MPG_Highway;
run;
%end;
title;
%mend allcylinders; 128
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
4-98 Lesson 4 Working with Macro Programs

4.09 Activity – Correct Answer


3. Why are there some values between 3 and 12 that did not produce
reports?
...
MLOGIC(ALLCYLINDERS): %DO loop index variable NUM is now 9; loop will
iterate again.
MPRINT(ALLCYLINDERS): title "9-Cylinder Cars";
MPRINT(ALLCYLINDERS): proc print data=sashelp.cars noobs;
MPRINT(ALLCYLINDERS): where Cylinders=9;
MPRINT(ALLCYLINDERS): var Make Model Type Origin MSRP MPG_City
MPG_Highway;
MPRINT(ALLCYLINDERS): run;
NOTE: No observations were selected from data set SASHELP.CARS.
NOTE: There were 0 observations read from the data set SASHELP.CARS.
WHERE Cylinders=9;
...
There are no cars with 7,
9, or 11 cylinders.
129
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

4.10 Question – Correct Answer


Complete the query to generate a macro variable named List that includes
a space-delimited list of the distinct values of Cylinders.

proc sql noprint;


select distinct Cylinders PROC SQL makes
into :list separated by " " creating a
from sashelp.cars delimited list of
where Cylinders ne .; values easy!
quit;

%put &=list;

%cyllist(&list) 80 %put &=list;


LIST=3 4 5 6 8 10 12

151
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
Lesson 5 Developing Macro
Applications

5.1 Storing Macros ........................................................................................................................ 5-3


Demonstration: Macro Autocall Libraries ............................................................................. 5-10

5.2 Generating Data-Dependent Code ...................................................................................... 5-17


Demonstration: Generating Data-Dependent Code............................................................. 5-23

Practice ................................................................................................................................. 5-25

5.3 Validating Parameters and Documenting Macros ............................................................. 5-27


Demonstration: Validating Parameters ................................................................................ 5-38

Practice ................................................................................................................................. 5-44

5.4 Solutions ................................................................................................................................ 5-46


Solutions to Practices ........................................................................................................... 5-46

Solutions to Activities and Questions ................................................................................... 5-51


5-2 Lesson 5 Developing Macro Applications

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-3

5.1 Storing Macros

Storing and Reusing Macro Programs

How can I make my


macro programs
automatically available
to use each time I start
How can I easily store
SAS?
and maintain macro
programs and share
them with my
colleagues?

3
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Compiling a Macro Definition (Review)

PRINTTABLE

work.sasmacr (default)

%macro printtable(dsn=sashelp.cars,obs=5)
/des='Print a table. Parms: DSN= OBS=';
proc print data=&dsn(obs=&obs);
run;
%mend printtable;

4
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-4 Lesson 5 Developing Macro Applications

5.01 Activity
Open m105a01.sas from the activities folder and perform the following tasks:
1. This program creates a macro named PrintTable in the default
work.sasmacr catalog. PROC CATALOG lists the contents of work.sasmacr.
2. Run the program. The report includes all macros in work.sasmacr,
including PRINTTABLE and its description.
3. Uncomment the second CONTENTS statement. This statement creates a
table including the macros in work.sasmacr. The WHERE= data set option
is used to filter the results.
contents out=macrolist(where=(name like '%TABLE%'));

4. Run the program and examine the output table. How many macros
include TABLE in the name? 5
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Using Macros

The Work library, including


all macros in work.sasmacr,
is deleted at the end of the
SAS session.

7
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-5

Autocall Macros
The autocall facility
makes it easy to reuse
and share macro
programs in any SAS
session!
Autocall Autocall
library facility

includes .sas programs calls macros in the autocall


that each include a library without having to open
single macro definition and submit the macro definition

8
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Selected Autocall Macros


Macro Description
%CMPRES Compresses multiple blanks and removes
leading and trailing blanks.
%DATATYP Returns the data type of a value.
%LEFT Left-aligns an argument by removing leading
blanks.
%SYSRC Returns a value corresponding to an error
condition.
Several autocall
macros are provided
%TRIM Trims trailing blanks.
by SAS.
%LOWCASE Converts characters to lowercase.

9
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-6 Lesson 5 Developing Macro Applications

Autocall Macro Facility


%put NOTE: SASAUTOS=%sysfunc(pathname(sasautos));

The sasautos fileref points to the paths


where macros supplied by SAS are stored.

NOTE: SASAUTOS=(
'C:\Program Files\SASHome\SASFoundation\9.4\core\sasmacro'
'C:\Program Files\SASHome\SASFoundation\9.4\access\sasmacro'
...

Each .sas program includes


a macro supplied by SAS.

10
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.02 Activity
Open m105a02.sas from the activities folder and perform the following
tasks:
1. Highlight the PROC CATALOG step and run the selected code. Notice
in the report that the DATATYP macro is not listed.
2. Run the %LET and %PUT statements that call the %Datatyp macro.
View the log and confirm the macro runs successfully.
3. Highlight the PROC CATALOG step again and run the selected code.
Is DATATYP included in the report?

11
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-7

Autocall Rules
%datatyp(123)

DATATYP in a
Yes Execute compiled %Datatyp macro.
macro catalog?

No

Include datatyp.sas program in the input


datatyp.sas in Yes stack, compile it, and store it in
SASAUTOS locations? work.sasmacr.

No

Return tokens to WARNING: Apparent invocation of


word scanner macro DATATYP not resolved.

14
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Adding Personal Macros to Autocall Library

s:/workshop/autocall

How can I add my own


Autocall macro programs to a
library
user-defined autocall
library?

15
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-8 Lesson 5 Developing Macro Applications

Adding Personal Macros to Autocall Library

Step Write a macro definition and save


1 a .sas file with the same name as
the macro.

%macro printtable(dsn=sashelp.cars,obs=5)
/des='Print a table. Parms: DSN= OBS=';
proc print data=&dsn(obs=&obs);
run;
%mend printtable;
&path/autocall/printtable.sas

16
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d01.sas

Adding Personal Macros to Autocall Library


In each new SAS session, submit the
Step
SASAUTOS= option and provide
2
locations of autocall libraries.

OPTIONS SASAUTOS=("path", SASAUTOS);

options sasautos=("&path/autocall", SASAUTOS);

folder with personal fileref for autocall


.sas macro programs macros supplied by SAS

17
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d01.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-9

Here are other options related to the SAS autocall facility:

MAUTOSOURCE|NOMAUTOSOURCE Specifies whether the autocall feature is


available.

MRECALL Specifies whether autocall libraries are


searched for a member that was not found
during an earlier search.

MAUTOCOMPLOC Displays in the SAS log the source location of


an autocall macro when the autocall macro is
compiled.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-10 Lesson 5 Developing Macro Applications

Macro Autocall Libraries

Scenario
Build a helpful utility macro to delete all user-defined macro variables from the global symbol table.
Save the program in an autocall library and set up the autocall facility to make the macro available in
any SAS session.

Files
• m105d02.sas

Syntax

OPTIONS SASAUTOS=("my-path",SASAUTOS)

Notes
• An autocall library is a location with .sas programs that each contain a macro definition. The name
of the .sas file must match the name of the macro.
• The macro facility calls macros in the autocall library without having to open and submit the macro
definition
• Use the SASAUTOS= option to specify the locations of autocall libraries

Demo
1. Open the m105d02.sas program from the demos folder. In Section 1, notice that the DATA step
creates a series of macro variables. Macro variable names are derived from the CountryCode
column and values are assigned from the CountryName column.
data _null_;
set mc1.country_codes;
call symputx(CountryCode, CountryName);
run;
2. Information about macro variables and values is stored in a read-only SAS view known as a
DICTIONARY table. The SQL step in Section 1 creates a report that includes all columns from
the dictionary.macros table ordered by Scope and Name.
proc sql;
select *
from dictionary.macros
order by Scope, Name;
quit;
3. Highlight the code in Section 1 and run the selection. Examine the report and notice all the
automatic and global macro variables that are listed. The global CountryCode macro variables
are included in the report. There are also several global macro variables that start with SYS,
SQL, STUDIO, OLD, or an underscore. These macro variables are in the global symbol table.
However, they are defined by the SAS application.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-11

4. In Section 2, notice that the SQL query includes a WHERE statement to subset the
dictionary.macro table to include macro variables with global scope and exclude selected
macro variables that are defined by SAS applications. Highlight the SQL step in Section 2 and
run the selected code. The resulting report should include the user-defined macro variables.
Note: The ESCAPE clause in the LIKE expression is used to treat the underscore as text rather
than a wildcard for a single character.
proc sql;
select *
from dictionary.macros
where Scope='GLOBAL' and
Name not like 'SYS%' and
Name not like 'SQL%' and
Name not like 'SASWORK%' and
Name not like 'GRAPH%' and
Name not like 'STUDIO%' and
Name not like 'OLD%' and
Name not like '^_%' escape '^' and
Name ne 'CLIENTMACHINE' and
Name ne 'USERDIR';
quit;
5. Modify the SQL step as follows. Then run the step and examine the value of the Vars macro
variable in the log.

a. Suppress the printed report.

b. Select only the Name column.


c. Load each value of Name as a space-delimited list into a macro variable named Vars.
d. Display the value of &Vars in the log.
proc sql noprint;
select Name
into :Vars separated by ' '
from dictionary.macros
where Scope='GLOBAL' and
Name not like 'SYS%' and
Name not like 'SQL%' and
Name not like 'SASWORK%' and
Name not like 'GRAPH%' and
Name not like 'STUDIO%' and
Name not like 'OLD%' and
Name not like '^_%' escape '^' and
Name ne 'CLIENTMACHINE' and
Name ne 'USERDIR';
quit;
%put &=vars;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-12 Lesson 5 Developing Macro Applications

6. Copy the code in Section 2 and paste it in a new program. Make the following modifications:

a. Define a macro named DeleteAll with no parameters.


b. After the SQL step, change %PUT to %SYMDEL so that the statement deletes all macro
variables captured in the &Vars list.
c. Write a custom note to the log listing the macro variables that are deleted.
d. Close the macro definition.

e. Run the macro program to confirm that it compiles successfully.


%macro deleteall;
proc sql noprint;
select Name
into :Vars separated by ' '
from dictionary.macros
where Scope='GLOBAL' and
Name not like 'SYS%' and
Name not like 'SQL%' and
Name not like 'SASWORK%' and
Name not like 'GRAPH%' and
Name not like 'STUDIO%' and
Name not like 'OLD%' and
Name not like '^_%' escape '^' and
Name ne 'CLIENTMACHINE' and
Name ne 'USERDIR';
quit;
%symdel &vars;
%put NOTE: Macro variables deleted from global table: &vars;
%mend deleteall;
7. Save the program in the autocall folder as deleteall.sas. Close the deleteall.sas program.
Note: It is recommended that the program names be saved in lowercase because some
operating systems are case sensitive.

8. Open the libname.sas program. Add the following OPTIONS statement to indicate that autocall
macros should be read from the autocall folder in the course files and the SASAUTOS fileref.
Save the program and run it.
options sasautos=("&path/autocall", sasautos);
9. Return to the m105d02.sas program and submit the PROC CATALOG step in Section 3 to
delete the DeleteAll macro from the work.sasmacr catalog. This enables us to test whether the
autocall macro is accessible the next time that we call %DeleteAll.
proc catalog cat=work.sasmacr;
delete deleteall.macro;
run;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-13

10. In Section 1, insert the %deleteall macro call between the DATA step and the PROC SQL step.
data _null_;
set mc1.country_codes;
call symputx(CountryCode, CountryName);
run;

%deleteall

proc sql;
...
11. Highlight the code in Section 1 and run the selection. View the report and the log to confirm that
the CountryCode macro variables are no longer in the global symbol table.
12. Set up your SAS environment to automatically include your personal AUTOCALL macro libraries.

a. SAS Studio
1) Copy the code in the libname.sas program.

2) Click the More application options button and select Edit Autoexec File.
3) Paste the program in the editor. Click Run to test the code and execute it for the current
SAS session. Click Save to make the changes permanent:

b. SAS Enterprise Guide

1) Copy the code in the libname.sas program.


2) Select Tools  Options  SAS Programs. Select the box labeled Submit SAS code
when server is connected and click Edit.

3) Paste the program in the editor and click Save  OK.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-14 Lesson 5 Developing Macro Applications

continued...
5.03 Activity
1. Open m105a03.sas from the activities folder. Run the PROC CATALOG
step and confirm that PROPCASE does not exist in work.sasmacr.
2. Create a new program and enter the following code. The %Propcase
macro applies the PROPCASE function to the text parameter. Do not run
the program, but save it as propcase.sas in the autocall folder.

%macro propcase(text);
%sysfunc(propcase(&text))
%mend propcase;

19
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.03 Activity
3. Open the libname.sas program. Add an OPTIONS statement and the
SASAUTOS= option to include the autocall folder as an additional
autocall library. Run the program and save it.
options sasautos=("&path/autocall", sasautos);

4. Return to the m105a03.sas program and uncomment the %PUT


statement. Run the program. Confirm that the %Propcase macro
executes successfully and verify that it has been added to the
work.sasmacr catalog.

20
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.1 Storing Macros 5-15

Other Autocall Macros

Other helpful autocall


macros are included
in the autocall folder
in the course files.

22
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Other Autocall Macros


This macro returns 1 if
%VAREXIST(dsname, varname);
a column exists in a table
and 0 otherwise.

73 %put NOTE: Does the column MAKE exist in SASHELP.CARS?;


NOTE: Does the column MAKE exist in SASHELP.CARS?
74 %put NOTE: VAREXIST macro returns %varexist(sashelp.cars, Make);
NOTE: VAREXIST macro returns 1

73 %put NOTE: Does the column MAKE exist in SASHELP.CLASS?;


NOTE: Does the column MAKE exist in SASHELP.CLASS?
74 %put NOTE: VAREXIST macro returns %varexist(sashelp.class, Make);
NOTE: VAREXIST macro returns 0

23
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. autocall/varexist.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-16 Lesson 5 Developing Macro Applications

Other Autocall Macros

%VARTYPE(dsname, varname); This macro returns C if a column


is character or N if it is numeric.

73 %put NOTE: The column type of Origin in SASHELP.CARS is


%vartype(sashelp.cars,origin).;
NOTE: The column type of Origin in SASHELP.CARS is C.
74 %put NOTE: The column type of Age in SASHELP.CLASS is
%vartype(sashelp.class,age).;
NOTE: The column type of Age in SASHELP.CLASS is N.

24
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. autocall/vartype.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.2 Generating Data-Dependent Code 5-17

5.2 Generating Data-Dependent Code

Developing Macro Applications

How can I create a flexible


macro application that can
split any table into separate
tables based on the distinct
values of a column?

27
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

We will show you two


%splittable(sashelp.cars, Origin) possibilities using the
first five steps of the
macro development
%splittable(mc1.storm_summary, Basin) process.

%splittable(mc1.customers, Country)

28
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-18 Lesson 5 Developing Macro Applications

Developing Macro Applications Method


#1
Start with a
validated SAS
program data Asia Europe USA;
set sashelp.cars;
select(Origin);
when ("Asia") output Asia;
when ("Europe") output Europe;
when ("USA") output USA;
otherwise;
end;
run;

29
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Developing Macro Applications

Generalize The table and column


with macro names can easily be
variables %let tab=sashelp.cars; replaced with macro
%let col=origin; variables.
data Asia Europe USA;
set &tab;
select(&col);
when ("Asia") output Asia;
when ("Europe") output Europe;
when ("USA") output USA;
otherwise;
end;
run;

30
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.2 Generating Data-Dependent Code 5-19

Developing Macro Applications


Create a
macro
definition with %macro splittable(tab,col);
parameters data Asia Europe USA;
set &tab;
select(&col);
when ("Asia") output Asia;
when ("Europe") output Europe;
when ("USA") output USA;
otherwise;
end;
run;
%mend splittable;

%splittable(sashelp.cars,origin)
31
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Developing Macro Applications

%macro splittable(tab,col);
data Asia Europe USA;
set &tab;
select(&col);
How can we update when ("Asia") output Asia;
the DATA and WHEN when ("Europe") output Europe;
statements based on when ("USA") output USA;
the values of the col otherwise;
parameter? end;
run;
%mend splittable;

%splittable(sashelp.cars,origin)
32
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-20 Lesson 5 Developing Macro Applications

Developing Macro Applications


Use macro- Local Symbol Table
level Name Value
programming
for complex %macro splittable(tab,col); TAB sashelp.cars
processing proc sql noprint; COL Origin
select distinct &col
into :table1- TABLE1 Asia
Add data-
from &tab; TABLE2 Europe
driven quit; TABLE3 USA
features ...
%mend splittable; SQLOBS 3

%splittable(sashelp.cars,origin)

Create a numbered series of macro


variables for each distinct value of col.
33
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Developing Macro Applications


...
data
%do i=1 %to &sqlobs; data Asia Europe USA;
&&table&i
%end; Local Symbol Table
;
set &tab; Name Value
select(&col); TAB sashelp.cars
%do i=1 %to &sqlobs; COL Origin
when ("&&table&i") output &&table&i;
%end; TABLE1 Asia
otherwise; TABLE2 Europe
end; TABLE3 USA
run; Use %DO loops with indirect references
to insert each Tablen value. SQLOBS 3
I 4
34
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.2 Generating Data-Dependent Code 5-21

Developing Macro Applications


...
data
%do i=1 %to &sqlobs;
&&table&i
%end; Local Symbol Table
;
set &tab; Name Value
select(&col); TAB sashelp.cars
%do i=1 %to &sqlobs; COL Origin
when ("&&table&i") output &&table&i;
%end; TABLE1 Asia
otherwise; TABLE2 Europe
end; TABLE3 USA
run; when ("Asia") output Asia;
when ("Europe") output Europe; SQLOBS 3
when ("USA") output USA; I 4
35
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d03.sas

Developing Macro Applications Method


#2
Add data-
driven
features
%macro splittable(tab,col);
data Asia Europe USA;
set &tab;
select(&col);
How could PROC when ("Asia") output Asia;
when ("Europe") output Europe;
SQL generate the when ("USA") output USA;
data-driven text? otherwise;
end;
run;
%mend splittable;
%splittable(sashelp.cars,origin)

36
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-22 Lesson 5 Developing Macro Applications

5.04 Activity
Open m105a04.sas from the activities folder and perform the following
tasks:
1. Notice that the program includes two SELECT statements. Run the
program. The first report includes the distinct values of Origin. The
second report includes a separate WHEN statement for each value
of Origin.
2. Change the value of the Col macro variable to Type. Run the program
again and observe the two reports.
3. What syntax can be used to create macro variables that store the
distinct values as a delimited list?

37
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.2 Generating Data-Dependent Code 5-23

Generating Data-Dependent Code

Scenario
Create a macro program that splits a table based on the distinct values of a selected column. The
resulting program generated by the macro is dependent on the data associated with the input
parameters.

Files
• m105d04.sas

Syntax

OPTIONS SASAUTOS=("my-path",SASAUTOS)

Demo
1. Open the m105d04.sas program from the demos folder. This program does the following:

a. creates the macro variables Tab and Col and assigns the values of mc1.storm_final and
Ocean
b. creates the macro variable TabList by reading the distinct values from &col into a space-
delimited list
c. creates the macro variable WhenList by first concatenating text to build a WHEN statement
for each distinct value of &col and then combining the text into a list separated by a
semicolon
d. reads the Name and Value columns from the dictionary.macros table to print the values of
the TabList and WhenList macro variables

e. deletes the user-defined macro variables


2. Run the program and view the output. TabList includes the list of table names to produce, and
WhenList includes a string of WHEN statements for each table to be created. Note that neither
macro variable value has a semicolon at the end of the string.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-24 Lesson 5 Developing Macro Applications

3. Modify the program to create a macro named SplitTable_SQL with the parameters Tab and Col.
Include only the first PROC SQL step that creates the TabList and WhenList macro variables.
Add the following DATA step that is built using TabList and WhenList:
%macro splittable_sql(tab,col);
proc sql noprint;
select distinct &col
into :tablist separated by " "
from &tab;
select distinct
cat('when ("', &col, '") output ', &col)
into :whenlist separated by ";"
from &tab;
quit;

data &tablist;
set &tab;
select(&col);
&whenlist;
otherwise;
end;
run;
%mend splittable_sql;
4. Call the %SplitTable_SQL macro with sashelp.cars and Type as the parameter values. Run
the program and verify that six tables are created for the distinct values of Type.
%splittable_sql(sashelp.cars, Type)
5. Call the %SplitTable_SQL macro again with mc1.storm_final and Basin as the parameter
values. Run the program and verify that six tables are created for the distinct values of Basin.
%splittable_sql(mc1.storm_final, Basin)
6. Save the program in the autocall folder as splittable_sql.sas.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.2 Generating Data-Dependent Code 5-25

Practice

Level 1

1. Generating Data-Dependent Listing Reports

a. Open m105p01.sas from the practices folder. Review and submit the program. Confirm that
a report listing Gold high activity customers is produced.
b. Add a %MACRO statement to create a macro named GroupList with two parameters, Tab
for the input table and Col for the selected column. This macro generalizes the starter
program so that a PROC PRINT report is generated for each unique value of the specified
column.
c. Use a PROC SQL step to select the distinct uppercase values of the Col parameter. Load
the values into a numbered series of macro variables starting with Val1. Read the column
from the table specified by the Tab parameter.
d. Add a macro %DO loop to repeat the TITLE statement and PROC PRINT step once for each
Valn macro variable created.
Note: Use the Sqlobs macro variable created automatically by the PROC SQL step to
provide the stop value for the loop.
e. Use an indirect macro variable reference to replace GOLD HIGH ACTIVITY with Val1 for the
first %DO loop iteration, Val2 for the second iteration, and so on.
f. Close the %DO loop with %END and the macro definition with %MEND.

g. Call the %GroupList macro with mc1.customers and Type as the parameter values.
Confirm that a separate PROC PRINT step is executed for each distinct value of Type.
h. Call the %GroupList macro with sashelp.cars and DriveTrain as the parameter values.
• What is the value of DriveTrain for the first report generated?

Level 2

2. Exporting Data to Separate Worksheets in Microsoft Excel


a. Open m105p02.sas from the practices folder. Review and submit the program. Open the
Excel file to confirm storms from the NA basin are included.
• SAS Studio: In the Files and Folders section of the navigation pane, navigate to the course
data folder, select the NAStorms.xlsx file, and click (Download). Close the Excel file
after viewing it.
• Enterprise Guide: In the Servers window, expand Local  Files and navigate to the
course data folder. Double-click the NAStorms.xlsx file. Close the Excel file after
viewing it.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-26 Lesson 5 Developing Macro Applications

b. Create a macro named BasinXLS that writes storms for each distinct value of Basin to a
different worksheet in an Excel workbook named BasinStorms.xlsx. Include the following
logic in the macro program:
• Use the automatic macro variable Syslibrc to verify whether the LIBNAME statement runs
successfully (SYSLIBRC=0). If it does not run successfully (SYSLIBRC≠0), write a custom
error message to the log and terminate macro execution.
• Create a numbered series of macro variables for each value of Basin and BasinName in
the mc1.storm_basin_codes table. Remove all spaces from the BasinName values
before assigning them to macro variables.
• Use a macro %DO loop to repeat the DATA step for each value of Basin.
c. Call the %BasinXLS macro and open the BasinStorms.xlsx file. Confirm that six
worksheets are included.
• What is the name of the first storm listed in the SouthIndian_Storms worksheet?

Challenge

3. Analyzing All Columns from a Table


a. Open m105p03.sas from the practices folder. Review and submit the program. The SQL
query generates a report based on the dictionary.columns table that includes a list of all
columns and attributes from the selected table. The SGPLOT step creates a histogram to
visualize the distribution of the numeric column, MSRP. The SGPIE step creates a donut
chart to visualize the distribution of the character column, Type.

b. Create a macro named ColumnReport with one parameter, Tab. Add the following logic to
the macro to create a histogram for all numeric columns in the selected table and a donut
chart for all the character columns:
• Convert the tab parameter value to uppercase.
• After the first SQL query, add another SQL step to create a series of numbered macro
variables that will store the column values for Name and Type.
• Use a %DO loop to execute either the SGPLOT or SGPIE step for each column in the
input table. If the column type is num, then run the SGPLOT step to create the histogram.
If the column type is char, then run the SGPIE step to create the donut chart.
• Add a title for each graph: Distribution of <columnname>.
c. Call the %ColumnReport macro with mc1.storm_final as the parameter value. Verify that
the appropriate charts are created for each column.

Note: Character columns with many unique values, such as Name, are grouped into a
category labeled Other.
Note: You can ignore warnings regarding the font.

d. Call the macro again with mc1.customers as the parameter value.


• In the Distribution of Group chart, how many Orion Club Gold members are there?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-27

5.3 Validating Parameters and


Documenting Macros

Developing Macro Applications

Use macro-level
Start with a Generalize Create a macro Validate
programming Add Data Driven
validated SAS with macro definition with parameters and
for complex Features
program variables parameters document
processing

Effective macro
programs include logic
to address potential
issues with parameter
resolution.

43
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing Macro Applications

What could
possibly break
the %SplitTable
macro?

%splittable(sashelp.cars,Origin)

44
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-28 Lesson 5 Developing Macro Applications

5.05 Activity
Open m105a05.sas from the activities folder and perform the following
tasks:
1. Open sashelp.cars to view the table and columns.
2. In the program, select the SplitTable macro definition and submit the
selected code.
3. Highlight each %SplitTable macro call, one at a time, and submit it.
4. Which macro calls fail and why?

45
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing a Macro Application


%splittable(sashelp.cars,Origin)

What if values are not provided It is helpful to


for both parameters? consider all possible
scenarios to build
Will the case of the parameter
values matter? self-correcting logic
into the macro.
What if the table or column does
not exist?

What if the column is numeric?

What if the column values


contain special characters?

48
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-29

Developing a Macro Application

What macro tools


can we use to
address these
issues?

49
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. ...

Developing a Macro Application


Macro functions

Conditional processing
What macro tools
can we use to Macro variables
address these
issues?
Custom log messages

Dynamic data validation

Autocall macros

50
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-30 Lesson 5 Developing Macro Applications

Step 1: Standardize Parameter Values

%macro splittable(tab,col);

/* Ensure parameter values are uppercase */


%let tab=%upcase(&tab);
%let col=%upcase(&col); standardize case

/* If only a table name is provided, add prefix WORK. */


%if %scan(&tab,2)= %then %do;
%let tab=WORK.&tab;
%end;
... standardize
lib.table format

51
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 2: Validate Parameter Values


The EXIST function
returns a 1 if the table
%macro splittable(tab,col); exists and 0 otherwise.
...
/* Check if the table exists */
%if %sysfunc(exist(&tab))=0 %then %do;
%put ERROR: &tab does not exist.;
%put ERROR- Macro will stop executing.;
%return;
%end;
...
The %RETURN statement
causes the macro to stop
executing.

52
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-31

Step 2: Validate Parameter Values

%macro splittable(tab,col);
...
/* Check if the column exists in the selected table */
%else %if %varexist(&tab,&col)=0 %then %do;
%put ERROR: Column &col does not exist in &tab..;
%put ERROR- Macro will stop executing.;
%return;
%end;
...
%VarExist is an autocall macro that
returns 1 if the column exists in the
table and 0 otherwise.

53
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 2: Validate Parameter Values

%macro splittable(tab,col);
...
/* Check if the column exists in the selected table */
%else %if %varexist(&tab,&col)=0 %then %do;
%put ERROR: Column &col does not exist in &tab..;
%put ERROR- Macro will stop executing.;
%return;
%end; How could we enhance
...
the macro by listing
columns from the given
table in the log?

54
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-32 Lesson 5 Developing Macro Applications

Step 2: Validate Parameter Values


dictionary.columns (partial listing)

We can retrieve
column names and
attributes from
dictionary.columns.

55
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

5.06 Activity
Open m105a06.sas from the activities folder and perform the following
tasks:
1. Review the program and notice that the query is reading all columns
from the dictionary.columns table for sashelp.cars. Run the program
and observe the information available in the generated report.
2. Modify the query to create a macro variable named Varlist that
is a comma-delimited list of values in the Name column.
3. Add &Varlist after the colon in the %PUT statement. Run the program
and verify that the log lists the column names.
4. Modify the program to examine the columns in sashelp.class.
Run the program. How many columns are listed in the log?
56
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-33

Step 3: Provide Data-Driven Messages in the Log


...
%else %if %varexist(&tab,&col)=0 %then %do;
proc sql noprint;
select Name Use SQL to create a
into :varlist separated by ", " list of valid column
from dictionary.columns
where libname="%scan(&tab,1)" and names for the
memname="%scan(&tab,2)"; selected table.
quit;
%put ERROR: Column &col does not exist in &tab..;
%put ERROR- Columns in &tab include &varlist..;
%put ERROR- Macro will stop executing.;
%return;
%end;
...
58
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 4: Modify Program Based on Conditions


character
...
when ("Asia") output Asia; How do the WHEN
when ("Europe") output Europe; statements differ
when ("USA") output USA; depending on
...
column type?
numeric
...
when (3) output CYLINDERS_3;
when (4) output CYLINDERS_4;
when (5) output CYLINDERS_5;
when (6) output CYLINDERS_6;
...

59
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-34 Lesson 5 Developing Macro Applications

Step 4: Modify Program Based on Conditions


If the column is NUMERIC ...

...
when (3) output CYLINDERS_3;
when (4) output CYLINDERS_4;
when (5) output CYLINDERS_5;
when (6) output CYLINDERS_6;
...

The original data A prefix must be added


values must be to the number to create
unquoted. valid table names.

60
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 4: Modify Program Based on Conditions


If the column is NUMERIC ...
Use the %vartype
autocall macro to
%else %if %vartype(&tab,&col)=N %then %do; identify the
proc sql noprint; column type.
select distinct &col, cats("&col._", &col)
into :val1-, :table1-
from &tab
where &col is not missing;
quit;
%end;

61
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-35

Step 4: Modify Program Based on Conditions


If the column is NUMERIC ...
Local Symbol Table
Name Value
%else %if %vartype(&tab,&col)=N %then %do;
proc sql noprint; TAB SASHELP.CARS
select distinct &col, cats("&col._", &col) COL CYLINDERS
into :val1-, :table1-
VAL1 3
from &tab
where &col is not missing; VAL2 4
quit; ...
%end; Create two series of macro variables: one TABLE1 CYLINDERS_3
to store the raw numeric values, and the TABLE2 CYLINDERS_4
other to store table names with a prefix.
...

62
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 4: Modify Program Based on Conditions


If the column is CHARACTER ...

...
when ("Acura") output Acura;
when ("Land Rover") output LandRover;
when ("Mercedes-Benz") output MercedesBenz;
when ("Volvo") output Volvo;
...

The original data Table names must


values must be have invalid
quoted. characters removed.

63
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-36 Lesson 5 Developing Macro Applications

Step 4: Modify Program Based on Conditions


If the column is CHARACTER ...
Local Symbol Table
Name Value
%else %if %vartype(&tab,&col)=C %then %do;
TAB SASHELP.CARS
proc sql noprint;
select distinct &col format=$quote34., COL MAKE
compress(&col,,'nk') VAL1 "Acura"
into :val1-, :table1-
VAL2 "Land Rover"
from &tab
where &col is not missing; ...
quit; TABLE1 Acura
%end; VAL1-VALn stores the distinct TABLE2 LandRover
quoted character values from the ...
selected column.

64
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Note: The $QUOTE format does not include trailing blanks inside the quotation marks.

Step 4: Modify Program Based on Conditions


If the column is CHARACTER ...
Local Symbol Table
Name Value
%else %if %vartype(&tab,&col)=C %then %do;
TAB SASHELP.CARS
proc sql noprint;
select distinct &col format=$quote34., COL MAKE
compress(&col,,'nk') VAL1 "Acura"
into :val1-, :table1-
VAL2 "Land Rover"
from &tab
where &col is not missing; ...
quit; TABLE1 Acura
%end; The third argument in the COMPRESS TABLE2 LandRover
function keeps all characters, numbers, and ...
underscores and removes other symbols.

65
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-37

Step 4: Modify Program Based on Conditions


If the column is CHARACTER ...
Local Symbol Table
Name Value
%else %if %vartype(&tab,&col)=C %then %do;
TAB SASHELP.CARS
proc sql noprint;
select distinct &col format=$quote34., COL MAKE
compress(&col,,'nk') VAL1 "Acura"
into :val1-, :table1-
VAL2 "Land Rover"
from &tab
where &col is not missing; ...
quit; TABLE1 Acura
%end;
TABLE1-TABLEn stores the TABLE2 LandRover

compressed character values. ...

66
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Step 4: Modify Program Based on Conditions

data If the macro variables


%do i=1 %to &sqlobs; are created properly
&&table&i given the column type,
%end; then this DATA step
;
set &tab; splits the input table
select(&col); successfully.
%do i=1 %to &sqlobs;
when (&&val&i) output &&table&i;
%end;
otherwise;
end;
run;

67
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved. m105d05.sas

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-38 Lesson 5 Developing Macro Applications

Validating Parameters

Scenario
Build parameter validation into the %SplitTable macro to account for possible issues with the
parameter or data values.

Files
• m105d05.sas

Notes
The following macro tools are used to build a complete macro application that includes logic to
validate parameter values and resolve potential issues when possible:
• macro functions
• conditional processing
• macro variable
• custom log messages
• dynamic data validation
• autocall macros

Demo
1. Open the m105d05.sas program from the demos folder. This program does the following:

a. A macro named SplitTable is created with the parameters Tab and Col.
b. Parameter values are converted to uppercase. If only a table name is provided for the Tab
parameters, then WORK. is added as a prefix to the table name.
c. A condition tests whether the table exists. If the table does not exist, an error message is
written to the log, and the macro ends execution.

d. A condition verifies that the column exists in the specified table. If the column does not exist,
an error message is written to the log with a list of valid columns, and the macro ends
execution.
e. Based on the column type, values are assigned to macro variables for each distinct data
value and table value to be created.

f. A DATA step is generated to split the tables based on the distinct values of the Col
parameter.
2. Highlight and submit the macro program, and verify that it compiles successfully.

3. Select the OPTIONS statement and the first macro call with mc1.storm_final and Ocean as the
parameter values. Run the selected code. Confirm that the program runs successfully and that
three tables are created.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-39

4. Run the second macro call with false and ID as the parameter values. False is not a valid table.
Confirm that an error message is written to the log indicating that the table does not exist.
73 %splittable(false, ID)
ERROR: WORK.FALSE does not exist.
Macro will stop executing.

5. Run the third macro call with sashelp.cars and Test as the parameter values. Test is not a
column in the sashelp.cars table. Confirm that an error message is written to the log indicating
that the column does not exist and a list of valid columns is provided.
ERROR: Column TEST does not exist in SASHELP.CARS.
Columns in SASHELP.CARS include Make, Model, Type, Origin,
DriveTrain, MSRP, Invoice, EngineSize, Cylinders,
Horsepower, MPG_City, MPG_Highway, Weight, Wheelbase,
Length.
Macro will stop executing.
6. Run the fourth macro call with sashelp.cars and Make as the parameter values. Make includes
values with invalid table names with spaces and hyphens. Confirm that the tables are created
successfully, including tables for MERCEDESBENZ and LANDROVER.
7. Run the fifth macro call with mc1.orders and Order_Type as the parameter values. Order_Type
is numeric. Confirm that three tables are created with Order_Type as the prefix for each table
name.

8. Submit the final OPTIONS statement to turn off the MPRINT option.
9. Save the program as splittable.sas in the autocall folder.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-40 Lesson 5 Developing Macro Applications

Step 5: Documenting Macros


%macro splittable(tab,col);

%if &tab= or &tab=? or %upcase(&tab)=HELP %then %do;


%put WARNING-************************************;
%put WARNING-* SplitTable Macro *;
%put WARNING-* Syntax: splittable(tab,col) *;
%put WARNING-* Parameters: *;
%put WARNING-* TAB: Table to split *;
%put WARNING-* COL: Column to use to create *;
%put WARNING-* separate tables *;
%put WARNING-************************************;
%return;
%end; Use a special word or symbol to
produce a note in the log with
macro documentation.

69
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Step 5: Documenting Macros


%macro splittable(tab,col);

%if &tab= or &tab=? or %upcase(&tab)=HELP %then %do;


...

Multiple OR conditions
must be used in this
statement because the
macro IN operator
does not permit null
values in the list.

70
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-41

Step 5: Documenting Macros

%splittable(help)

156 %splittable(help)
************************************
* SplitTable Macro *
* Syntax: splittable(tab,col) *
* Parameters: *
* TAB: Table to split *
* COL: Column to use to create *
* separate tables *
************************************

71
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.07 Activity
Open m105a07.sas from the activities folder and perform the following
tasks:
1. Run the SplitTable macro definition and verify that it compiles without
error.
2. Call the %SplitTable macro with help as the parameter value. View the
log. What is causing error messages to appear in the comment?
3. Use a macro quoting function to prevent macro triggers from resolving
in the %PUT statements.
4. Run the program again and confirm that the macro documentation is
printed in the log.

72
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-42 Lesson 5 Developing Macro Applications

Developing a Macro Application


mc1.customers
Does the %SplitTable
macro resolve all
potential issues that
could be caused by the
parameter or data
values?

data values with character


quotation marks or columns starting
macro triggers with a number
75
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Developing a Macro Application


mc1.customers
In the SAS Macro
Language 2: Advanced
Techniques course,
learn more about
building complete
macro applications.

data values with character


quotation marks or columns starting
macro triggers with a number
76
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-43

Case Study

Put everything you have


learned into practice by
completing the case
study on the Extended
Learning page!

77
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-44 Lesson 5 Developing Macro Applications

Practice

Level 1

4. Validating a Macro Parameter

a. Open m105p04.sas from the practices folder. Review and submit the program.

b. Modify the macro to convert the Type parameter value to uppercase.


c. Add %IF-%THEN and %ELSE statements to validate the Type parameter. The macro should
submit the TITLE statement and PROC FREQ step only if the Type parameter is LOW,
MEDIUM, or HIGH. If the Type parameter is not correct, the macro should write this
message to the log, where xxxx is the Type parameter:
ERROR: Invalid TYPE: xxxx
ERROR: Valid TYPE values are HIGH, MEDIUM, LOW

d. Resubmit the macro definition and call the macro using a valid and invalid parameter value.
e. Modify the macro to first test whether Type is null. If so, do not execute the TITLE statement
or PROC FREQ step. Instead, the macro should write this message to the log:
ERROR: Missing TYPE
ERROR: Valid TYPE values are HIGH, MEDIUM, LOW

f. Resubmit the macro definition and call the macro with a null parameter value, valid values in
uppercase and lowercase, and an invalid value.
• How many low-activity customers are Italian (IT)?

Level 2

5. Validating Macro Parameters with Data Values

a. Open m105p05.sas from the practices folder. Review and submit the program.
b. Use PROC SQL to create the macro variables MinSeason and MaxSeason that store the
minimum and maximum values of the Season column in the mc1.storm_final table. Add a
condition to verify that the Season parameter is between MinSeason and MaxSeason. If
the Season parameter is outside of the valid range, write this message to the log:
ERROR: Valid Seasons are between <minSeason> and <maxSeason>

c. If the Season parameter is valid, use PROC SQL to create a space-delimited list of valid
Basin codes from the mc1.storm_basin_codes table. Load the list into a macro variable.
d. If the Basin parameter is in the list of valid codes, execute the TITLE statements and the
PROC SGPLOT step.
Note: Be sure to use the MINOPERATOR option in the %MACRO statement to enable the
macro IN operator.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.3 Validating Parameters and Documenting Macros 5-45

e. If the Basin parameter is not in the list of valid codes, write this message to the log:
ERROR: AA is an invalid basin code. Basin codes include NA WP EP SP NI SI.

f. Test the macro with valid and invalid values for both Basin and Season.
• How many tropical storms were there in the EP basin in 2010?

Challenge

6. Validating a Macro Parameter with Data Values That Require Quoting Functions
%SUPERQ is a helpful macro function that retrieves the value of a macro variable from the
macro symbol table and quotes it immediately, preventing the macro processor from making any
attempt to resolve anything that might occur in the resolved value. If the value of a macro
variable could include macro triggers, operators, or special symbols, %SUPERQ is an effective
alternative to resolving the macro variable with &mac-var.

%SUPERQ(mac-var)

Note: Do not include & in front of the macro variable name.


a. Open m105p06.sas from the practices folder. Review and submit the program.
b. Modify the macro so that if the Ctry parameter is null, execute a modified TITLE statement
and PROC SGPLOT step that includes customers from all countries.

Note: The country codes IN (India) and LT (Lithuania) are possible parameter values,
which could be interpreted as the macro IN operator or the less than operator. In the
%IF statement, use the %SUPERQ function to ensure that the Ctry parameter value
is treated as text.
c. If the Ctry parameter is not null, verify that it is one of the distinct values from the Country
column in the mc1.customers table. If Ctry is a valid country code, generate the chart for
customers in that country.
Note: Use %SUPERQ to ensure that the Ctry parameter value and the list of country
codes are treated as text.
d. If the Ctry parameter is an invalid value, write this message to the log and substitute a list of
valid country codes:
ERROR: ZZ is an invalid country code
Valid country codes include <list of country codes>

e. Test the macro for parameter values null, AU, in, and zz.
• What is the last valid country code listed in the log message when the Ctry parameter
is zz?

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-46 Lesson 5 Developing Macro Applications

5.4 Solutions
Solutions to Practices

Section 5.2

1. Generating Data-Dependent Listing Reports


%macro grouplist(tab,col);
proc sql noprint;
select distinct upcase(&col)
into :val1-
from &tab;
quit;

%do i=1 %to &sqlobs;


title "Group: &&val&i";
proc print data=&tab noobs;
where upcase(&col)="&&val&i";
run;
%end;
%mend grouplist;

%grouplist(mc1.customers, Type)
%grouplist(sashelp.cars, DriveTrain)
What is the value of DriveTrain for the first report generated? ALL
2. Exporting Data to Separate Worksheets in Microsoft Excel
%macro basinxls;
libname storm xlsx "&path/basinstorms.xlsx";
%if &syslibrc ne 0 %then %do;
%put ERROR: BasinStorms.xlsx was not successfully assigned.
Check the path and filename.;
%end;

%else %do;
proc sql noprint;
select Basin, compress(BasinName)
into :basin1-, :basinname1-
from mc1.storm_basin_codes;
quit;

%do i=1 %to &sqlobs;


data storm.&&basinname&i.._Storms;
set mc1.storm_final;
where Basin="&&basin&i";
run;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.4 Solutions 5-47

%end;
%end;
libname storm clear;
%mend basinxls;
%basinxls
What is the name of the first storm listed in the SouthIndian_Storms worksheet? ALFRED
3. Analyzing all Columns from a Table
%macro columnreport(tab);

%let tab=%upcase(&tab);

title "Analysis of Columns from &tab Table";


proc sql;
select Name, Label, Type, Length, Format
from dictionary.columns
where libname="%scan(&tab,1)" and
memname="%scan(&tab,2)";
quit;

proc sql noprint;


select Name, Type, Label
into :col1-, :type1-, :label1-
from dictionary.columns
where libname="%scan(&tab,1)" and
memname="%scan(&tab,2)";
quit;

%do i=1 %to &sqlobs;


title1 "Distribution of &&label&i";
title2 "Column Name: &&col&i";
%if &&Type&i=num %then %do;
proc sgplot data=&tab;
histogram &&col&i;
run;
%end;

%else %do;
proc sgpie data=&tab;
donut &&col&i;
run;
%end;
%end;
%mend columnreport;

%columnreport(mc1.storm_final)
%columnreport(sashelp.cars)
%columnreport(mc1.customers)
%columnreport(sashelp.heart)

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-48 Lesson 5 Developing Macro Applications

In the Distribution of Group chart, how many Orion Club Gold members are there? 680

Section 5.3

4. Validating a Macro Parameter


%macro custtype(type) / minoperator;
%if &type= %then %do;
%put ERROR: Missing TYPE;
%put ERROR: Valid TYPE values are HIGH, MEDIUM, LOW;
%end;
%else %do;
%let type=%upcase(&type);
%if &type in HIGH MEDIUM LOW %then %do;
title "&Type Activity Customers by Country";
proc freq data=mc1.customers order=freq;
where upcase(Type) contains "&type";
tables Country;
run;
title;
%end;
%else %do;
%put ERROR: Invalid TYPE: &type;
%put ERROR: Valid TYPE values are HIGH, MEDIUM, LOW;
%end;
%end;
%mend custtype;

%custtype(HIGH)
%custtype(low)
%custtype(med)
%custtype()

How many low-activity customers are Italian (IT)? 60

5. Validating Macro Parameters with Data Values


%macro stormchart(basin, season) / minoperator;
proc sql noprint;
select min(season), max(season)
into :minseason trimmed, :maxseason trimmed
from mc1.storm_final;
quit;

%if &season<&minseason or &season>&maxseason %then %do;


%put ERROR: Valid Seasons are between 1980 and 2017;
%end;

%else %do;
proc sql noprint;
select Basin

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.4 Solutions 5-49

into :basinlist separated by " "


from mc1.storm_basin_codes;
quit;
%if &basin in &basinlist %then %do;
title1 "Storm Frequency by Type";
title2 "&basin, &season";
proc sgplot data=mc1.storm_final noborder;
vbar StormType / filltype=gradient;
where Basin="&Basin" and Season=&Season;
yaxis grid;
run;
title;
%end;
%else %do;
%put ERROR: &basin is an invalid basin code. Basin codes
include &basinlist..;
%end;
%end;
%mend stormchart;

%stormchart(NA,2020)
%stormchart(EP,2010)
%stormchart(AA,2010)
How many tropical storms were there in the EP basin in 2010? Two
6. Validating a Macro Parameter with Data Values That Require Quoting Functions
%macro customerlist(ctry) / minoperator;
%if %superq(ctry)= %then %do;
title "All Customers";
proc sgplot data=mc1.customers noborder;
vbar Group / filltype=gradient stat=percent;
yaxis grid display=(noticks noline nolabel);
run;
%end;

%else %do;
%let ctry=%upcase(&ctry);
proc sql noprint;
select distinct Country
into :ctrylist separated by " "
from mc1.customers;
quit;
%if %superq(ctry) in %superq(ctrylist) %then %do;
title "Customers from &ctry";
proc sgplot data=mc1.customers noborder;
vbar Group / filltype=gradient stat=percent;
yaxis grid display=(noticks noline nolabel);
where Country="&ctry";
run;

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-50 Lesson 5 Developing Macro Applications

%end;
%else %do;
%put ERROR: &ctry is an invalid country code;
%put ERROR- Valid country codes include &ctrylist;
%end;
%end;
%mend customerlist;

%customerlist()
%customerlist(AU)
%customerlist(in)
%customerlist(zz)
What is the last valid country code listed in the log message when the Ctry parameter is zz? ZA

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.4 Solutions 5-51

Solutions to Activities and Questions

5.01 Activity – Correct Answer


How many macros include TABLE in the name? Four
(The number might vary depending on your SAS environment.)
proc catalog catalog=work.sasmacr;
contents out=macrolist(where=(name like '%TABLE%'));
run;
Single quotation marks prevent macro
resolution, so the % is treated as a wildcard for
the LIKE operator rather than a macro trigger.

6
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.02 Activity – Correct Answer


Is DATATYP included in the report? Yes

76 %put The data type of Val1 is %datatyp(&val1);


The data type of Val1 is CHAR
77 %put The data type of Val2 is %datatyp(&val2);
The data type of Val2 is NUMERIC
The first time the
%Datatyp macro is
called in a SAS session,
it is compiled and
added to the
work.sasmacr catalog.

12
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-52 Lesson 5 Developing Macro Applications

5.02 Activity – Correct Answer


Is DATATYP included in the report? Yes

%Datatyp calls other autocall


macros, which are also added
to work.sasmacr.

13
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.03 Activity – Correct Answer

%put Testing the PROPCASE macro: %propcase(does PROPCASE WorK?);

77 %put Testing the PROPCASE macro: %propcase(does PROPCASE WorK?);


Testing the PROPCASE macro: Does Propcase Work?

21
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.4 Solutions 5-53

5.04 Activity – Correct Answer


What syntax can be used to create macro variables that store the distinct
values as delimited list?

%let tab=sashelp.cars;
%let col=Type;
proc sql ;
select distinct &col
into :tablist separated by " "
from &tab;
select distinct
cat('when ("', &col, '") output ', &col)
into :whenlist separated by ";"
from &tab;
quit;

38
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

continued...
5.05 Activity – Correct Answer
Which macro calls fail and why?

%splittable(sashelp.cars,Origin) sashelp.crs does not exist.


%splittable(sashelp.crs,Origin)

%splittable(sashelp.cars,Price) Price is not in sashelp.cars.

%splittable(sashelp.cars,DriveTrain) Make includes values that


are not valid table names.
%splittable(sashelp.cars,Make)
Cylinders is numeric and
%splittable(sashelp.cars,Cylinders) includes missing values.

46
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-54 Lesson 5 Developing Macro Applications

5.05 Activity – Correct Answer


Which macro calls fail and why?

%splittable(sashelp.cars,Origin)
Origin and DriveTrain both
%splittable(sashelp.crs,Origin) work because the column
%splittable(sashelp.cars,Price) values are valid table
names.
%splittable(sashelp.cars,DriveTrain)

%splittable(sashelp.cars,Make)

%splittable(sashelp.cars,Cylinders)

47
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.06 Activity – Correct Answer


How many columns are listed in the log? Five columns

options nolabel;
proc sql noprint;
select Name
into :varlist separated by ", "
from dictionary.columns
where libname="SASHELP" and
memname="CLASS";
quit;

%put NOTE: Columns in SASHELP.CLASS include: &varlist;


options label;
NOTE: Columns in SASHELP.CLASS include:
Name, Sex, Age, Height, Weight
57
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5.4 Solutions 5-55

5.07 Activity – Correct Answer


2. What is causing error messages to appear in the comment?
Macro triggers in the %PUT statements are executing the %SplitTable
macro.
%put WARNING-************************************;
%put WARNING-* SplitTable Macro *;
%put WARNING-* Syntax: %splittable(tab,col) *;
...

169 %splittable(help)
************************************
* SplitTable Macro *
ERROR: WORK.TAB does not exist.
Macro will stop executing.
* Syntax: *

73
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

5.07 Activity – Correct Answer


3. Use a macro quoting function to prevent macro triggers from resolving
in the %PUT statements.
Use %NRSTR to mask macro triggers.
%put WARNING-************************************;
%put WARNING-* SplitTable Macro *;
%put %nrstr(WARNING-* Syntax: %splittable(tab,col) *);
...
************************************
* SplitTable Macro *
* Syntax: %splittable(tab,col) *
* Parameters: *
* TAB: Table to split *
* COL: Column to use to create *
* separate tables *
************************************
74
Copyr i ght © SAS I nsti tute I nc. Al l r i ghts reser ved.

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.
5-56 Lesson 5 Developing Macro Applications

Copyright © 2019, SAS Institute Inc., Cary, North Carolina, USA. ALL RIGHTS RESERVED.

You might also like