Lesson 10, Part 3a: %SYSFUNC and %QSYSFUNC Functions¶

Executing SAS Functions with the %SYSFUNC Macro Function

%SYSFUNC function executes most of the data step functions.¶

“Because %SYSFUNC is a macro function, you do not need to enclose character values in quotation marks as you do in DATA step functions” (SAS® Documentation).

In [1]:
* Ex4_Percent_sysfunc.sas;
options nodate nonumber nonotes nosource;
ods html close;

**** Here is a DATA step ;
data _null_;
  ds1 ='CLASS|CARS|HEART|DEMOGRAPHICS';
  count_words_v1 = countw(ds1, '|');
  put 'DATA step variable: ' DS1=;
  put 'DATA step variable: ' count_words_v1= ;
run;
SAS Connection established. Subprocess id is 11592

Out[1]:

4                                                          The SAS System                            13:05 Friday, November 13, 2020

28 ods listing close;ods html5 (id=saspy_internal) file=_tomods1 options(bitmap_mode='inline') device=svg style=HTMLBlue;
28 ! ods graphics on / outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
29
30 * Ex4_Percent_sysfunc.sas;
31 options nodate nonumber nonotes nosource;
DATA step variable: ds1=CLASS|CARS|HEART|DEMOGRAPHICS
DATA step variable: count_words_v1=4
E3969440A681A2408885998500000004
In [6]:
**** Creating and displaying macro variables in open code;
options nodate nonumber nosource;
ods html close;
%let m_ds1 = CLASS|CARS|HEART|DEMOGRAPHICS;
%let m_count_words_v1 = %sysfunc(countw(&m_ds1, %str(|)) );
%put Macro variable: &=m_ds1;
%put Macro variable: &=m_count_words_v1;
%symdel m_ds1 m_count_words_v1/nowarn;
%put _user_;
Out[6]:

                                                           The SAS System

Macro variable: M_DS1=CLASS|CARS|HEART|DEMOGRAPHICS
Macro variable: M_COUNT_WORDS_V1=4
E3969440A681A2408885998500000009

Things to notice in the SAS code in the following cell.¶

  • The macro variable m_ds2 has a comma (,) in its value.
  • The comma (,) is part of the macro variable value, not a delemter.

Question: How to mask the comma (,) - a special character (or token)?¶

Answer: Use the %quote macro quoting function to reference &m_ds2.¶

If you don't use %quote, SAS would treat the comma as a delimiter, which is meaningful in the countw function.

Read Patterson and Remigio, 2017 about macro quoting functions

In [7]:
options nodate nonumber nosource;
ods html close;

%let m_ds3 = "CLASS","CARS","HEART","DEMOGRAPHICS";
%let m_count_words_v3 = %sysfunc(countw(%quote(&m_ds3)));
%put Macro variable: &=m_ds3;
%put Macro variable: &=m_count_words_v3;
%put _user_;
%symdel m_ds3 m_count_words_v3/nowarn;
%put _user_;
Out[7]:

                                                           The SAS System

Macro variable: M_DS3="CLASS","CARS","HEART","DEMOGRAPHICS"
Macro variable: M_COUNT_WORDS_V3=4
GLOBAL M_COUNT_WORDS_V3 4
GLOBAL M_DS3 "CLASS","CARS","HEART","DEMOGRAPHICS"
E3969440A681A2408885998500000010
In [ ]:
options nonumber nocenter nodate nosource nosymbolgen;
ods html close;
%LET list = %str(sashelp.class sashelp.iris sashelp.retail);
/* Count # of values in the string */
%LET count=%sysfunc(countw(&list, %STR( ))); 
%put &=list;
%put &=count;
%macro doit;
  %do i = 1 %to &count;
    %put title&i  %left(%unquote(%SCAN(&list, &i, %STR( ))));
   %end;
   %put _user_;
%mend doit;
%doit

Another example of %SYSFUNC¶

