Home Contact Us



SLIST Editor
Tech Teaser

You'll find a range of tips here.  Some come from our own experience while others are from other SAS users. 

If you'd like to share a tip or trap with other users, please email us.

PUT it _ALL_ out to the Log - in style  (details)

Here's an easy way to make that PUT _ALL_ a lot more readable.


A SAS date/time converter  (details)

Download this easy tool to convert that raw SAS date, datetime or time into something you can understand.  And visa versa.  It's free.


Tricks with the colon ':' operator modifier  (details)

Using a colon (:) after a comparison operator can make for simpler coding.


Creating macro variables using Proc SQL (details)

Its not only possible to assign simple values to macro variables from within an SQL select statement, but you can do some neat tricks on the way, and very easily.


View Format details with the click of a mouse (details)

Display the details of a format by just clicking on it's catalog entry in the SAS Explorer window.


Aligning PUT function results (details)

Did you know you can align the results of the PUT function with the  -l, -c, -r options.


Using the TYPES statement in Proc Summary (details)

The TYPES statement in Proc Summary (and Means) is more than a mere nicety, it can be a life saver with big data sets. 


No more macro variable litter (details)

Using macro variables extensively can get messy, and start to chew up memory.   CALL SYMDEL enables macro variables to be deleted.





 Tricks with the colon (:) operator modifier


When making character comparisons, you can use the colon (:) after the operator to compare only the first character(s) of the two operands.

For example:     if name =: 'S'

compares just the first character of name  with 'S' to be true for all names which begin with 'S'.

But the fun doesn't stop there.  Have a look at these examples...



if name <= 'S'

This will be false as 'SMITH' is compared with 'S    '.


if name <=: 'S'

While this will be true as only the first character of each value is compared.


if name in: ('A','SM')

The length of each value in the list does not have to be the same.  So this finds names starting with A or SM (but not just S).


Although sometimes known as the 'Starts With' operator, this can be misleading because the comparison is based on the length of the shortest string, whichever side of the operator it is.


if name in:('A','SMITHERS') So this will match with 'SMITH' too.




 Creating macro variables using Proc SQL



Using Proc SQL to create macro variables can sometimes be more convenient than from within a Data Step, and it can sometimes be a lot easier.


The select statement has an into clause which can assign values to macro variables. There are a few options though that can make this a very powerful feature.

These examples use the ubiquitous SAS data set HOUSES :


Style       SqFeet
CONDO          900
CONDO         1000
RANCH         1200
RANCH         1400
SPLIT         1600
SPLIT         1800
TWOSTORY      2100
TWOSTORY      3000

You can create macro variables based on the first row of the result.

proc sql noprint;
   select style, sqfeet
          into :style, :sqfeet
   from sasuser.houses;
%put &style &sqfeet;



You can create macro variables from multiple rows by using variable list syntax i.e. by using a hyphen and a variable range:

proc sql noprint;
   select style, sqfeet
             into :style1-:style3, :sqfeet1-:sqfeet4
   from sasuser.houses;
%put &style1 &sqfeet1;
%put &style2 &sqfeet2;
%put &style3 &sqfeet3;
%put &sqfeet4;

CONDO 1000
RANCH 1200

Note that its possible to use a different number of rows for macro variables depending on the number defined by the into clause.



You can also create a string of concatenated values from different rows, by using the separated by clause:

proc sql noprint;
   select distinct style
             into :styles separated by ','
   from sasuser.houses;

%put &styles;


This can be a great short cut for building a where clause for another step, for example.





 Displaying Formats from the SAS Explorer


Displaying the contents of a user-defined format hasn’t been particularly easy.  You have to submit this to get the details printed in the Output window:

proc format lib=library.formats fmtlib ;

  select $fctr1l;


At SUGA 2002 though, it was pointed out by the SAS techos that you can define your own Actions for SAS Explorer objects.  One obvious application of this is to allow us to click on a format Catalog entry type to display the format’s details. 

To do this manually, make the Explorer window active; click on Tools ŕ Options… ŕ Explorer…  Then select Catalog Entries from the drop-down list at the top of the dialog box.  A list of catalog entry types is displayed, from where the current actions can be altered.

This can be rather long-winded and impractical if you want a lot SAS users to make the same change.  So here is a short cut. 

