SAS9

Gérer les boucles de dates en Macro

Simon 8 views

Un défi classique pour tout programmeur SAS© est de transformer une boucle Data Step simple en une Macro dynamique. L'opération date + 7 jours devient soudainement complexe.

Pourquoi le copier-coller échoue-t-il ? Et comment manipuler le temps dans le processeur macro ? Voici les explications tirées de la discussion.

1. Le Problème : Littéral vs Texte

Dans un Data Step, SAS© interprète intelligemment les dates. Quand vous écrivez i = '01Oct2007'd;, SAS© convertit immédiatement ce littéral en un nombre (le nombre de jours depuis 1960). L'opération i + 7 est donc une simple addition mathématique.

Dans une Macro, tout est CHAÎNE DE CARACTÈRES. L'utilisateur a tenté ceci :

1%let i = '01Oct2007'd;
2/* &i contient le texte "'01Oct2007'd" */
3%let i = %eval(&i + 7);
4/* ERREUR ! */
La fonction %eval (calculatrice d'entiers macro) voit le texte '01Oct2007'd + 7. Elle ne sait pas convertir le littéral '...'d en nombre. Elle échoue donc à faire l'addition.

2. La Solution : Passer par la valeur numérique (%SYSFUNC)

Comme l'explique Linda (LAP), pour faire des maths en macro, vous devez travailler avec des nombres purs, pas des dates formatées.

Il faut utiliser %sysfunc() pour accéder aux fonctions de conversion de SAS©.

La démarche correcte :

  1. Convertir la date texte en nombre SAS© dès le début.

  2. Calculer (boucler, incrémenter) sur ce nombre.

  3. Re-formater le nombre en date lisible uniquement pour l'affichage/utilisation finale.

Le Code Corrigé

Voici comment transformer la logique de l'utilisateur en macro fonctionnelle :

1%macro loop;
2 /* 1. On convertit le littéral en nombre (ex: 17440) grâce à PUTN ou INPUTN */
3 /* Note: Ici on utilise l'astuce de formater le littéral en nombre brut '8.' */
4 %let i = %sysfunc(putn('01Oct2007'd, 8.));
5
6 /* On convertit aussi la borne de fin */
7 %let fin = %sysfunc(putn('31Dec2007'd, 8.));
8 
9 /* 2. La boucle compare maintenant deux nombres entiers */
10 %DO %until (&i >= &fin);
11
12 /* 3. L'incrémentation fonctionne car &i est un entier */
13 %let i = %eval(&i + 7);
14
15 /* 4. Pour l'affichage, on re-transforme le nombre en date lisible */
16 %put %sysfunc(putn(&i, date9.));
17
18 %END;
19%mend loop;
20 
21%loop;

3. L'Alternative : %SYSEVALF

L'expert Peter_C mentionne une fonction plus puissante : %sysevalf. Contrairement à %eval (qui ne gère que les entiers), %sysevalf (System Evaluation Floating) gère les nombres à virgule, mais est aussi capable de mieux interpréter certains littéraux de date s'ils sont entre guillemets doubles.

Cependant, la méthode la plus robuste reste la conversion explicite en nombre via %sysfunc.

ContexteGestion des datesExemple
Data StepAutomatique (littéraux 'ddMMMyyyy'd)date + 1;
MacroManuelle (tout est texte)%eval(%sysfunc(inputn(&date,date9.)) + 1);

Règle d'or : Le processeur macro est "aveugle" aux types de données. Si vous voulez faire des maths, donnez-lui des nombres purs. Si vous voulez des dates, convertissez-les en nombres avant de les lui passer.