%SYSFUNC: A powerful SAS® tool.

Foster Kerrison

NJSUG, December 10th, 2004.

 


ABSTRACT

%SYSFUNC is a very powerful and flexible component of the SAS ® system. This BASUG presentation is designed to teach you how to understand the basic elements of %SYSFUNC, and how to apply it to your daily tasks. %SYSFUNC is a macro function, but you don’t need to be a macro guru to use it. %SYSFUNC allows you to undertake a wide range of tasks related to your data by using consistent syntax. Understanding how to use %SYSFUNC is the key to success, and this presentation will teach you how.

 

INTRODUCTION

After reading this paper, and the programs attatched, you should be able to incorporate %SYSFUNC into your daily tasks. Over time, and with experience, you will learn to add new and more complex features of %SYSFUNC, until you become adept at all the options in %SYSFUNC.

 

%SYSFUNC

%SYSFUNC was added in one of the version 6 enhancements, and is now available in all current versions. %SYSFUNC runs on all systems, so you can use it anywhere.

 

%SYSFUNC is a SAS ® utility which allows a programmer access to almost all SAS functions, and 61 SCL functions.

 

MACROS

The use of %SYSFUNC does not require that you know how to write macros, although a few macro basics will help you get the best out of %SYSFUNC. The primary macro statement to understand is the %LET statement. The syntax for this is %LET name = value ;

 

This is a macro language statement that assigns a value to a macro variable name. If you use the %LET statement in open code it will automatically create a global macro variable (meaning you can use it anywhere in that SAS ® session).  If you use it inside a macro, then it creates a local macro variable (meaning you can use it within the macro). To illustrate:

 

%let country = Ireland ;

 

To use the assigned value we call it by putting an ampersand (&) in front of it, like this: &country.

 

I could then add it to a title statement anywhere:

 

TITLE “It is green in &country “; 

 

And the title would print like this:

 

It is green in Ireland.

 

So the value of the macrovar is assigned by the %LET statement, and called by &country.

 

Being able to pass values around like this is very convenient because we will see that many of the %SYSFUNC operations can be assigned in open code and we can pass their values around.

 

WHERE TO USE %SYSFUNC

%SYSFUNC can be used with: SAS DATASETS, EXTERNAL FILES, SAS CATALOGS, and FILE DIRECTORIES.

 

%SYSFUNC can be used in: open code (outside a datastep or macro), in a datastep, or inside a macro. It is, therefore, very adabtable and of course very powerful.

 

%SYSFUNC with Functions

First, let’s have a look at how %SYSFUNC works with regular SAS® functions.

 

%SYSFUNC can access all SAS® functions, other than, DIF, DIM, INPUT, PUT, LAG, RESOLVE, HBOUND, LBOUND, MISSING, IORCMSG and SYMGET.

 

%SYSFUNC should not be confused with the SAS® %functions (e.g. %upcase(var)).

 

BASIC %SYSFUNC SYNTAX:

 