1. Copy and paste the following SAS Registry updates to a text file, e.g. c:\temp\regUpdate.txt. 

#--- Update registry with extra Explorer actions


"1;&List"="gsubmit ""proc format lib=%b.%b fmtlib; select %b ; run;"""

"@"="gsubmit ""proc format lib=%b.%b fmtlib; select %b ; run;"""


"1;&List"="gsubmit ""proc format lib=%b.%b fmtlib; select $%b;run;"""

"@"="gsubmit ""proc format lib=%b.%b fmtlib; select $%b;run;"""


"1;&List"="gsubmit ""proc format lib=%b.%b fmtlib; select @%b;run;"""

"@"="gsubmit ""proc format lib=%b.%b fmtlib; select @%b; run;"""


"1;&List"="gsubmit ""proc format lib=%b.%b fmtlib; select @$%b;run;"""

"@"="gsubmit ""proc format lib=%b.%b fmtlib; select @$%b;run;"""


2. Submit this:

/* Change the file if necessary */

filename regin 'c:\temp\regUpdate.txt';

proc registry import=regin;


After this, you can just double click on a format entry type and the default action will be to run the associated code, printing the details in the Output window. 

Now isn’t that easier. 




 PUT it _ALL_ out to the Log - in style



It's often useful to print to the Log all the values of variables in the current Data step.  This is usually done with:

         put _all_

The problem with this is that the variables and their values are compressed onto as few lines as possible, making them hard to read.  The PUT statement also prints out automatic SAS variables too - often useful but not always wanted.

So try:


         put (_all_)  (= /);
The parentheses turn _all_ from a keyword into a variable list, and a variable list can have an associated format list.  In this case, the = format modifier is used to make the value appear with its variable name, and the  /  throws a new line for each variable.
So for example:

data _null_ ;

  input a b c $;

  put _all_ ;

  put (_all_) (= /);

  put (_all_) (+0);


50 99 string



results in: 

a=50 b=99 c=string _ERROR_=0 _N_=1






50 99 string

Note the third PUT statement has a "do nothing" pointer control, and prints just the variable values.
There are many useful possibilities here especially if you also want to treat the _character_ and _numeric_ keywords as variable lists in the same way as _all_.  For example, you could give all the character variables a common format.




 Aligning PUT function results


Using the PUT function to convert numeric values to character leaves the result right aligned. For example:

   string = ‘{‘ || put(someNumber, 6.) || ‘}’; 

results, if someNumber is 12, in the variable string having a value of: {    12}.

The PUT function in Version 8 allows us to use the alignment specifications (-L, -C, -R) previously available only in the PUT statement.

To centre the number we can now write:

   string = ‘{‘ || put(someNumber, 6.-C) || ‘}’; 

and gives a result of: {  12  }.




 The TYPES statement in Proc Summary (and Means)


When you only need certain combinations of CLASS variables in a Proc Summary, you might do it like this:

   proc summary data=basedata;

      class vara varb varc;

      output out=summdata(where=(_type_ in (1,3,5))


      /* i.e. combinations 0 0 1, 0 1 1, 1 0 1 */



You can specify the required combinations with the TYPES statement:

   proc summary data=basedata;

      class vara varb varc;

      types varc         /* _type_ = 1 */

            varb * varc  /* _type_ = 3 */

            vara * varc  /* _type_ = 5 */ ;

      output out=summdata




Apart from being easier to understand what's going on, it can save significant processing and memory on big data sets because SAS doesn't waste resources calculating unwanted _type_s, as with the first example.



 Deleting Macro Variables


Good house keeping demands that we throw away things when we no longer need them, such as data sets and variables.  They clutter up our applications and can impact performance.  Macro variables are no exception.

CALL SYMDEL allows us to delete macro variables from the macro global symbol table:

   %let mvar998 = Another macro variable;

   %let mvar999 = Yet another macro variable;


   data _null_;

      mvarName = 'mvar998';

      call symdel(mvarName, 'nowarn');

      call symdel('mvar999');


The nowarn option suppresses a warning message if the macro variable doesn't exist.

There are no excuses for littering your applications with old macro variables now.


Home ]

Copyright © 2013 Softscape Solutions Pty Ltd