WS

SAS-Macros mit eingebauter Hilfe-Funktion schreiben

Spätestens, wenn Macros in Autocall-Bibliotheken oder kompiliert in SAS-Katalogen bereitgestellt werden, freut sich jeder über eine gute Hilfe. Hier folgen ein paar kleine Tips, die das Leben leichter machen.

Der Beitrag ist ausschließlich für freundliche und hilfsbereite Kolleginnen und Kollegen gedacht, die sich und anderen Freude bereiten wollen.


Inhaltsverzeichnis


Einführung

Wer ein Macro benutzt, möchte sich in der Regel nicht mit dem Code beschäftigen. Bei größeren Autocall-Bibliotheken weiß oft nicht einmal mehr der Entwickler auf Anhieb, in welchem Directory oder PDS der Code steht. Bei compilerten Macros in SAS-Katalogen, hat der Benutzer möglicherweise den Code nicht zur Hand.

Kurz: ein Macro wird aufgerufen und hat zu funktionieren. Schön ist es dabei, wenn man herausbekommen kann, wie das Macro aufgerufen wird, und, wenn es dann doch Probleme gibt, wie es funktioniert.

Der erste Schritt ist ein eingebautes Hilfe-System: Das Macro erzählt dem Benutzer, wie es behandelt werden möchte.

Natürlich gibt es immer Menschen, die immer alles wissen und dann trotzdem was falsch machen. Auch denen können wir helfen, indem wir die Parameter sorgfältig prüfen, bevor Fehler in Proc- oder Data-Schritten Rätsel aufgeben.

Wenn es trotzdem zu Problemen kommt, oder auch nur um zu verstehen, wie das Macro arbeitet, verwenden manche vor dem Macro-Aufruf die Option MPRINT. Dann wird im Log der erzeugte SAS-Code ausgegeben. Auch dabei können wir dem Benutzer helfen, indem wir ihm zusätzliche Kommentare anzeigen.
 

Die Hilfe-Funktion

Manche Menschen, z.B. der Autor, haben ein schlechtes Gedächtnis und finden grundsätzlich keine Dokumentation. Aber SAS-Macros kann man beibringen, daß sie einem helfen wenn man eine Hilfe anfordert. Der Aufruf
%print ( hilfe=Ja gerne );
könnte mir einen hilfreichen Text im SAS-Log anzeigen.
Wie? Ganz einfach: SAS-Macros kennen benannte und Positions-Parameter. Positions-Parameter werden in der Reihenfolge angegeben, in der sie deklariert wurden. Benannte Parameter können in beliebiger Reihenfolge angegeben und bei der Deklaration vorbelegt werden.
Beispiel:
%MACRO print (data,var,by=,pagesize=60,linesize=72 );
In diesem Beispiel sind DATA und VAR Positionsparameter. BY, LINESIZE und PAGESIZE sind benannte Parameter, die bei Bedarf gesetzt bzw. überschrieben werden. Man könnte das Macro z.B. so aufrufen:
%print (sasuser.fitness,pagesize= ,linesize=120 );
Dann werden vermutlich alle Variablen aus SASUSER.FITNESS ausgedruckt. Die aktuell eingestellte Pagesize wird beibehalten und die Linesize auf 120 Zeichen gesetzt.

Für die Hilfe-Funktion geben wir jetzt einfach einen zusätzlichen Parameter an, der sie aktiviert - und weil ich mir nie merken kann, ob es jetzt HILFE oder HELP heißt, nehme ich gleich drei:

%MACRO print (data,var,by=,pagesize=60,linesize=72, 
           info=n, help=n, hilfe=n);
Wenn jetzt jemand einen der drei Parameter mit etwas anderem als n belegt, wissen wir, daß er Hilfe benötigt.
Im Macro-Code fragen wir diese Parameter als erstes ab, und geben unseren Hilfetext mit %PUT und den Macro-Funktionen %STR und %NRSTR aus:
%IF %QUOTE(&info.&help.&hilfe) NE nnn %THEN %DO;
    %PUT %NRSTR(Dieses Macro druckt eine Datei mit PROC print);
    %PUT %NRSTR(Aufruf %print%( data   * Dateiname);
    %PUT %NRSTR( optional:);
    %PUT %NRSTR(     ,var    * Variablen);
    %PUT %NRSTR(     ,by=    * Variablen für Untergruppen-Verarbeitung);
    %PUT   %STR(     ,linesize=&linesize    * Zeilenenlänge);
    %PUT   %STR(     ,pagesize=&pagesize    * Seitenlänge);
    %PUT %NRSTR(   %);); %RETURN; %* Vor derSAS-Version 9 stand hier %GOTO ende mit einem Sprungziel am Macro-ende;
