Le piège classique est de penser que le macro processeur comprend le format '01JAN2020'd comme le ferait un Data Step. Pour une macro, c'est juste une chaîne de caractères. Pour effectuer des opérations mathématiques (j+7), vous devez impérativement convertir cette chaîne en nombre pur via %sysfunc(inputn(...)) avant d'utiliser %eval. C'est la seule façon de rendre une boucle temporelle robuste
Dans une Macro, tout est CHAÎNE DE CARACTÈRES.
L'utilisateur a tenté ceci :
%let i = '01Oct2007'd; /* &i contient le texte "'01Oct2007'd" */
%let i = %eval(&i + 7); /* ERREUR ! */
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.
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 :
%macro loop;
/* 1. On convertit le littéral en nombre (ex: 17440) grâce à PUTN ou INPUTN */
/* Note: Ici on utilise l'astuce de formater le littéral en nombre brut '8.' */
%let i = %sysfunc(putn('01Oct2007'd, 8.));
/* On convertit aussi la borne de fin */
%let fin = %sysfunc(putn('31Dec2007'd, 8.));
/* 2. La boucle compare maintenant deux nombres entiers */
%do %until (&i >= &fin);
/* 3. L'incrémentation fonctionne car &i est un entier */
%let i = %eval(&i + 7);
/* 4. Pour l'affichage, on re-transforme le nombre en date lisible */
%put %sysfunc(putn(&i, date9.));
%end;
%mend loop;
%loop;
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.
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.
Aviso importante
Los códigos y ejemplos proporcionados en WeAreCAS.eu son con fines educativos. Es imperativo no copiarlos y pegarlos ciegamente en sus entornos de producción. El mejor enfoque es comprender la lógica antes de aplicarla. Recomendamos encarecidamente probar estos scripts en un entorno de prueba (Sandbox/Dev). WeAreCAS no acepta ninguna responsabilidad por cualquier impacto o pérdida de datos en sus sistemas.
SAS y todos los demás nombres de productos o servicios de SAS Institute Inc. son marcas registradas o marcas comerciales de SAS Institute Inc. en los EE. UU. y otros países. ® indica registro en los EE. UU. WeAreCAS es un sitio comunitario independiente y no está afiliado a SAS Institute Inc.
Este sitio utiliza cookies técnicas y analíticas para mejorar su experiencia.
Saber más.