As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Macro Design Issues Checklist

From sasCommunity
Jump to: navigation, search

Macro Design Issues Checklist

Note: These recommendations are for project and site macros, i.e. macros not in a program, but in separate files and therefore available to the autocall facility.

  • Always use Named Parameters
  • Always use two-level data set names: Work.MyData
  • Always have a Parameter named Testing
  • Always provide a Description (des=); proc catalog shows the description
  • Always use %do + %end to avoid confusion about whether you want to generate a sas or macro semicolon at end of a statement
  •  %local macro variables: assign an initial value and include a description
  • Always terminate a macro variable reference with a dot: (&Data.) in the following cases:
fails             works
---------------   ----------------
&Libname.&Data.   &Libname..&Data. 
&Filename.txt     &Filename..txt
$char&Length.     $char&Length..

Reference: missing

Contents of File containing Macro

  1. documentation in slash asterisk comment block
  2. macro definition: macro, mend

Macro Statement

%Macro MacroName
(input   = sashelp.class
,process =
,output  = work.class
,testing = 0
)/ /* ** store source /* */
des = 'project/site: macro description';

Macro Template

This template combines the slash+asterisk comment block and macro+mend.

Note: this style avoids having slash+asterisk (/*) in column 1 which is the JCL which ends a mainframe (MVS or z/OS) job.

 /*    name: ...\SAS-site\macros\ProcThis.sas 
description:
purpose    :
parameters : 
usage      :
%ProcThis(data=Library.BigData)
author:
change history:
*** */
%Macro MacroName 
(data    = sashelp.class
,libname = /* SQL */
,memname = /* SQL */
,name    = /* SQL var name */
,process =
,byvars  =
,class   =
,outData = OutData
,outLib  = Work
,testing = 0
)/ /* *** store source /* */
des = 'project/site: macro description';
 
%* this is a macro comment;
 
%* reset local var based on global options;
%let Testing = %eval(   &Testing.
                     or %sysfunc(getoption(mprint)) eq MPRINT);
 
%* allocate temp vars: name, initial value shows type, description;
%local Catastrophe;%let Catastrophe = 0;%* error check;
%local I          ;%let I           = 0;%* loop counter;
 
%* deconstruct SQL vars;
%if   %index(&Data.,.) %then %do;
      %*is.a two-level.name;
      %let Libname = %scan(&Data.,1,.);
      %let Memname = %scan(&Data.,2,.);
      %end;
%else %do;
      %*is.a one-level-name;
      %let Libname = WORK;
      %let Memname = %upcase(&Data.);
      %end;
%let Libname = %upcase(&Libname.);
%let Memname = %upcase(&Memname.);
%let Name    = %upcase(&Name.);
 
PROC SQL ;* noprint;
         select *
         from   Dictionary.Columns
                %* or      Tables;
         where  Libname eq "&Libname."
           and  Memname eq "&Memname."
           and  Name    eq "&Name."
           and  MemType eq 'DATA';
         quit;
 
%if &Testing. %then %put _local_;
 
%* testing parameter is empty/null/missing;
%if &Parm. = %then %do;
%* or;
%*if &Parm. eq %then %do;
    %put ERROR:  You must supply a parameter to macro &SysMacroName.;
    %goto exit;
   %end;
 
%if &Catastrophe. %then %do;
    %put Error: %SysMacroName.;
    %put _local_;
    %RETURN;
    %*or:;
    %goto Exit;
    %end;
 
DATA &OutLib..&OutData.;
set  &Data.;
set  &Libname..&Memname.(keep = &Name.);
by   &ByVars.;%* note: ByVars can be empty and this will work;
 
%if &Testing. %then %do;
    PROC SQL; describe table &SysLast.;
              quit;
    %end;
 
PROC Freq data = &Data.;
PROC Freq data = &Libname..&Memname.;
          tables &Name.;
 
%if &Testing. %then %put _local_;
%Exit: run;
%Mend;

Testing

* name: MyMacro-Test;
options mprint;
%MyMacro(data = sashelp.Class);

References

  • Don Henderson to SAS-L

http://listserv.uga.edu/cgi-bin/wa?A2=ind0804B&L=sas-l&P=R18071

--macro maven == the radical programmer 11:13, 19 June 2007 (EDT)