Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nota:
Los grupos de interés de la comunidad ahora se han movido de Yammer a Microsoft Viva Engage. Para unirse a una comunidad viva Engage y participar en las últimas discusiones, rellene el formulario Solicitar acceso a Finance and Operations Viva Engage Community y elija la comunidad a la que desea unirse.
En este artículo se describe cómo crear y usar macros en X++.
Las directivas del precompilador, es decir, las macros, se procesan conceptualmente antes de compilar el código. Las directivas declaran y controlan macros y sus valores. Las directivas se reemplazan por el contenido que designan, por lo que el compilador nunca los encuentra. El compilador X++ solo ve la secuencia de caracteres escritos en el código X++ por las directivas .
Advertencia
Las macros son características heredadas y pueden quedar en desuso en futuras versiones. Use construcciones de lenguaje en su lugar: en lugar de macros, use construcciones de lenguaje como estas:
- Constantes
- Sysda para consultas.
Definición de macros
Defina una macro con nombre mediante la sintaxis que se muestra a continuación.
- #define. MyMacro(Value) crea una macro con un valor opcional.
- #if. MyMacro comprueba si se define una macro.
- #undef. MyMacro quita una definición de macro.
directivas #define y #if
Todas las directivas y símbolos del precompilador comienzan con el # carácter .
Defina una macro con la siguiente sintaxis:
#define.MyMacro(Value) // creates a macro with a value.
#define.AnotherMacro() // creates a macro without a value.
Puede definir una macro en cualquier parte del código. La macro puede tener un valor que sea una secuencia de caracteres, pero no es necesario tener un valor. La #define directiva indica al precompilador que cree la variable de macro, opcionalmente, incluido un valor.
La #if directiva comprueba si la variable está definida y, opcionalmente, si tiene un valor específico, como se muestra en el ejemplo siguiente:
#if.MyMacro
// The MyNaacro is defined.
#endif
#ifnot.MyMacro
// The MyNaacro is not defined.
#endif
Las directivas del precompilador X++, los nombres de macro que definen y las #if pruebas de valor de directiva no distinguen mayúsculas de minúsculas. Sin embargo, defina los nombres de macro que comienzan con una letra mayúscula.
directiva #undef
Use la #undef directiva para quitar una definición de macro que exista de un objeto anterior #define.
#undef.MyMacro
#if.MyMacro
// The macro is not defined, so this is not included
#endif
Puede volver a definir un nombre de macro con #undef el que ha quitado mediante otro #define.
Usar un valor de macro
Puede definir un nombre de macro para tener un valor.
#define.Offset(42)
...
print #Offset; // 42
Un valor de macro no tiene un tipo de datos determinado: es simplemente una secuencia de caracteres. Asigne un valor a una macro proporcionando el valor entre paréntesis al final de una #define.MyMacro directiva. Use el símbolo de macro donde quiera que se produzca el valor en el código X++. Un símbolo de macro es el nombre de la macro con el # carácter agregado como prefijo. En el ejemplo de código siguiente se muestra un símbolo de macro #MyMacro. El símbolo se reemplaza por el valor de la macro.
Probar un valor de macro
Puede probar una macro para determinar si tiene un valor. También puede determinar si su valor es igual a una secuencia específica de caracteres. Estas pruebas permiten incluir condicionalmente líneas de código en el programa X++. No hay ninguna manera de probar si una macro definida tiene un valor. Solo puede probar si el valor de macro coincide con un valor específico. Como procedimiento recomendado, defina siempre un valor para cualquier nombre de macro que defina o nunca defina un valor. Cuando se alterna entre estos modos, el código resulta difícil de entender.
directivas #defInc y #defDec
#defInc y #defDec son las únicas directivas que interpretan el valor de una macro. Solo se aplican a las macros que tienen un valor que el precompilador puede convertir al tipo int formal. Estas directivas cambian el valor numérico de una macro en tiempo de compilación. El valor solo puede contener números. El único carácter no numérico permitido es un signo negativo inicial (-). El valor entero se trata como un entero X++, no como un valor int64. Para los nombres de macro que usa la #defInc directiva, la #define directiva que crea la macro no debe residir en una declaración de clase. El comportamiento de #defInc en estos casos es impredecible. En su lugar, defina estas macros solo en un método . Use las #defInc directivas y #defDec solo para las macros que tienen un valor entero. El precompilador sigue reglas especiales para #defInc cuando el valor de la macro no es un entero o cuando el valor es inusual o extremo. En la tabla siguiente se enumeran los valores que #defInc se convierten en cero (0) y, a continuación, se incrementan. Cuando #defInc convierte un valor en 0, no se puede recuperar el valor original, ni siquiera mediante #defDec.
| Valor de macro | defInc Value | Comportamiento |
|---|---|---|
| (+55) | 56 | El prefijo de signo positivo (+) hace que el precompilador trate este valor como una cadena no numérica. El precompilador trata todas las cadenas no numéricas como 0 cuando controla una #defInc directiva (o #defDec). |
| ("3") | 1 | Los enteros entre comillas se tratan como 0. |
| ( ) | 1 | Una cadena de espacios se trata como 0. |
| () | 1 | Una cadena de longitud cero se trata como 0. |
| (Cadena aleatoria). | 1 | Cualquier cadena no numérica de caracteres se trata como 0. |
| (0x12) | 1 | Los números hexadecimales se tratan como cadenas no numéricas. Por lo tanto, el precompilador los convierte en 0. |
| (-44) | -43 | Los números negativos son aceptables. |
| (2147483647) | -2147483648 | El valor int positivo máximo se desborda al valor int negativo mínimo por #defInc. |
| (999888777666555) | 1 | Cualquier gran número, más allá de la capacidad de int e int64. |
| (5.8) | 1 | Los números reales se interpretan como 0. |
| 1 | Cuando no se proporciona ningún valor ni paréntesis para la directiva #define.MyValuelessMacro , el valor es 0. |
directiva #globaldefine
La #globaldefine directiva es similar a la #define directiva . Use #define en lugar de #globaldefine.
directivas #localmacro y #macro
La #localmacro directiva es una buena opción cuando desea que una macro tenga un valor de varias líneas largas o cuando el valor de la macro contenga un paréntesis de cierre, lo que hace que sean buenos candidatos para contener fragmentos de código fuente.
#macro.RetailMatchedAggregatedSalesLine(
%1.price == %2.price
&& %1.businessDate == %2.businessDate
&& %1.itemId == %2.itemId
&& ((((%3) && (%1.qty <= 0)) || ((! %3) && (%1.qty > 0))) || (%4))
)
#endmacro
La #localmacro directiva se puede escribir como #macro. Sin embargo, #localmacro es el término recomendado. Mediante la #if directiva , puede probar si se declara un nombre de macro con la #define directiva . Sin embargo, no se puede probar si el nombre de la macro se declara con la #localmacro directiva . Solo las macros declaradas mediante la #define directiva se ven afectadas por la #undef directiva . En una #define directiva, puede especificar un nombre que ya esté en el ámbito como .#localmacro El efecto es descartar #localmacro y crear una #define macro. Esto también se aplica a la secuencia opuesta, lo que significa que un #localmacro elemento puede volver a definir un #define. Un #localmacro (que tiene un nombre de macro y un valor) siempre invalida un anterior #localmacro que tiene el mismo nombre. Este mismo problema se produce con #globaldefine. La principal diferencia entre una #define macro y una #localmacro macro es cómo finaliza su sintaxis. Los terminadores son los siguientes:
-
#define– termina por–) -
#localmacro– termina por–#endmacro
#localmacro es una mejor opción para las macros con varios valores de línea. Normalmente, varios valores de línea son líneas de código X++ o SQL. X++ y SQL contienen muchos paréntesis, y estos finalizarían prematuramente un #define. Tanto #define como #localmacro se pueden declarar y terminar en una sola línea o en líneas posteriores. En la práctica, se #define termina en la misma línea en la que se declara. En la práctica, el #localmacro objeto finaliza en una línea posterior.
Parámetros de macro
Puede definir valores de macro para incluir símbolos de parámetro. El primer símbolo de parámetro es %1, el segundo es %2y así sucesivamente. Se pasan valores para los parámetros al hacer referencia al nombre del símbolo de macro para la expansión. Los valores de los parámetros de macro son secuencias de caracteres sin tipo formal y están delimitados por comas. No hay ninguna manera de pasar una coma como parte de un valor de parámetro. El número de parámetros pasados puede ser menor que, mayor o igual que el número de parámetros que el valor de la macro está diseñado para recibir. El sistema tolera errores de coincidencia en el número de parámetros pasados. Si se pasan menos parámetros que la macro espera, cada parámetro omitido se trata como una secuencia de caracteres de longitud cero.
Anidar símbolos de macro
Puede anidar directivas de definición del precompilador dentro de una directiva de definición externa. Las directivas de definición principal son #define y #localmacro.
Una #define directiva se puede dar dentro de una #localmacro directiva y un #localmacro elemento puede estar dentro de .#define
directiva #macrolib
En el Explorador de aplicaciones, en el nodo Macros del nodo Código, hay muchos nodos de biblioteca que contienen conjuntos de directivas de macro. Tanto #define como #localmacro a menudo aparecen en el contenido de estas bibliotecas de macros. Puede usar el #macrolib. MyAOTMacroLibrary para incluir el contenido de una biblioteca de macros en el código X++. Las #if directivas y #undef no se aplican a #macrolib los nombres. Sin embargo, se aplican a #define las directivas que son el contenido de una #macrolib macro. La directiva #macrolib. MyAOTMacroLibrary también se puede escribir como #MyAOTMacroLibrary. Se recomienda el #macrolib prefijo porque nunca es ambiguo para una persona que más adelante lee el código.
Directiva #linenumber
Puede usar la directiva durante el #linenumber desarrollo y la depuración del código. Se reemplaza por el número de línea físico del archivo de código antes de cualquier expansión de macro.
Ámbito de macro
El intervalo en el que puede hacer referencia a una macro depende de dónde defina la macro. En una clase, puede hacer referencia a macros que defina en la clase primaria. Cuando el precompilador controla una clase secundaria, primero realiza un seguimiento de la cadena de herencia a la clase raíz. A continuación, el precompilador procesa todas las directivas de la clase raíz a la clase que se está compilando. Almacena todas las macros y sus valores en sus tablas internas. Los resultados de las directivas de cada declaración de clase se aplican a las tablas internas que ya se rellenan de directivas que se encontraron anteriormente en la cadena de herencia.
Sin embargo, el precompilador controla cada método por separado. Actualiza sus tablas internas para que pueda restaurar el estado de las tablas a medida que estaban antes de procesar el método actual. Una vez que el precompilador controla el primer método, restaura las tablas internas antes de controlar el método siguiente.
En este contexto, un método se define como el contenido de un nodo de método en el árbol de objetos de aplicación (AOT). En AOT, puede expandir el nodo Clases, expandir un nodo de clase, hacer clic con el botón derecho en un nodo de método y, a continuación, seleccionar Editar. A continuación, puede agregar una línea para #define.MyMacro("abc") antes de la declaración del método. El precompilador trata esta #define directiva como parte del método , aunque #define se produce fuera del {} bloque del método .