As the first step in the decommissioning of 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\ 
purpose    :
parameters : 
usage      :
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;
      %let Libname = %scan(&Data.,1,.);
      %let Memname = %scan(&Data.,2,.);
%else %do;
      %*is.a one-level-name;
      %let Libname = WORK;
      %let Memname = %upcase(&Data.);
%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';
%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;
%if &Catastrophe. %then %do;
    %put Error: %SysMacroName.;
    %put _local_;
    %goto Exit;
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.;
PROC Freq data = &Data.;
PROC Freq data = &Libname..&Memname.;
          tables &Name.;
%if &Testing. %then %put _local_;
%Exit: run;


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


  • Don Henderson to SAS-L

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