SAS9

Gestionar bucles de fechas en Macro

Simon 10 views

Un desafío clásico para cualquier programador SAS© es transformar un simple bucle Data Step en una Macro dinámica. La operación date + 7 jours se vuelve repentinamente compleja.

¿Por qué falla el copiar y pegar? ¿Y cómo manipular el tiempo en el procesador de macros? Aquí están las explicaciones extraídas de la discusión.

1. El Problema: Literal vs Texto

En un Data Step, SAS© interpreta las fechas de forma inteligente. Cuando escribes i = '01Oct2007'd;, SAS© convierte inmediatamente este literal en un número (el número de días desde 1960). La operación i + 7 es, por lo tanto, una simple suma matemática.

En una Macro, todo es CADENA DE CARACTERES. El usuario intentó esto:

1%let i = '01Oct2007'd;
2/* &i contient le texte "'01Oct2007'd" */
3%let i = %eval(&i + 7);
4/* ERREUR ! */
La función %eval (calculadora de enteros de macro) ve el texto '01Oct2007'd + 7. No sabe cómo convertir el literal '...'d a número. Por lo tanto, falla al realizar la suma.

2. La Solución: Pasar por el valor numérico (%SYSFUNC)

Como explica Linda (LAP), para hacer matemáticas en macro, debes trabajar con números puros, no con fechas formateadas.

Es necesario usar %sysfunc() para acceder a las funciones de conversión de SAS©.

El enfoque correcto:

  1. Convertir la fecha de texto en número SAS© desde el principio.

  2. Calcular (bucle, incrementar) sobre este número.

  3. Reformatear el número a una fecha legible solo para la visualización/uso final.

El Código Corregido

Así es como se transforma la lógica del usuario en una macro funcional:

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. La Alternativa: %SYSEVALF

El experto Peter_C menciona una función más potente: %sysevalf. A diferencia de %eval (que solo maneja enteros), %sysevalf (System Evaluation Floating) maneja números decimales, pero también es capaz de interpretar mejor ciertos literales de fecha si están entre comillas dobles.

Sin embargo, el método más robusto sigue siendo la conversión explícita a número a través de %sysfunc.

ContextoGestión de fechasEjemplo
Data StepAutomático (literales 'ddMMMyyyy'd)date + 1;
MacroManual (todo es texto)%eval(%sysfunc(inputn(&date,date9.)) + 1);

Regla de oro: El procesador de macros es "ciego" a los tipos de datos. Si quieres hacer matemáticas, dale números puros. Si quieres fechas, conviértelas a números antes de pasárselas.