%END;
Wer möchte kann noch weitere Informationen, wie Namen und Telefonnummer oder eine detailliertere Beschreibung hinterlassen. Die %QUOTE-Funktion beim Prüfen der Parameter vermeidet Fehler bei Leuten die, wie im obigen Beispiel, unbedingt zwei Worte angeben müssen. Für die vorbelegten Parameter LINESIZE und PAGESIZE habe ich hier die %STR-Funktion und die Werte der Macro-Variablen verwendet, weil ich die Vorbelegung einmal ändern werde, und dann sicher vergesse, den Hilfetext mit zu ändern. So werden Fehler schon im Ansatz vermieden.

Fertig ist das Macro mit der Hilfe-Funktion.
 

Parameter-Prüfung

Wenig ist unangenehmer als eine Reihe unverständlicher Fehler nach einem Macro-Aufruf. Dabei ist es so einfach, zumindest die häufigsten Fehler bei einem Macro-Aufruf schon im Vorfeld abzuprüfen.
  • Sind die notwendigen Parameter angegeben?
  • Existiert die SAS-Datei?
  • Ganz nette Zeitgenossen prüfen auch noch, ob es die Variablen in der Datei gibt, ob sie den richtigen Typ haben, usw.
Fehlende Parameter lassen sich einfach mit folgenden Blöcken prüfen:
%IF %SUPERQ(data) EQ %THEN %DO;
    %PUT Fehler: Angabe des Dateinamens fehlt;
    %PUT Hilfe mit info=Y;
    %RETURN;
%END;
Ab Release 6.11 (6.09 auf MVS) lassen sich auch SCL-Funktionen verwenden, z.B. um zu prüfen, ob eine Datei exitiert:
%IF NOT %SYSFUNC(EXIST(&data)) %THEN %DO;
    %PUT Fehler: Datei &data nicht gefunden;
    %PUT Hilfe mit info=Y;
    %RETURN;
%END;
Alle SCL-Functionen werden mit der Macro-Funktion %SYSFUNC() aufgerufen. Dokumentiert ist die Funktion ab Release 6.12 in der Online-Hilfe.

Ach ja, wer ganz penibel ist schreibt z.B.:

%IF %WSICHDV ( DATA   = &data,
               ANYVAR = &var,
               NUMVAR = &sumvar)
      NE OK  %THEN %DO;
    %PUT Verarbeitung aufgrund dieser Fehler abgebrochen;
    %PUT Hilfe mit info=Y;
    %RETURN;
%END;
Das Macro ist gegen Name und Adresse mit einer Bestellung per EMail bei der WS Unternehmensberatung erhältlich. Es prüft
  • ob die Datei existiert
  • ob die Variablen in der Datei sind,
  • ob die Variablen den vorrausgesetzten Typ haben (numerisch oder character)
schreibt eine entsprechende Fehler-Meldung in den SAS-Log und gibt als Ergebnis entweder OK oder ERR zurück.
 

 

Abbrüche nach Macro-Fehlern

Ein Nachteil beim Abfangen von Fehlern in Macros ist, daß das SAS-System den Fehler nicht mitbekommt und bei Batch-Jobs einfach weitermacht. Dabei können falsche Daten entstehen oder, noch schlimmer, Daten verlorengehen.

Der Autor bevorzugt bei produktiv eingesetzten Programmen die kräftige Methode des Job-Abbruchs:

%IF NOT %SYSFUNC(EXIST(&data)) %THEN %DO;
    %PUT Die Datei &data wurde nicht gefunden,;
    %PUT deshalb wird der Job vorsichtshalber abgebrochen.;
%ABORT ABEND 12;

%END;
Das hat den Vorteil, daß das Betriebssystem und der Sheduler den Fehler richtig mitbekommt und eventuelle Folge-Jobs nicht gestartet werden. Außerdem spielen Anfänger nicht soviel interaktiv mit den Schöpfungen des Genies herum ;-), wenn bei einem Fehler gleich die ganze SAS-Session beendet wird. In Batch-Jobs ist es aber ausgesprochen angenehm, daß die wichtige Fehlermeldung am Ende des SAS-Logs steht.

Etwas weniger brutal ist die Erzeugung eines Syntaxfehlers, der anschließ in der automatischen Macro-Variablen &SYSERR abgefragt werden kann. Man kann auch mit der Macrovariablen &SYSENV zwischen interaktiver und Batch-Verarbeitung unterscheiden.
Beispiel:

%IF NOT %SYSFUNC(EXIST(&data)) %THEN %DO;
    %PUT Die Datei &data wurde nicht gefunden,;
    %IF &SYSENV EQ BACK %THEN %DO;
        %PUT deshalb wird der Job vorsichtshalber abgebrochen.;
        %ABORT Abend 12;
    %END;
    * Syntaxfehler erzeugen;
    DATA _NULL_;
        Das ist ein Syntaxfehler zum Setzen von SYSERR;
    RUN;
    %RETURN; 
%END;
   

Kommentare für die Ausgabe mit der Option MPRINT

Kommentare sollen normalerweise den Aufbau und die Besonderheiten eines Programms erläutern. Manchmal möchte man aber auch wissen, welchen Code das Macro erzeugt. In diesem Fall hilft die SAS-Option MPRINT. Der vom Macro erzeugte Code wird dann im SAS-Log ausgegeben. Dieser Code kann mit den Kommentaren im Stil

* Kommentar;
ergänzt werden. Solche Kommentare werden mit der Option MPRINT ebenfalls ausgegeben, während die anderen Kommentare, wie
%* Macro Kommentar;
und
/* Kommentar-Text zum Code */;
"verschluckt" werden und nur der Dokumentation des Codes dienen.

Im folgenden Beispiel wird dies verdeutlicht.
 

Beispiel

Zunächst das Macro:
%MACRO print(data,
   var=,
   info=n,help=n,hilfe=n);
/*---------------------------------------------------------
   Macro zur Demonstration der Macro-Hilfe, der
   Parameter-Prüfung und der Wirkung von Kommentaren

   Beitrag zum SAS-Anwenderhandbuch der Uni Heidelberg
   Wilfried Schollenberger  < wisch@ws-unternehmensberatung.de >
   WS Unternehmensberatung und Controlling-Systeme
----------------------------------------------------------*/

%* Hilfe-Funktion;

%IF %QUOTE(&info.&help.&hilfe) NE nnn %THEN %DO;
    %PUT %NRSTR(Dieses Macro druckt eine Datei mit PROC print);
    %PUT %NRSTR(Aufruf %print%( data   * Dateiname);
    %PUT %NRSTR( optional:);
    %PUT %NRSTR(     ,var=   * Variablen);
    %PUT %NRSTR(   %););
    %RETURN;
%END;

* Prüfen der Parameter;

%IF %QUOTE(&data) EQ %THEN %DO;
    %PUT Fehler: Angabe des Dateinamens fehlt;
    %PUT Hilfe mit info=Y;
    %RETURN;
%END;

%IF NOT %SYSFUNC(EXIST(&data)) %THEN %DO;
    %PUT Fehler: Datei &data nicht gefunden;
    %PUT Hilfe mit info=Y;
    %RETURN;
%END;

* Ausgabe der Datei &data;

 TITLE "Datei &data";
 PROC PRINT DATA=&data LABEL;
%IF %QUOTE(&var) GT %THEN %DO;
    VAR &var;
%END;
 RUN;
%* Löschen der Überschrift;
 TITLE;
%MEND;
Ein fehlerhafter Aufruf wäre z.B.:
%print;
Wir erhalten im Log:
Fehler: Angabe des Dateinamens fehlt
Hilfe mit info=Y
Daraufhin rufen wir die Hilfe-Funktion auf:
%print ( info=Y );
und erhalten im Log:
Dieses Macro druckt eine Datei mit PROC print
Aufruf %print( data   * Dateiname
 optional:
     ,var=   * Variablen
   );
Aha!
Wir wollen aber ganz genau wissen, was das Macro tut und verwenden die SAS-Option MPRINT:
OPTIONS MPRINT;

%print ( data=sasuser.class );

OPTIONS NOMPRINT;
Im Log erhalten wir auch die Kommentare, die mit einem * beginnen:
131  OPTIONS MPRINT;
132
133  %print ( data=sasuser.class );
MPRINT(PRINT):   * PRüFEN DER PARAMETER;
MPRINT(PRINT):   * AUSGABE DER DATEI &DATA;
MPRINT(PRINT):   TITLE "Datei sasuser.class";
MPRINT(PRINT):   PROC PRINT DATA=SASUSER.CLASS LABEL;
MPRINT(PRINT):   RUN;

NOTE: The PROCEDURE PRINT used 0.33 seconds.


MPRINT(PRINT):   TITLE;
134
135  OPTIONS NOMPRINT;
zurück zum Anfang

© WS Unternehmensberatung und Controlling-Systeme GmbH
Friedrich-Weinbrenner-Straße 20
69126 Heidelberg

Tel.: 06221 / 401 409
Fax: 06221 / 401 422

EMail: info @ ws-unternehmensberatung.de

Amtsgericht Mannheim, HRB 335485
Geschäftsführer: Wilfried Schollenberger