In [2]:
title;
options nodate nonumber nosource nonotes;
ods html close;
footnote1 "%sysfunc(date(),worddate.) Class Report";
proc print data=sashelp.class (obs=3);
run;
SAS Output
Obs Name Sex Age Height Weight
1 Alfred M 14 69.0 112.5
2 Alice F 13 56.5 84.0
3 Barbara F 13 65.3 98.0

March 29, 2024 Class Report

In [5]:
options nodate nonumber nosource;
ods html close;
data _null_;
    var1= 'STAT 4197';
    var2 = translate(var1, '6', '4');
    put 'DATA step variable:' var1= ; 
    put 'DATA step variable:' var2= ;  
run;
%let m_var1 = STAT 4197;
%let m_var2 = %sysfunc(translate(&m_var1, 6, 4));
%put macro variable: &=m_var1;
%put macro variable: &=m_var2;
%symdel var1 var2 /nowarn;
Out[5]:

                                                           The SAS System

DATA step variable:var1=STAT 4197
DATA step variable:var2=STAT 6197
macro variable: M_VAR1=STAT 4197
macro variable: M_VAR2=STAT 6197
E3969440A681A2408885998500000008
%SYSFUNC and PUTN only take macro variables, not data step variables.¶
In [85]:
options nodate nonumber nosource;
ods html close;
%let x1=%sysfunc(today(),date9.);
%let x2=%sysfunc(today(),monname3.);
%let x3=%sysfunc(today(),day2.);
%let x4=%sysfunc(today(),year4.);
%let x5 =%sysfunc(putn('27jan2016'd, date9.)); 
%let x6 =%sysfunc(putn(0, date9.)); 
%let x7 =%sysfunc(inputn(04jul2016, date9.)); 
%let x7 =%sysfunc(putn(%sysfunc(inputn(04jul2016, date9.)), mmddyy10.)); 
%let x9=%sysfunc(datetime(), datetime.);
%let x10=%sysfunc(date(),worddate.);
%let x11= %sysfunc(left(%qsysfunc(date(),worddate32.)));
%put &=x1 &=x2 &=x3 &=x4 &=x5 &=x6 ;
%put &=x7 &=x8 &=x9;
%put &=x10 &=x11;
%symdel x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11/nowarn;
Out[85]:

                                                           The SAS System

X1=27OCT2019 X2=Oct X3=27 X4=2019 X5=27JAN2016 X6=01JAN1960
X7=07/04/2016 X8=27OCT19:15:43:33 X9=27OCT19:15:57:29
X10=October 27, 2019 X11=October 27, 2019
E3969440A681A2408885998500000088

Why use %QSYSFUNC

Below the LEFT function expects only one argument, but you are passing "November 24, 2020" to it. It interprets the comma as the delimiter between two arguments.

You can mask the comma by using the %QSYSFUNC function instead, as follows:

In [8]:
options nodate nonumber nosource;
ods html close;
title "%sysfunc(left(%qsysfunc(today(),worddate32.))) Student Report";
proc print data=sashelp.class (obs=5); run;
Out[8]:
SAS Output

November 24, 2020 Student Report

Obs Name Sex Age Height Weight
1 Alfred M 14 69.0 112.5
2 Alice F 13 56.5 84.0
3 Barbara F 13 65.3 98.0
4 Carol F 14 62.8 102.5
5 Henry M 14 63.5 102.5

Author: KurtBremser Call INTNX FROM %SYSFUNC

In [20]:
options nonotes nodate nonumber nosource;
ods html close;
%put %sysfunc(intnx(month,%sysfunc(today()),1),monname8.);
%put %sysfunc(intnx(month,%sysfunc(today()),-1,s),year.);
%put %sysfunc(intnx(year,%sysfunc(today()),2),year.);
Out[20]:

                                                           The SAS System

November
2019
2021
E3969440A681A2408885998500000023

The following code is obtained from author Haikuo at Communities.sas.com - 08/09/2013

