Posts Tagged ‘macro’

Passer de CLASS CLAS à « CLASS » « CLAS » dans une macro variable
février 1, 2013Mettre toutes les mots contenus dans une macro variable entre guillemets (quote en anglais) est un tâche plus fréquente qu’elle n’y paraît.
Une vois le code écrit, il est souvent plus rapide de faire du copier/coller et ensuite de modifier. Voici un exemple où DSN=CLASS CLAS sert à créer DSN_QUOTE= »CLASS » « CLAS ».
1. Exemple dans une macro
Dans l’exemple, la macro est PRINTDSN. Elle a pour tâche d’imprimer dans la log tous les datasets présents dans la bibliothèque SASHELP qui sont cités dans le paramètre de macro DSN, s’ils existent.
%macro printdsn (dsn=); %let dsn =%upcase(&dsn.); %let dsn_quote=%sysfunc(tranwrd(%nrstr(%")&dsn.%nrstr(%"),%str( ),%str(" "))); proc sql; create table ref as select memname from dictionary.tables where upcase(libname)='SASHELP' and upcase(memname) in (&dsn_quote.); quit; data _null_; set ref; call execute ('proc print data=sashelp.' || memname || ';'); call execute ('run;'); run; %mend printdsn; %printdsn(dsn=class clas);
Pour ma part j’ai pris l’habitude de mettre le contenu des macros paramètres en majuscule, et ce dès le début du programme, sauf besoin spécifique contraire. Ceci explique la ligne %let dsn=upcase(&dsn.);
De plus j’ai pris l’habitude de rajouter le suffixe _quote au nom de la macro variable. Dans notre exemple il y a la macro variable DSN mise en majuscule. Cette variable est ensuite mise entre guillemets.
La macro fonction %sysfunc() permet d’utiliser la fonction tranwrd dans une expression macro. La fonction tranwrd est composée de trois paramètres :
- le texte d’origine entre guillemets
- le partie de texte à remplacer dans cette chaîne de caractères
- le texte de remplacement
2. Le même exemple sans macro
L’exemple est présenté dans une macro. Pour tester le code, un simple %let et %put feront l’affaire. Le résultat s’affiche alors dans la log.
%let dsn=CLASS CLAS; %let dsn_quote=%sysfunc(tranwrd(%nrstr(%")&dsn.%nrstr(%"),%str( ),%str(" "); %put &dsn_quote.;

Macro : mini-programmes/routines pour tester la validité d’un nom de variable
juin 27, 2010Après avoir appris les bases de la programmation, vous allez vous rendre compte que certaines tâches se répètent de programme à programme. Une partie d’entre eux peut se résumer à quelques lignes. Il est alors tentant d’écrire un programme de manière « officielle » et de le valider au lieux d’avoir à écrire le code à chaque fois.
Voici un petit exemple. Il s’agit du descriptif d’une macro qui va indiquer si le nom de variable donné est conforme aux règles requises par SAS. Ici vous avez la spécification et les tests de validation.
1. Spécification : Quelles sont les règles ?
Le nom d’une variable ne peut pas avoir plus de 32 caractères.
Le premier caractère est une des 26 lettres de l’alphabet ou un chiffre.
Les autres caractères peuvent être des lettres de l’alphabet, un chiffre ou un tiret bas (underscore).
2. Spécification : Quelques contraintes ?
Vous développez une macro disons VARNAME_VALID ayant un paramètre VARNAME où vous pourrez entrer le nom d’une variable à tester. Si ce nom entre dans les critères de définition de SAS, alors une macro variable varname_ok=1 sinon la macro variable varname_ok=o.
3. Test Cases : Quand tout va bien: un nom de variable avec une seule lettre, deux lettre, commençant par un tiret bas, écrit en majuscule, avec un chiffre au milieu, avec un chiffre à la fin
Qu’est ce qui est testé : un nom de variable suivant les règles requises par SAS.
Quel est le code à soumettre :
%varname_valid(varname=a);
%varname_valid(varname=ab);
%varname_valid(varname=_ab);
%varname_valid(varname=AB);
%varname_valid(varname=ab1a);
%varname_valid(varname=ab1);
Quel est le résultat attendu :
La macro variable garde la valeur un
&varname_ok.=1
Un message dans la log est affiché :
NOTE: (VARNAME_VALID) Nom de variable correct.
NOTE: (VARNAME_VALID) Valeur actuelle : ab
D’autres programmes peuvent être appelés après.
4. Test Cases : Violation des pré-requis de la macro
4.1 Violation pré-requis : le paramètre est manquant
Qu’est ce qui est testé : Un nom de variable doit être donné dans le paramètre de la macro
Quel est le code à soumettre : %varname_valid(varname=);
Quel est le résultat attendu :
La macro variable VARNAME_OK prend la valeur zéro
&varname_ok.=0
Un message dans la log est affiché :
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle:
EARNING: (VARNAME_VALID) Valeur attendue: un nom de variable.
D’autres programmes peuvent être appelés après.
4.2 Violation pré-requis : plus d’un nom de variable est entré
Qu’est ce qui est testé : Plus d’une variable est entrée dans le paramètre de macro
Quel est le code à soumettre : %varname_valid(varname= ab cd );
Quel est le résultat attendu :
La macro variable prend la valeur zéro
&varname_ok.=0
Un message dans la log est affiché :
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle : ab cd
WARNING: (VARNAME_VALID) Valeur attendue : un seul nom de variable.
D’autres programmes peuvent être appelés après.
5. Test Cases : Les règles définies par SAS pour nommer une variable
5.1 Un nom de variable : Au maximum 32 caractères
Qu’est ce qui est testé : un variable avec plus de 32 caractères
Quel est le code à soumettre : %varname_valid(varname=abcdefghijklmnopqrstuvwxyz1234567890);
Quel est le résultat attendu :
La macro variable prend la valeur z éro
&varname_ok.=0
Un message dans la log est affiché :
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle : abcdefghijklmnopqrstuvwxyz1234567890
WARNING: (VARNAME_VALID) Valeur attendue : 32 caractères au maximum.
D’autres programmes peuvent être appelés après.
5.2 Un nom de variable : commence par une lettre de l’alphabet (a-z) ou un tiret bas
Qu’est ce qui est testés : Un premier caractère différent d’une lettre de l’alphabet ou d’un tiret bas
Quel est le code à soumettre : %varname_valid(varname=é);
Quel est le résultat attendu :
La macro variable prend la valeur zéro
&varname_ok.=0
Un message dans la log est affiché :
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle : é
WARNING: (VARNAME_VALID) Valeur attendue : La première lettre est une des 26 lettres ou un tiret bas.
D’autres programmes peuvent être appelés après.
5.3 Un nom de variable : Après le premier caractère on peut avoir des lettres (a-z), des chiffres (0-9) et des tirets bas.
Qu’est ce qui est testé : un caractère différent d’une lettre de l’alphabet, d’un chiffre ou d’un tiret bas parmi les autres caractères de l’alphabet
Quel est le code à soumettre : %varname_valid(varname=1é);
Quel est le résultat attendu :
La macro variable prend la valeur zéro
&varname_ok.=0
Un message dans la log est affiché :
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle : 1é
WARNING: (VARNAME_VALID) Valeur attendue : La première lettre est une des 26 lettres ou un tiret bas.
WARNING: (VARNAME_VALID) Nom de variable incorrect.
WARNING: (VARNAME_VALID) Valeur actuelle : 1é
WARNING: (VARNAME_VALID) Valeur attendue : A partir du deuxième caractères, seuls des lettres,
WARNING: (VARNAME_VALID) des chiffres et un tiret bas sont autorisés.
Lecture complémentaire

Une petite histoire de macro : compter le nombre de mots dans un paramètre de macro
avril 11, 2010Il est courant de devoir compter le nombre de mots dans un paramètre de macro. Il est par exemple possible de vouloir créer une boucle pour travailler chacun des termes contenu dans cette macro de manière séparée.
Voici donc l’histoire d’une mini macro qu’on nommera CNT_WRD qui crée une macro variable TOT_WRD renvoyant le nombre de mots contenu dans le paramètre TXT.
Ceci est pour vous l’occasion de voir ou revoir un raisonnement possible dans la construction d’une macro sous SAS.
1. Préciser ses besoins, une rapide « spécification »
La macro CNT_WRD composée d’un seul paramètre retournera dans une macro variable TOT_WRD le nombre de mots contenus dans le texte donné dans le paramètre de macro.
Ici on considérera comme mot, tout terme séparé par au moins un blanc.
Si le paramètre de macro est vide, la macro ne devra pas afficher de message d’erreur et la macro variable TOT_WRD sera égale à 1. Par défaut, aucune valeur ne sera entrée dans le paramètre TXT.
La macro variable doit pouvoir être utilisable à l’extérieur de la macro (macro variable globale).
2. Tester la fonction COUNT dans une étape data
La fonction COUNT permet de comptabiliser certains caractères et donc de répondre à ce type de besoin. En fait, cette fonction ne compte pas le nombre de mots mais compte le nombre de caractères définis par le second élément dans la fonction; dans notre cas, elle comptera le nombre de blancs. Il faut donc ajouter 1 au total.
Voici un exemple dans une étape data.
data _null_;
tot_wrd=1+count(‘mot1 mot2’,‘ ‘);
put tot_wrd=;
run;
Dans la log, vous pouvez voir que cnt_wrd=2.
Mais cela ne suffit pas pour gérer les blancs multiples et les blancs aux extrémités. Car si vous avez plus d’un blanc entre chaque mot, chacun sera compté. Il faut donc les enlever au préalable (avec la fonction COMPBL ici). Les blancs de début et fin peuvent s’enlever au moyen de la fonction STRIP.
data _null_;
tot_wrd=1+count(strip(compbl(‘ mot1 mot2 ‘)),‘ ‘);
put tot_wrd=;
run;
Mais que ce passe t-il si notre texte à compter est vide ? TOT_WRD sera égal à 1. Il faut donc ajouter le 1 au total que si le texte à analyser n’est pas vide.
data _null_;
length txt $200;
txt=;
if txt ne ‘ ‘ then tot_wrd=1+count(strip(compbl(txt)),‘ ‘);
put tot_wrd=;
run;
3. Créer la macro
Comme indiqué dans le dernier point, on travaille ici de manière conditionnelle. Si le paramètre de macro TXT est vide, la macro variable CNT_WRD nouvellement créée prend la valeur zéro. Sinon, On passe par la fonction COUNT.
Comme il n’existe pas d’équivalent aux fonctions COUNT et COMPBL en langage macro, il faut encadrer chacune d’elle dans une fonction macro SYSFUNC.
Ici on notera que la fonction STRIP n’apparaît pas. Les blancs de début et de fin en langage macro n’ont aucun impact.
%macro cnt_wrd(txt=);
%global tot_word;
%if &txt.= %then %let tot_wrd=0;
%else %let tot_wrd=%eval(1+%sysfunc(count(%sysfunc(compbl(&txt.)),%str( ))));
%mend cnt_wrd;
Pour représenter un blanc dans une étape data, il suffit d’utiliser des guillemets. En langage macro, on fait appel à la fonction %STR(). Il faudra ne pas oublier d’ajouter un blanc entre les parenthèses.
Afin d’ajouter 1 au résultat de la fonction COUNT, il faut utiliser la macro fonction %EVAL. Le contenu des macro variables sont sinon tous interprétés comme du texte, qu’il s’agisse de nombres ou pas.
Enfin, pour que cette macro variable TOT_WRD soit utilisable en dehors de la macro, il faut qu’elle soit globale. Hors par défaut, une macro variable créée dans une macro est locale, c’est-à-dire n’existe que le temps de la macro. L’instruction %GLOBAL TOT_WRD; résouds le problème.
4. Tester la macro dans le cadre de sa validation
Que se passe t-il quand on ne change pas la valeur par défaut du paramètre de macro ?
%cnt_wrd;
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il quand le paramètre de macro TXT est vide de texte ?
%put Valeur de TOT_WRD: &tot_wrd;
%cnt_wrd(txt=);
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il lorsqu’il n’y a qu’un mot?
%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il quand il y a plusieurs mots ?
%cnt_wrd(txt=mot1 mot2 mot3);
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?
%cnt_wrd(txt= mot1 mot2 mot3 );
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?
%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;
Que se passe t-il quand la macro est appelée plusieurs fois ?
%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;
%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;
Lecture complémentaire

Une fonction LIBREF au résultat inattendu
mars 23, 2010La fonction LIBREF vérifie l’existence d’une bibliothèque. Vu que la réponse attentue est oui ou non, on pourrait s’attendre à une résultat binaire avec zéro pour non et un pour oui. Dans les faits, cette fonction retourne zéro pour oui et toute autre valeur signifie non.
Voici un exemple.
1. Contexte, exemple
Vous cherchez à savoir si le chemin d’accès défini dans un paramètre de macro peut servir de bibliothèque. Une solution est de tenter de créer la bibliothèque et ensuite de vérifier si la bibliothèque a été créée ou non.
2. Le programme
Dans l’exemple qui suit, une macro TEST est créée. Elle a un paramètre DSNPATH=. Le chemin d’accès donné dans ce paramètre est utilisé pour créé la bibliothèque INLIB.
Ensuite pour les besoins de l’exemple, un message est ajouté dans la log au moyen des instructions %PUT.
- Tout d’abord, est indiqué dans la log la valeur prise par le paramètre de macro DSNPATH.
- Puis, la valeur prise par la fonction LIBREF est affiché dans la log.
Afin de pouvoir utiliser cette fonction hors d’une étape data ou d’une procédure PROC SQL, il faut l’englober dans une macro fonction %SYSFUNC().
En fin de macro la référence à la bibliothèque est supprimée.
%macro test(dsnpath=);
libname inlib « &dsnpath. »;
%put MESSAGE: DSNPATH= &dsnpath.;
%put MESSAGE: Voir le résultat de la fonction LIBREF dans la log: %sysfunc(libref(inlib));
libname inlib;
%mend test;
Le premier appel de macro se fait avec un chemin d’accès valid. Tandis que le second appel de macro utilise un chemin d’accès erroné.
%test (dsnpath=C:/sasref);
%test (dsnpath=C:/sasre);
3. La log
Lorsque le chemin d’accès est correct, la fonction LIBREF retourne la valeur 0.
Quand le chemin d’accès n’est pas correct, la fonction LIBREF retourne une valeur différente de zéro. Dans l’exemple, il s’agit de la valeur -70008.
Lectures complémentaires
Autres articles sur %SYSFUNC
- Récupérer la valeur d’une option système, %SYSFUNC(GETOPTION())
- Evaluer le critère performance TEMPS d’un programme (%SYSFUNC, %SYSEVALF)
- Ajouter une date dans un nom de fichier Excel, Word…
- Combien d’observations dans mon data set ?
SAS Online Doc
- Summary Descriptions and Syntax
- LIBREF Function

Lire le contenu d’un catalogue pour macros
septembre 24, 2009Dans l’article « Sauvegarder une macro au delà d’une session« , vous avez vu comment créer un macro catalogue permanent. Ici, je vous propose de voir comment savoir quelles macros sont contenues dans ce fichier.
1. Rappel : ajouter une entrée dans un catalogue pour macros
Dans l’étape qui suit, la macro PERM_MACRO a été sauvée dans un catalogue pour macro. Le nom par défaut d’un catalogue pour macro est SASMACR. Celui-ci a été sauvegardé dans la bibliothèque SASREF.
libname sasref ‘C:/sasref’;
options sasmstore=sasref mstored;
%macro perm_macro /store;
proc print data=sashelp.class;
run;
%mend perm_macro;
2. Voir le contenu d’un catalogue pour macro
A présent, la procédure catalogue et plus particulièrement l’instruction CONTENTS permet de lire le contenu de SASMACR.
La procédure CATALOG peut être composée de plusieurs étapes. Pour voir le résultat en séquence de ces étapes une instruction RUN est ajoutée entre chacune d’elle. Un QUIT en fin de procédure permet de clore la procédure.
Ici comme une seule étape est requise, seul un RUN apparaît. Il est donc possible, dans ce cas précis de se contenter d’un QUIT.
- Avec RUN et QUIT, REAL et CPU times sont de 0.01 secondes.
- Avec seulement QUIT, REAL TIME=0.04 secondes et CPU TIME=0.00 secondes.
libname sasref ‘C:/sasref’;
proc catalog catalog=sasref.sasmacr;
contents;
run;
quit;
Ce contenu est affiché dans la fenêtre OUTPUT de SAS. Voir le résultat :
Lectures complémentaires

Plusieurs mots d’un paramètre de macro à mettre entre guillemets (%QSYSFUNC, %STR(), TRANWRD)
mai 28, 2009Mettre entre guillemets les mots contenus dans une macro variable SAS et les séparer par des virgules est possible au moyen des fonction %STR(), %QSYSFUNC et TRANWRD. Dans quel cas est-ce utile ? Comment se décompose cette syntaxe ?
1. Dans quel cas a-t-on besoin d’ajouter des guillemets et virgules ?
Lors de l’écriture d’une macro, vous pouvez avoir besoin d’autoriser plus d’un mot dans un des paramètres.
options mprint;
%macro test (multival=);
…
%mend test;
%test (multival=Alfred William);
Note : l’option MPRINT de l’instruction OPTIONS permettra de voir la résolution de la macro dans la log.
Ensuite, le contenu de ce paramètre traité comme une macro variable peut être appelé dans une condition. Dans l’exemple qui suit « Alfred », »William » sera remplacée par la macro variable mise à jour.
proc print data=sashelp.class (where=(name = (« Alfred », »William »));
run;
Il faut pour cela mettre la macro variable à jour en ajoutant des guillemets et la virgule comme séparateur.
2. Comment ajouter guillemets et virgules ?
2.1 Un mot
Dans le cas d’un paramètre avec un mot, on peut ajouter %str(% ») devant et derrière. Le symbole % permet d’introduire les caractères spéciaux comme le guillemet.
%let multival=%str(% »)&multival.%str(% »);
La macro donne alors :
%macro test (multival=);
%let multival=%str(% »)&multival.%str(% »);
proc print data=sashelp.class (where=(name = &multival.));
run;
%mend test;
%test (multival=Alfred);
2.2 Plus d’un mot
Pour mettre entre guillemets plus d’un mot, l’espace entre les mots sera remplacé par « , » (guillemet, virgule, guillemet) au moyen de la fonction TRANWRD.
%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))
Pour exécuter cette fonction, qui n’a pas d’équivalent dans les macros fonctions, il faut englober le tout dans %SYSFUNC/%QSYSFUNC. La présence de la virgule oblige dans notre cas à utiliser %QSYSFUNC.
%macro test (multival=);
%let multival=%str(% »)%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))%str(% »);
proc print data=sashelp.class (where=(name in (&multival.));
run;
%mend test;
%test (multival=Alfred William);
2.3 Plus d’un mot mis en majuscule
Enfin, pour ne pas tenir compte de la case, le texte peut être mis en majuscule au moyen de la fonction %UPCASE.
where=(upcase(name) in (%upcase(&multival.))
Cela donne :
%macro test (multival=);
%let multival=%str(% »)%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))%str(% »);
proc print data=sashelp.class (where=(upcase(name) in (%upcase(&multival.))));
run;
%mend test;
%test (multival=Alfred William);
Lectures complémentaires