%SYSFUNC(FUNCTION(ARGUMENT<,FORMAT>) ;

 

To illustrate its use with functions, I used a datastep to assign a value:

 

DATA NOM ;

  NAMED = '   PADDIE   ' ;

  NEWNAME = TRANSLATE(NAMED,"X"," ") ;

  CALL SYMPUT('NOMAMA',NEWNAME) ;

RUN ;

%PUT &NOMAMA ;

XXXPADDIEXXX

 

Then I used  %SYSFUNC to drop the X:

 

%let MAMA = %SYSFUNC(COMPRESS(&NOMAMA,X));

%PUT &MAMA ;

PADDIE

 

And then I added the X back again:

 

%let MAMA = %sysfunc(TRANSLATE(&NOMAMA,X, ));

%PUT &MAMA ;

XXXPADDIEXXX

 

So I used a SAS function with %SYSFUNC to flip over and back between:

 

        PADDIE

XXXPADDIEXXX

 

Of course, we don’t really need the datastep, because we can assign the value using a %let statement in open code:

 

%let BENIGN =  '   PADDIE   ' ;

%put BENIGN = &BENIGN ;

BENIGN = '   PADDIE   '

 

Then use %sysfunc to change it:

 

%let NASTY = %SYSFUNC(translate(&BENIGN,X, )) ;

%put NASTY = &NASTY;

NASTY = 'XXXPADDIEXXX'

 

Now change it back again:

 

%let BENIGN2 = %SYSFUNC(translate(&NASTY, ,X)) ;

%put BENIGN2 = &BENIGN2;

BENIGN2 = '   PADDIE   '

 

and finally, clean up the value (remove the quotation marks):

 

%let BENIGN2 = %SYSFUNC(compress(&benign2,’’)) ;

%put BENIGN2 = &BENIGN2;

BENIGN2 = PADDIE

 

You are probably wondering if %SYSFUNC can be nested. The answer is: “of course!” The key is to nest each %SYSFUNC. Like this:

 

%let ONELINE= %SYSFUNC(compress(%SYSFUNC(translate((%SYSFUNC(translate(&BENIGN,"X"," ")))," ","X")),"'() "))  ;

I just used two functions here for illustration: translate, and compress, but you have a vast array of functions available to you.

 

One other common use of %SYSFUNC is in reformatting dates. First assign the date:

 

%let txtdate = 120403    ; * MMDDYY6 ;

%let trydate = 12/04/03  ; * MMDDYY8 ;

 

Using a macro approach:

 

%macro change_date (redate,sasfmt) ;

   %let txtdate = %sysfunc(inputn(&&redate,&sasfmt)) ;

%mend change_date  ;

 

%change_date (&txtdate,mmddyy6) ;

 

or %SYSFUNC in open code:

 

%let trydate = %sysfunc(inputn(&trydate,mmddyy8)) ;

 

gives us the SAS® date:

 

MACRO CONVERTED THE TXTDATE TO: 16043 ;

OPEN CODE CONVERTED THE DATE TO: 16043 ;

 

You can also use your own user created formats or SAS® formats with %SYSFUNC.

 

%SYSFUNC with datasets

Another powerful, and useful, operation is to use %SYSFUNC with a dataset. %SYSFUNC offers an extensive range of dataset operations.

 

For illustration, so that they are easier to follow, I like to break them into two elements:

 

  1. Dataset information
  2. Dataset manipulation

 

This may be a little simplistic, because in many cases you will want to mix different operations, so the differentiation does not always hold.

 

The two major functions in 1. to look at dataset information are ATTRN and ATTRC. The difference is that one returns a numeric code (ATTRN) and the other returns a character (ATTRC). I have identified codes for the major functions in appendix1. Check more of them yourself, by trying the code.

 

To illustrate how this works, I want to check to see if a datasets exists. Then I want to know various bits of information about it such as how many observations and variables it has, how long the record is, when it was modified, if it is password protected, whether it is sorted and so on. Could I get this from PROC CONTENTS?

 

To answer the first question: does the dataset exist?

 

%LET OK = %SYSFUNC(EXIST(<dataset name>)) ;

 

If the dataset exists then the value for &OK is 1, but if it does not exist then &OK will be 0.

 

It is always a good idea to use IF statements to check if certain steps took place. Because you use %IF statements you need to enclose the code in a macro.

 

Assuming that the dataset exists, I want to have a look at it.

 

The first key, and critical, step is to open the dataset. An equally critical step is to close it when you are finished, otherwise it will not be available. So, putting these all together:

 

%IF %SYSFUNC(EXIST(&DS)) = 1 %THEN %DO ;

 

    /* ASSIGN THE DATASET NAME */

%LET DSNAME = &DS ;     

  /* OPEN THE DATASET */

%LET DSID = %SYSFUNC(OPEN(&DSNAME)) ;          

  /* IF THE DATASET OPENED ...*/

%IF &DSID %THEN %DO ;        

  /* DOES IT HAVE OBS? */

    %LET ANY = %SYSFUNC(ATTRN(&DSID,ANY)) ;     

  /* HOW MANY OBS DOES IT HAVE? */

    %LET OBS = %SYSFUNC(ATTRN(&DSID,NOBS)) ;     

  /* HOW MANY VARS DOES IT HAVE? */

     %LET VAR = %SYSFUNC(ATTRN(&DSID,NVARS)) ;    

  /* WHAT IS THE LRECL? */

     %LET LREC= %SYSFUNC(ATTRN(&DSID,LRECL)) ;    

  /* WHEN WAS IT CREATED? */

    %LET DTEC = %SYSFUNC(ATTRN(&DSID,CRDTE));    

  /* WHEN WAS IT MODIFIED? */

    %LET DTE = %SYSFUNC(ATTRN(&DSID,MODTE)) ;    

  /* IS IT PASSWORD PROTECTED? */

    %LET PWD=     %SYSFUNC(ATTRN(&DSID,ALTERPW)) ;

  /* WHAT ENGINE WAS USED TO CREATE IT? NOTE: ATTRC, NOT ATTRN*/

    %LET ENG = %SYSFUNC(ATTRC(&DSID,ENGINE)) ;    

  /* HAS IT BEEN SORTED? */

  %LET SRT=%SYSFUNC(ATTRC(&DSID,SORTEDBY));    

  /* WHAT TYPE OF DATASET IS IT? */

   %LET MDE = %SYSFUNC(ATTRC(&DSID,MODE));    

/* CLOSE THE DATASET - A CRITICAL STEP!*/

    %LET RC  = %SYSFUNC(CLOSE(&DSID)) ;            

/* END THE DO STATEMENT */

%END ;

 

 

Feel free to modify this to meet your own needs.

 

 

%SYSFUNC with files and directories

%SYSFUNC is also a very powerful tool with files and directories.

 

The basic syntax structure remains the same as we saw in datasets, but the commands, as you would expect, are different.

 

The process is also similar to what we saw in looking at datasets, 1. open the file, 2. investigate the contents, and 3. close the file.

 

SAS® uses the file data buffer (FDB) to read the file contents.

 

The first thing to do is to check if the file exists. So, create a fileref:

 

FILENAME TEST2 "C:\TESTS\TESTER.TXT" ; RUN ;

 

Then check for the file (inside a macro):

 

%LET RC = %SYSFUNC(FEXIST(TESTER)) ;

%IF &RC = 1 %THEN %PUT THE FILE EXISTS ;

 

Then open it, and work with it:

 

%LET FILRF = TEST2 ;

%LET RC = %SYSFUNC(FILENAME(FILRF, C:\TESTS\TESTER.TXT)) ;

%IF &RC = 0 %THEN %PUT FILE REF SUCCESSFUL ;

%LET FID = %SYSFUNC(FOPEN(&FILRF,I)) ;

%IF &FID = 1 %THEN %PUT FILE OPEN WAS A SUCCESS ;

%IF &FID = 0 %THEN %PUT %SYSFUNC(SYSMSG()) ;

  %IF &FID > 0 %THEN %DO ;

   %LET RC = %SYSFUNC(FREAD(&FID)) ;

   %LET RC = %SYSFUNC(FGET(&FID,MYSTRING,10));

                    %PUT ;

                    %PUT THE DATA STRING IS: &MYSTRING ;

                    %PUT ;

                    %LET INFOS = %SYSFUNC(FOPTNUM(&FID)) ;

    %PUT THE NUMBER OF FILE OPTIONS ARE: &INFOS AS FOLLOWS: ;

                    %DO I = 1 %TO &INFOS ;

                      %LET NAME = %SYSFUNC(FOPTNAME(&FID,&I)) ;

                      %LET VALUE = %SYSFUNC(FINFO(&FID,&NAME)) ;

                      %PUT %UPCASE(&NAME) HAS A VALUE OF &VALUE ;

                    %END ;

                    %PUT ;

                    %LET RC = %SYSFUNC(FCLOSE(&FID)) ;

                    %IF &RC = 0 %THEN

%PUT THE FILE WAS CLOSED SUCCESSFULLY ;

  %END ;   

 

In this case, we opened the file (FOPEN), then looked at the data in the first record (FREAD) which I forced to read the first 10 characters - the default is to read to the first token - and then identify the number of options (FOPTNUM), then I created a loop to run through the names of each of the options (FOPTNAME), outputting those values to the log, and then closed (FCLOSE) the file.

 

There are many file manipulation options available, including appending data, identifying various records within the file, moving the cursor around in the file to read data, and so on.

 

We can also work with the files themselves. Let’s say that we want to delete a file, we call the fileref and in one line of code delete  the file:

 

%let rd = %sysfunc(fdelete(tester)) ;

 

In a directory, we can do similar operations. First, let’s  see how many files are in a directory:

 

%LET DIR = C:\TEST ;

 

%LET DREF = TSTDIR ;

%LET RC = %SYSFUNC(FILENAME(DREF,&DIR)) ;

%LET DID = %SYSFUNC(DOPEN(&DREF)) ;

%LET MEMBERS = %SYSFUNC(DNUM(&DID)) ;

%LET RC = %SYSFUNC(DCLOSE(&DID)) ;

%PUT FILES = &MEMBERS ;  

 

Here, we opened the directory (DOPEN), and checked to see how many members there were (DNUM), closed the directory (DCLOSE), and then printed the number of members in the log.

 

That’s a useful thing to know, but you might also want to look at the names of the members. If you do, then try this macro:

 

%MACRO MEMBER ;                                                                                           

  %LET DIRECTORY = C:\TEST ;                                                    

  %LET DREF = TSTDIR ;                                  

  %LET RC=%SYSFUNC(FILENAME(DREF,&DIRECT));         

  %LET DID = %SYSFUNC(DOPEN(&DREF)) ;                  

  %LET MEMBERS = %SYSFUNC(DNUM(&DID)) ;                

  %DO I = 1 %TO &MEMBERS ;                              

     %LET NAMED&I = %SYSFUNC(DREAD(&DID,&I)) ;         

  %END ;                                               

  %LET RC = %SYSFUNC(DCLOSE(&DID)) ;                   

  %PUT ;                                                     

  %PUT THE NUMBER OF MEMBERS IN &DIRECT IS:   = &MEMBERS ;     

  %DO T = 1 %TO &MEMBERS ;                                   

    %PUT FILENAME&T = &&NAMED&T ;                            

  %END ;                                                                                                                  

%MEND MEMBER ;                                               

                                                         

%MEMBER ; 

 

This will produce a listing in your log of the number of files in the directory, and their names. If you have a library on MVS, you can use this code to read the number of members, and their names; just change the directory name to suit your library name. If you have hundreds of files in your directory you might not want to print them in your log, but that’s up to you. Remember, the basic steps are, 1. open the directory, 2. check the contents, and 3. close.

 

So can we mix these operations to pick individual files, read them and manipulate them in one step? Yes you can, and how you do it is a matter of how adept and creative you can become using %SYSFUNC.

 

RETURN CODES

I mentioned earlier that I was including return codes for the major functions, and I recommend that you become familiar with these return codes. Knowing what code is returned - they are not always 1 for success and 0 for unsuccessful - will make your life much easier.

 

I created a table of codes with the associated %SYSFUNC code, which you might find useful as a start point in becoming familiar with return codes.

 

DO IT YOURSELF

%SYSFUNC has so many options to work with that you really have to build your own approach and technique. Build your own, “homemade,” solutions to undertake complex tasks to reconfigure data, or files.

 

For more information about %SYSFUNC within the SAS® system look in online docs, and drill down to find %SYSFUNC, or check the references below for examples.

 

Hopefully this paper will give you the basics that allow you to use %SYFUNC. You are the best person to determine your own needs, and you are the best person to build on the basics in this paper, so I encourage you to test and use %SYSFUNC approaches to make your life easier, and add to your SAS® skillsets.

 

CONTACT INFORMATION

 

Foster Kerrison

 

Phone: 603-520-7520

Email: kerrison@metrocast.net

Web: www.fosterkerrison.com

 


REFERENCES:

 

SAS Institute Inc., SAS ® Macro Language : Reference, first edition, SAS Institute, Cary NC, USA, 1997. 304pp.

 

Burlew, Michele M. SAS® MACRO Programming Made Easy, Cary, NC SAS Institute Inc., 2001. 208pp.

 

Ysidra, Chris, “%SYSFUNC – The brave new macro world”, SUGI23, 1998.

 

SAS Institute Inc., TS-DOC:TS-544-Base Language Changes for release 6.09E Maintenance, SAS Institute, Cary NC, USA, 2000.