In [ ]:
*SAS Documentation 9.4;
%macro checkds(dsn);
   %if %sysfunc(exist(&dsn)) %then
      %do;
         proc print data=&dsn;
         run;
      %end;
      %else
         %put The data set &dsn does not exist.;
%mend checkds;
%checkds(Sasuser.Houses)
Challenge¶

How to replace commas in a macro variable and put spaces

 "You will need to macro quote both commas and spaces to get them to be treated as text instead of delimiters." (Solution by Tom SUPER USER)

The %SYSFUNC enables the macro facility to execute SAS language functions or user-written funtions in open code (SAS Documentation).

In [24]:
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let have = a,b,c;
%let want = %sysfunc(translate(%quote(&have),%str( ),%str(,)));
%put &=want;
Out[24]:

The SAS System

WANT=a b c
E3969440A681A2408885998500000027
In [32]:
options nocenter nonumber nodate nonotes nosource;
ods html close;
data _null_;
have = 'a,b,c';
want = translate(have, ' ', ',');
put (_ALL_) (=);
Out[32]:

The SAS System

have=a,b,c want=a b c
E3969440A681A2408885998500000035
%QSYSFUNC function additionally masks special characters and mnemonic operators.¶
%SYSFUNC does not mask special characters or mnemonic operators in its result. %QSYSFUNC masks the following special characters and mnemonic operators in its result:
& % ' " ( ) + − * / < > = ¬ ^ ~ ; , #  blank
AND OR NOT EQ NE LE LT GE GT IN

In [8]:
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let asthma_vars17 =    ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU;
%let q_asthma_vars17 = %unquote(%str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%'));
%put &=asthma_vars17;
%put &=q_asthma_vars17;
The SAS System

ASTHMA_VARS17=ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU
Q_ASTHMA_VARS17='ASTHDX' 'ASSTIL31' 'ASATAK31' 'PERWT17F' 'VARSTR' 'VARPSU'
The SAS System

E3969440A681A2408885998500000010
In [6]:
ods html close;
options nocenter nonumber nodate nonotes nosource;
%let asthma_vars17 =    ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU;
%let s_asthma_vars17 = %str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%');
%put _user_;
The SAS System

GLOBAL ASTHMA_VARS17 ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU
GLOBAL S_ASTHMA_VARS17 ASTHDX ASSTIL31 ASATAK31 PERWT17F VARSTR VARPS
The SAS System

E3969440A681A2408885998500000008

%QSYSFUNC function additionally masks special characters and mnemonic operators. %SYSFUNC does not mask special characters or mnemonic operators in its result. %QSYSFUNC masks the following special characters and mnemonic operators in its result: & % ' " ( ) + − * / < > = ¬ ^ ~ ; , # blank AND OR NOT EQ NE LE LT GE GT IN

In [10]:
options nocenter nonumber nodate nonotes nosource;
ods html close;
%let asthma_vars17 =    ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU;
%let q_asthma_vars17 = %unquote(%str(%')%qsysfunc(tranwrd(%sysfunc(compbl(&asthma_vars17)),%str( ),' '))%str(%'));
%put &=asthma_vars17;
%put &=q_asthma_vars17;
The SAS System

ASTHMA_VARS17=ASTHDX  ASSTIL31   ASATAK31  PERWT17F VARSTR VARPSU
Q_ASTHMA_VARS17='ASTHDX' 'ASSTIL31' 'ASATAK31' 'PERWT17F' 'VARSTR' 'VARPSU'
The SAS System

E3969440A681A2408885998500000012

When a macro variable is created with a macro quoting function like %STR or %QSYSFUNC, the function uses unprintable delta characters to mask the special characters in the macro variable's value.

These delta characters can cause unexpected syntax errors when the macro variable is used in non-macro syntax. Above, the macro variable has resolved, and the syntax error occurred during tokenization.

Solution: Use the %UNQUOTE function to remove the delta characters and prevent possible syntax errors caused by the characters.