Récupérer la valeur d’une option système dans une macro variable, %SYSFUNC(GETOPTION())
avril 30, 2009Les options SAS modifiables au moyen de l’instruction globale OPTIONS peuvent être retrouvées dans une étape data ou autre au moyen de %SYSFUNC(GETOPTION()).
Par exemple, cette semaine, j’ai eu besoin de savoir combien de caractères par ligne je pouvais entrer dans ma sortie (fenêtre OUTPUT). En d’autres termes, je voulais connaître la LINESIZE et en fonction d’elle ajuster les colonnes de mon listing généré au moyen d’un simple PROC REPORT.
1. Lire dans la LOG l’information
L’instruction PROC OPTIONS permet de lister toutes les options dans la fenêtre LOG de SAS. En ajoutant OPTION=, l’affichage est réduit à la seule option LINESIZE.
proc options option=linesize;
run;
Dans notre exemple, l’option LINESIZE est de 91. Jusqu’à 91 caractères pourront être affichés sur une même ligne avec un PROC PRINT ou autre.
LINESIZE=91 Line size for SAS log and SAS procedure output
NOTE: PROCEDURE OPTIONS used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
2. Sauvegarder l’information dans une macro variable
Pour illustrer la syntaxe %SYSFUNC(GETOPTION()), je choisi de sauvegarder l’information dans une macro variable appelée CURRENT_LS. Cette valeur est ensuite affichée dans la LOG au moyen de l’instruction %PUT.
%let current_ls=%sysfunc(getoption(linesize));
%put ¤t_ls.;
Vous pouvez directement inclure %SYSFUNC(GETOPTION()), dans une instruction globale comme TITLE si vous le souhaitez.
La liste des options du système SAS est grande. A vous d’explorer les possibilités que vous offre cette notation.

Evaluer le critère performance TEMPS d’un programme (%SYSFUNC, %SYSEVALF)
avril 10, 2009Un critère pour évaluer la performance d’un programme est de connaître son temps d’exécution. La fonction système %SYSFUNC permettra de récupérer le temps à un instant donné et la fonction %SYSEVALF servira à calculer la différence entre deux temps pré-enregistrés. Voici un exemple en 4 étapes.
1. Récupérer le temps en début de programme
Dans un premier temps, le temps de début est sauvegardé dans une macro variable TEMPS_DEBUT. Il est extrait au moyen de la fonction TIME() et est donc exprimé en secondes.
%let temps_debut = %sysfunc(time());
2. Exécuter la partie principale du programme
Pour l’exemple un simple PROC PRINT est ajouté comme partie principale du programme.
proc print data=sashelp.class;
run;
3. Récupérer le temps en fin de programme
Dans un troisième temps, le temps en fin de programme est sauvagardé dans la macro variable TEMPS_FIN. Comme précédemment; la fonction TIME() est utilisée.
%let temps_fin = %sysfunc(time());
4. Evalutation et affichage de la durée écoulée
La durée écoulé entre le début et la fin du programme est sauvegardée dans la macro variable DUREE. Cette durée est ensuite affichée dans la log au moyen de l’instruction %PUT.
Sur le même principe qu’une fonction %EVAL dans une macro, la fonction %SYSEVALF permet de considérer les deux variables TEMPS_DEBUT/TEMPS_FIN comme des nombres le temps du calcul de la différence.
%let duree = %sysevalf(&temps_fin.-&temps_debut.);
%put Durée d’exécution : &duree.;
Lectures complémentaires
- Ajouter une date dans le nom de fichier Word, Excel,…
- Combien d’observations dans mon data set
- Additionner deux macros variables : la fonction %EVAL
- Créer une date SAS de 3 manières
SAS Online Doc
- Using SAS Language Functions in the Data Step and Macro Facility
- %SYSFUNC and %QSYSFUNC Functions
- Summary Descriptions and Syntax
- %EVAL Function
- %SYSEVALF Function
- How the macro processor evaluates Arithmetic Expressions
- TIME Function

Les anniversaires, cela se fête avec SAS
avril 2, 2009Aujourd’hui étant mon anniversaire, je fais la paresseuse et vous communique un petit fichier SAS, reçu ce jour (merci Alex), à faire tourner sous Windows, écouteurs en place, pour la prochaine fois qu’un collègue ou pote qui connaît SAS soufflera ses bougies. Amusez-vous bien !
%let pc=1;
%macro sasreference_fr(note,octave,length);
select(¬e.);
when (‘A’) call sound (55*(2**&octave.),&length.*160*&pc.);
when (‘A#’) call sound (58*(2**&octave.),&length.*160*&pc.);
when (‘Bb’) call sound (58*(2**&octave.),&length.*160*&pc.);
when (‘B’) call sound (62*(2**&octave.),&length.*160*&pc.);
when (‘C’) call sound (65*(2**&octave.),&length.*160*&pc.);
when (‘C#’) call sound (69*(2**&octave.),&length.*160*&pc.);
when (‘Db’) call sound (69*(2**&octave.),&length.*160*&pc.);
when (‘D’) call sound (73.5*(2**&octave.),&length.*160*&pc.);
when (‘D#’) call sound (73.5*(2**&octave.),&length.*160*&pc.);
when (‘Eb’) call sound (78*(2**&octave.),&length.*160*&pc.);
when (‘E’) call sound (82*(2**&octave.),&length.*160*&pc.);
when (‘F’) call sound (87*(2**&octave.),&length.*160*&pc.);
when (‘F#’) call sound (92.5*(2**&octave.),&length.*160*&pc.);
when (‘Gb’) call sound (92.5*(2**&octave.),&length.*160*&pc.);
when (‘G’) call sound (98*(2**&octave.),&length.*160*&pc.);
when (‘G#’) call sound (104*(2**&octave.),&length.*160*&pc.);
when (‘Ab’) call sound (104*(2**&octave.),&length.*160*&pc.);
when (‘R’) call sleep((&length./3)*&pc.,1);
otherwise;
end;
%mend sasreference_fr;
data _null_;
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘D’,3,2);
%sasreference_fr(‘C’,3,2);
%sasreference_fr(‘F’,3,2);
%sasreference_fr(‘E’,3,4);
%sasreference_fr(‘R’,3,2);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘D’,3,2);
%sasreference_fr(‘C’,3,2);
%sasreference_fr(‘G’,3,2);
%sasreference_fr(‘F’,3,4);
%sasreference_fr(‘R’,3,2);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,4,2);
%sasreference_fr(‘A’,4,2);
%sasreference_fr(‘F’,3,1);
%sasreference_fr(‘F’,3,1);
%sasreference_fr(‘E’,3,2);
%sasreference_fr(‘D’,3,4);
%sasreference_fr(‘R’,3,2);
%sasreference_fr(‘Bb’,4,1);
%sasreference_fr(‘Bb’,4,1);
%sasreference_fr(‘A’,4,2);
%sasreference_fr(‘F’,3,2);
%sasreference_fr(‘G’,3,2);
%sasreference_fr(‘F’,3,4);
run;
Pour les curieux, je vous invite à consulter les programmes des chansons suivantes suggérées sur le forum de developpez.com :
Les plus téméraires s’intéresserons à la publication « Making Music in SAS« . Vos créations pourront être publiées sur le blog.
A lire aussi www.sasreference.fr :

Ajouter une date dans un nom de fichier Excel, Word…
mars 12, 2009Sous SAS, en créant un fichier .xls ou .rtf avec la syntaxe de l’ODS (Output Delivery System), il est parfois pratique d’ajouter dans le nom du fichier une date. Par exemple : listing_20090311.xls.
Nous verrons ici plusieurs représentations de la date et de l’heure : afin d’avoir des noms triables par ordre chronologique, l’année apparaît avant le mois et le jour.
La syntaxe proposée, %SYSFUNC(fonction, format), s’utilise dans d’autres cas que la définition d’un nom de fichier (.rtf, .xls, …). De manière générale, elle sert à utiliser des fonctions en dehors d’une étape data ou d’une procédure. Par exemple, elle peut être ajoutée dans une instruction TITLE.
1. L’objectif pour un programme exécuté le 11 mars 2009
L’objectif de l’exemple qui suit est d’obtenir un fichier .xls nommé class_20090311.xls dont la date change selon le jour de sa création.
La version fixe se présente ainsi : un fichier .xls est créé au moyen de ODS TAGSETS.EXCELXP. Il contient les données du data set SASHELP.CLASS. La création d’un fichier dans la fenêtre OUTPUT est suspendu le temps de la création du fichier .xls au moyen de l’instruction ODS LISTING CLOSE et ODS LISTING.
ods listing close; ods tagsets.excelxp file='C:/sasref/class_20090311.xls'; proc print data=sashelp.class; run; ods tagsets.excelxp close; ods listing;
2. Ajouter de la flexibilité avec %SYSFUNC
A présent, la date est définie automatiquement au moyen de la macro fonction %SYSFUNC. Cette fonction est dans ce cas particulier composée de deux paramètres :
- la date SAS extraite au moins de la fonction TODAY()
- le format à appliquer sur cette date
Résoudre le contenu de la fonction %SYSFUNC grâce aux guillemets doubles : la fonction %SYSFUNC fait partie du langage macro. Dès lors, pour obtenir la résolution de son contenu, il faut utiliser des guillemets doubles.
Retrouver la date d’exécution du programme grâce aux fonctions TODAY() ou DATE () : La fonction TODAY() retourne la date SAS d’exécution du programme. Une alternative est la fonction DATE(). Dans les deux cas, la fonction ne contient pas de paramètre.
Le format YYMMDDn. pour écrire 20090311 : Le format YYMMDDn. est un sous-ensemble de la fonction YYMMDD composée de 8 caractères, sauf indication contraire, faisant apparaître :
- l’année en premier,
- suivi du mois en chiffre et
- enfin du jour.
Ce format avec l’extension « n » a la particularité de ne pas utiliser de symbole ou espace séparatant le jour, du mois et de l’année. Les 8 caractères par défaut de la fonction laisse de la place à une année exprimée par 4 chiffres.
ods listing close; ods tagsets.excelxp file="C:/sasref/class_%sysfunc(today(),yymmddn.).xls"; proc print data=sashelp.class; run; ods tagsets.excelxp close; ods listing;
3. Tester d’autres formes d’affichage
3.1 Ajouter des tirets bas entre le jour, le mois et l’année grâce à la fonction TRANSLATE
class_2009_03_11.xls : pour avoir des tirets bas (underscore) entre le jour, le mois et l’année, il n’existe pas de format directement applicable. Une solution est alors d’utilise un autre symbole et de le remplacer avec la fonction TRANSLATE.
Ici le format YYMMDD10 retourne une date de la forme 20009-03-11. Les traits d’union (hyphen) sont remplacés par des tirets bas (underscore).
ods tagsets.excelxp file=« C:/sasref/class_%sysfunc(translate(%sysfunc(today(),yymmdd10.),’_’,’-‘)).xls »;
3.2 Ajouter une heure avec TIME() et PICTURE (class_20090311_113057.xls)
Quelle fonction pour l’heure ? : La fonction TIME() retourne l’heure sous la forme d’un time SAS.
Quels formats pour l’heure ? : Le format HHMM. retournera les heures et les minutes, tandis que le format TIME. retournera en plus les secondes. Dans les deux cas cependant, les heures avant 10h apparaissent avec seulement un chiffre : 9:30 et non 09:30. Un espace remplace le zéro manquant.
L’instruction PICTURE de PROC FORMAT pour un format personalisé : Une solution est de créer un format personalisé au moyen de l’instruction PICTURE (PICTURE statement). Comme les lettres H, M et S n’inclus pas de zéro devant (leading zero) pour les nombres à un chiffres, il faut les ajouter dans l’instruction PICTURE.
Note : %0S fait référence aux secondes. Il n’est obligatoire que si vous voulez des secondes dans votre texte final.
proc format;
picture sasref other=‘%0H%0M%0S’ (datatype=time);
run;
Ensuite,
- pour une heure à quatre chiffres (heure + minutes) , il faudra préciser le nombre 4 dans l’appel du format.
- pour une heures à six chiffres (heures + minutes + secondes), c’est 6 qui doit être ajouté
ods tagsets.excelxp file=« C:/sasref/class_%sysfunc(today(),yymmddn.)_%sysfunc(time(),sasref6.).xls »;
Lectures complémentaires sur http://www.sasreference.fr
ODS
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Partie 1/3)
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Partie 2/3)
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Parite 3/3)
Les fonctions
Les formats :
Les macros fonctions
- Additionner deux macros variables : la fonction %EVAL (usage de %SYSFUNC)
- Combien d’observations dans mon data set (usage de %SYSFUNC)

Sauvegarder une résolution de macro dans un fichier externe (l’option MFILE)
février 2, 2009Le programme SAS généré par un appel de macro peut être sauvegardé dans un fichier externe grâce à l’option globale MFILE. Quel est l’intérêt ? Comment concrètement cela se programme t-il ?A quoi ressemble le résultat ? C’est ce que je vous propose de découvrir dans cet article.
1. Quel est l’intérêt de sauvegarder le code généré par une macro?
- La résolution d’une macro dans la log avec l’option globale MPRINT est agrémenté d’information cachant le cœur du programme. Un accès au programme seul facilite la lisibilité.
- Extraire le code permet de l’exécuter morceau par morceau afin de s’assurer que la demande faite à SAS correspond à ses attentes et éventuellement trouver la cause d’un problème (to debug).
Le même type d’approche est possible avec un programme généré dans un DATA _NULL_.
2. Un exemple pour créer une étape data avec six instructions similaires
Dans cet exemple, le langage macro est utilisé pour générer six instructions dans une étape data au moyen d’une boucle.
A chaque nouvelle instruction une nouvelle variable est créée.
- Elle contient un nombre aléatoire extrait au moyen de la fonction RANUNI et sa racine variant de 1 à 6.
- Cette valeur est multipliée par 49 dans un premier temps.
- La valeur entière inférieure est gardée dans un second temps au moyen de la fonction FLOOR.
options mprint mfile; filename mprint 'C:/sasref/eg_mfile.sas'; %macro eg_mfile; data test; %do i=1 %to 6; var&i. = floor(ranuni(&i.)*49); %end; run; %mend eg_mfile; %eg_mfile;
2 points à respecter : On prendra bien soin de garder l’option MPRINT dans l’instruction OPTIONS et d’utiliser MPRINT comme nom de FILENAME.
3. Visualiser le contenu du fichier EG_MFILE.SAS
Le fichier EG_MFILE.SAS contient le contenu suivant :
data test; var1 = floor(ranuni(1)*49); var2 = floor(ranuni(2)*49); var3 = floor(ranuni(3)*49); var4 = floor(ranuni(4)*49); var5 = floor(ranuni(5)*49); var6 = floor(ranuni(6)*49); run;
Alors que la log, elle, contient des informations supplémentaires exploitables beaucoup moins rapidement.
MPRINT(EG_MFILE): data test; MPRINT(EG_MFILE): var1 = floor(ranuni(1)*49); MPRINT(EG_MFILE): var2 = floor(ranuni(2)*49); MPRINT(EG_MFILE): var3 = floor(ranuni(3)*49); MPRINT(EG_MFILE): var4 = floor(ranuni(4)*49); MPRINT(EG_MFILE): var5 = floor(ranuni(5)*49); MPRINT(EG_MFILE): var6 = floor(ranuni(6)*49); MPRINT(EG_MFILE): run;
Source : redscope.info/node/584 (ce site n’existe plus)

Sauvegarder une macro au delà d’une session SAS
janvier 8, 2009Par défaut, une macro est créée le temps d’une session. En effet, elle est sauvegardée dans le catalogue réservé aux macros (macro catalog) de la bibliothèque WORK. Comment changer la bibliothèque en vue d’une utilisation ultérieure de la macro ?
1. Par défaut, créer une macro temporaire
Dans un premier temps, une macro appelée TMP_MACRO est créée. Cette macro est sauvegardée dans un fichier appelé un macro catalog de la bibliothèque WORK.
%macro tmp_macro; proc print data=sashelp.class; run; %mend tmp_macro;
2. Sauvegarder de manière permanente la macro
A présent, il s’agit de sauvegarder la macro PERM_MACRO dans la biblioht`que SASREF. Comme précédemment, elle sera sauvegardée dans un catalogue ne pouvant contenir que des macro. Ce catalog s’appelle toujours SASMACR.
Grâce aux options SASMSTORED= et MSTORE, on précise à SAS que les macros à conserver (to store) seront à diriger dans la bibliothèque SASREF.
Ensuite, lors de la définition de la macro PERM_MACRO, on indique à SAS que cette macro fait partie des macros à conserver au delà de la session SAS. Elle sera donc sauvegardée dans la bibliothèque SASREF.
libname sasref 'C:/sasref'; options sasmstore=sasref mstored; %macro perm_macro /store; proc print data=sashelp.class; run; %mend perm_macro;
L’option STORE maintient la bibliothèque SASREF en activité. Il est alors impossible de désassigner la bibliothèque SASREF. Si vous avez une solution à ce problème, n’hésitez pas à nous la faire partager.
*libname sasref;

Mon paramètre de macro est-il rempli ?
mai 18, 2008Une macro sous SAS peut dans certains cas être comparée à un questionnaire. A chaque question (parameter) correspond plusieurs réponses possibles (parameter value). Certains réponses peuvent êtes obligatoires, d’autres facultatives. Dans le cas où la réponse est impérative mais n’est pas fournie par l’utilisateur, il faut pouvoir l’avertir : arrêter l’exécution du programme de manière propre et l’informer des éléments à fournir. Trois notions de programmation aideront à construire cette vérification (check).
1. Passer un message
Une condition en langage macro : ici, une macro est définie. Des instructions globales sont exécutées, si le paramètre de la macro est vide. Cette condition est donc définie avec une instruction du langage macro %IF … %THEN … %DO; …; %END;
Un message dans la log : l’objectif est d’informer l’utilisateur sur la nécessité d’une valeur pour le paramètre INPUT_VAL. Pour faire apparaître ce texte d’ERREUR dans la log, l’instruction du langage macro %PUT fera le travail.
Pas besoin de guillemets avec %IF ou %PUT : le paramètre d’une macro est une forme de macro variable. Pour retrouver sa valeur, son nom est donc entouré d’un symbole & et d’un point. Si cette valeur doit apparaître dans une chaîne de caractères entre guillemets, il faut impérativement utiliser des guillemets doubles. Dans le cas contraire, comme ici dans une instruction %IF ou %PUT, on se passe de guillemets pour résoudre la macro variable.
%macro test_param (input_val=,output_val=);
%if &input_val. = %then
%do;
%put ERREUR: Le macro paramètre INPUT_VAL= est obligatoire;
%end;
*suite du programme;
%mend test_param;
%test_param (input_val=,output_val=);
Personnaliser son message : quand SAS rencontre une erreur, il utilise le mot ERROR dans la log. Pour distinguer ce message des votre, vous pouvez ajouter un mot-clé comme le nom de la macro. Par exemple : « ERROR – TEST_PARAM: the INPUT_VAL= macro parameter is mandatory. ».
2. Gérer les caractères spéciaux : il est fréquent d’avoir des valeurs autres que les chiffres et les lettres de l’alphabet comme valeur pour un paramètre de macro. Vous aurez souvent besoin de définir l’emplacement des données sources et celui où les outputs seront sauvegardées. Pour cela, les paramètres auront des valeurs du type c:/mon_projet/mesdonnees ou encore c:/mon_projet/mes_resultats. Il existe des macros fonctions : %BQUOTE et %NBRQUOTE pour tenir compte de la barre inclinée (slash) et d’autres caractères spéciaux.
- %BQUOTE : les symboles suivants sont gérés avec la fonction %BQUOTE() : ‘ » ( ) + – * / < > = ¬ ^ ~ ; , blanc AND OR NOT EQ NE LE LT GE GT
- %NBRQUOTE : si, en plus, vous avez les symboles & (et) et % (pourcentage), il faudra faire appel à la macro fonction %NBRQUOTE().
SAS online DOC :
- %BQUOTE et %NBRQUOTE Functions
- Using the %BQUOTE and %NBRQUOTE Functions
3. Enjamber un programme
Si la condition n’est pas remplie, on peut demander à SAS d’ignorer une partie du code grâce à la syntaxe de %GOTO. Il était également possible de demander à SAS d’arrêter son exécution en plein milieu. Certes, enjamber le code permet d’avoir une log plus propre, puisque seuls nos messages apparaissent. Mais surtout, cela permet de poursuivre l’exécution du programme. Ainsi, si un appel de macro ne fonctionne pas, rien n’empêche de continuer la soumission d’autres appels de cette macro.
Dans un premier temps, il s’agit de définir une balise. A partir de cette position, SAS pourra continuer son exécution. Ici, la balise s’appelle FIN_PGM. Elle est ajoutée juste avant la fin du la macro.
Dans un second temps, si le paramètre est vide, SAS est prié d’ignorer le code qui suit jusqu’à la balise. Pour cela, dans la condition, l’instruction %GOTO est ajoutée.
%macro test_param (input_val=,output_val=);
%if &input_val. = %then
%do;
%put ERREUR: Le macro paramètre INPUT_VAL= est obligatoire;
%goto fin_pgm;
%end;
*suite du programme;
%fin_pgm:
%mend test_param;
%test_param (input_val=,output_val=);