El estamento select de X++ comparado con el estamento select del ANSI SQL
Simple Select sobre una Tabla
static void OrderByWhereJob(Args _args)
{
CustTable axCustTable;
;
while
select * from axCustTable
order by axCustTable.AccountNum desc
where (!(axCustTable.Name like ‘*ant*’)
&& axCustTable.Name like ‘T?e*’)
{
info(axCustTable.AccountNum + »
axCustTable.Name);
}
}
- En la clausula FROM se usa la variable Buffer de la tabla, no la tabla.
- La clausula ORDER BY precede a la clausula SELECT.
- Usamos ! para la negación lógica, no NOT.
- & y || son los operadores lógicos, no AND y OR.
- * y ? para comodines en la clausula LIKE, no % y _.
Clausula Join
static void OrderByWhereoinJob(Args _args)
{
CustTable axCustTable;
SalesPool axSalesPool;
;
while
select AccountName, Name
from axCustTable
order by axCustTable.AccountNum desc
where (axCustTable.Name like ‘*ant*’)
join axSalesPool
where axCustTable.salesPoolId ==
axSalesPool.SalesPoolId
{
info(axCustTable.AccountNum + »
axCustTable.Name);
}
}
- Solo se pueden seleccionar columnas de la primera tabla nombrada en la clausula FROM (las columnas no deben de llevar cualificadores)
- No usamos en el JOIN la palabra clave ON, simplemente lo hacemos con un WHERE.
- El JOIN será por defecto INNER JOIN. El OUTER JOIN está también disponible.
- La dirección del JOIN es LEFT. Se puede usar el RIGHT.
- Un doble igual == es usado como comparador, y no un simple igual =.
Campos Calculados
static void SumJob(Args _args)
{
PurchLine axPurchLine;
;
while
select sum(QtyOrdered)
from axPurchLine
{
info(«Cantidad: » +
num2str(axPurchLine.QtyOrdered, 3,2,1,3);
}
}
- Debemos referirnos al campo calculado con el nombre de su columna, ya que este no puede llevar un Alias.
Otras diferencias
-
El estamento WHILE SELECT del SQL de X++, nos proporciona un cursor automático para las filas devueltas.
-
No disponemos de la palabra clave HAVING, que en ANSI SQL permite indicar un filtro a las filas devueltas con una clausula GROUP BY.
-
Los valores nulos (Null) no serán devueltos. Si un valor es nulo, la fila es ignorada( tanto por WHILE como por NEXT).
-
La clausula FROM es opcional cuando no indiquemos columnas (usemos *), o solo una tabla participa en en SELECT. En X++ es lo mismo decir estas dos sentencias:
select * from Custtable;
select CustTable
Como crear un documento Word desde Axapta
Usando desde AXAPTA la interfaz COM podemos conectar con una aplicación externa como Microsoft Word.
En el siguiente ejemplo creamos un nuevo documento Microsoft Word.
Tenga en cuenta que debe de tener en AXAPTA el código de licencia necesario para que un cliente COM haga uso de la interfaz.
static void GenJob87(Args _args)
{
COM wordApplication;
COM wordDocuments;
COM wordDocument;
COM wordRange;
;wordApplication = new COM("word.application");
wordApplication.visible(true);
wordDocuments = wordApplication.Documents();wordDocument = wordDocuments.add();
wordDocument.saveas("c:\\Hola mundo.doc");
wordDocument.activate();wordRange = wordDocument.range(0,0);
wordRange.insertafter("Hola a todos desde Axapta vía AxaptaMente");wordDocument.save();
wordDocument.close();wordApplication.quit();
}
La potencia de los MenuItems en Axapta
Los MunuItems constituyen una de las áreas principales del control de los permisos de usuarios de AXAPTA. Las propiedades ConfigurationKey y SecurityKey permiten determinar cuando un usuario o un grupo de usuarios podrán acceder a un ítem de un menú. Si un usuario no tiene los privilegios para ejecutar un MenuItem, este no será visible para el usuario. Su potencia radica en que solo los MenuItems accesibles al usuario serán los visibles. Con esto se consigue que cada usuario solo vea las partes de la aplicación que son relevantes para su trabajo.
Otra de las áreas principales del control de permisos de usuarios son las tablas, pero eso ya lo discutiremos en próximas entradas.
Un MenuItem puede ser usado para instanciar un objeto desde un menú, desde un formulario que llame a otro objeto o desde el propio código. Lo objetos que formen parte de la interfaz de un usuario deberían ser siempre llamados usando un MenuItem.
Podríamos llamar a los formularios y los informes desde el código sin usar un MenuItem, pero si utilizamos un MenuItem podemos estar seguros que los permisos de usuario serán verificados.
static void GenEjecutaMenuItem(Args _args)
{
;
new menuFunction(menuItemDisplayStr (MiFormMenuItem).MenuItemType::Dysplay).run();
}
En el ejemplo, el formulario MiForm es llamado usando el display MenuItem MiFormMenuItem. El formulario solo será cargado si el usuario tiene asignados privilegios suficientes para ello. El método run() ejecuta el MenuItem y pasa la clase Args como parámetro. Por ejemplo podríamos filtrar los datos en MiForm usando los valores de Args.
Otra manera de pasar parámetros desde el el MenuItem es usando sus propiedades EnumTypeParameter y EnumParameter.
Configurando un parámetro enumerado en un MenuItem es fácil reutilizar un objeto, tal como un formulario, para realizar distintos propósitos sin tener que crear formularios similares.
La clase Args()
En AXAPTA la System Class Args se usa para gestionar parámetros.
En toda clase que se piense ejecutar debe de existir un método main que recibe Args como argumento. El propósito de Args es transferir parámetros entre distintos objetos.
La clase Args define la comunicación entre los distintos objetos de la aplicación que se están ejecutando. El objeto invocante (caller) es el que inicializa la información del objeto Args, el cual es pasado como argumento al objeto que es invocado (called).
static void main(Args _args)
{
CustTable custTable;
;if (_args.dataset() == TableNum(CustTable))
{
custTable = _args.record();
info(strfmt("Cliente seleccionado: %1",
custTable.name);
}
}
Si creásemos una nueva clase con ese método main y un MenuItem que llame a dicha clase, podriamos arrastra desde el AOT ese MenuItem al nodo diseño de un formulario que se nutra de CustTable para crear un botón que al pulsarse mostraría el nombre del cliente seleccionado.
Colores en páginas HTML
El uso del color en un documento solo tiene sentido únicamente cuando va a ser visualizado o impreso en un dispositivo capaz de reproducir ese tipo de información, tal como puede ser una pantalla o una impresora a color. La composición de los colores difiere según el dispositivo. Si se va a utilizar como soporte del documento un papel, lo usual es partir de un fondo blanco al que se le van añadiendo unos colores base, concretamente celeste, magenta y amarillo, para conseguir otros, siendo el negro la combinación de esos tres. En contraposición, si el documento va a ser visualizado en una pantalla, se parte de un fondo negro y los colores básicos son rojo, verde y azul, cuya adición va produciendo los restantes colores hasta llegar al blanco como combinación de los tres.
Dado que los navegadores muestran los documentos HTML en una pantalla, no es de extrañar que el modelo de color utilizado en HTML sea el RGB (Red, Green, Blue).
Un color codificado en RGB se compone de tres bytes, o lo que es lo mismo, 24 bits, utilizándose un byte, 8 bits, para cada componente: rojo, verde y azul. Con 8 bits pueden representarse 256 colores diferentes: de 0 a 255 en decimal o de 00 a FF en hexadecimal. Esto significa que podríamos definir colores usando 256 tonalidades para rojo, otras tantas para verde y lo mismo para el azul. Si por cada rojo tenemos 256 de verde y por cada verde 256 de azul, una simple multiplicación: 256x256x256 nos dirá el número total de colores que podemos obtener: 16.777.216. Más de dieciséis millones de colores.
NOTA:
En realidad no son 16 millones de colores diferentes, ya que además de colores realmente distintos existirán miles de tonalidades o matices de un mismo color. En muchas ocasiones nuestra vista ni siquiera nos permitirá apreciar esas pequeñas diferencias.
Para asignar al atributo color, o cualquier otro que acepte un color, un valor RGB tendremos que expresarlo así:
color="#rrvvaa"
La almohadilla que precede a la secuencia de dígitos indica que se trata de un código RGB en hexadecimal. Los valores de rr, vv, aa, indicarán la intensidad de rojo, verde y azul, respectivamente, a usar para obtener el color. Cada uno de ellos debe de estar comprendido entre 00 y FF.
Colores más usuales:
Color | Nombre | Código |
---|---|---|
Snow | #FFFAFA | |
Ghost White | #F8F8FF | |
White Smoke | #F5F5F5 | |
Gainsboro | #DCDCDC | |
FloralWhite | #FFFAF0 | |
Old Lace | #FDF5E6 | |
Linen | #FAF0E6 | |
Antique White | #FAEBD7 | |
Papaya Whip | #FFEFD5 | |
Blanched Almond | #FFEBCD | |
Bisque | #FFE4C4 | |
PeachPuff | #FFDAB9 | |
Navajo White | #FFDEAD | |
Moccasin | #FFE4B5 | |
Cornsilk | #FFF8DC | |
Ivory | #FFFFF0 | |
Lemon Chiffon | #FFFACD | |
Seashell | #FFF5EE | |
Honeydew | #F0FFF0 | |
Mint Cream | #F5FFFA | |
Azure | #F0FFFF | |
Alice Blue | #F0F8FF | |
Lavender | #E6E6FA | |
Lavender Blush | #FFF0F5 | |
Misty Rose | #FFE4E1 | |
White | #FFFFFF | |
Black | #000000 | |
Dark Slate Gray | #2F4F4F | |
Dim Grey | #696969 | |
SlateGrey | #708090 | |
Light Slate Gray | #778899 | |
Dark Grey | #A9A9A9 | |
Gray | #BEBEBE | |
Light Gray | #D3D3D3 | |
Midnight Blue | #191970 | |
Navy Blue | #000080 | |
Cornflower Blue | #6495ED | |
Dark Slate Blue | #483D8B | |
Slate Blue | #6A5ACD | |
Medium Slate Blue | #7B68EE | |
Light Slate Blue | #8470FF | |
Medium Blue | #0000CD | |
Royal Blue | #4169E1 | |
Blue | #0000FF | |
Dodger Blue | #1E90FF | |
Deep Sky Blue | #00BFFF | |
Sky Blue | #87CEEB | |
Light Sky Blue | #87CEFA | |
Steel Blue | #4682B4 | |
Light Steel Blue | #B0C4DE | |
Light Blue | #ADD8E6 | |
Powder Blue | #B0E0E6 | |
Pale Turquoise | #AFEEEE | |
Dark Turquoise | #00CED1 | |
Medium Turquoise | #48D1CC | |
Turquoise | #40E0D0 | |
Cyan | #00FFFF | |
Light Cyan | #E0FFFF | |
Cadet Blue | #5F9EA0 | |
Medium Aquamarine | #66CDAA | |
Aquamarine | #7FFFD4 | |
Dark Green | #006400 | |
Dark Olive Green | #556B2F | |
Dark Sea Green | #8FBC8F | |
Sea | #2E8B57 | |
Medium Sea Green | #3CB371 | |
Light Sea Green | #20B2AA | |
Pale Green | #98FB98 | |
Light Green | #90EE90 | |
Spring Green | #00FF7F | |
Lawn Green | #7CFC00 | |
Green | #00FF00 | |
Chartreuse | #7FFF00 | |
Medium Spring Green | #00FA9A | |
Green Yellow | #ADFF2F | |
Lime Green | #32CD32 | |
Yellow Green | #9ACD32 | |
Forest Green | #228B22 | |
Olive Drab | #6B8E23 | |
Dark Khaki | #BDB76B | |
Pale Goldenrod | #EEE8AA | |
Light Goldenrod | #FAFAD2 | |
Light Yellow | #FFFFE0 | |
Yellow | #FFFF00 | |
Gold | #FFD700 | |
Light Goldenrod | #EEDD82 | |
Goldenrod | #DAA520 | |
Dark Goldenrod | #B8860B | |
Rosy Brown | #BC8F8F | |
Indian Red | #CD5C5C | |
Saddle Brown | #8B4513 | |
Sienna | #A0522D | |
Peru | #CD853F | |
Burlywood | #DEB887 | |
Beige | #F5F5DC | |
Wheat | #F5DEB3 | |
Sandy Brown | #F4A460 | |
Tan | #D2B48C | |
Chocolate | #D2691E | |
Firebrick | #B22222 | |
Brown | #A52A2A | |
Dark Salmon | #E9967A | |
Salmon | #FA8072 | |
Light Salmon | #FFA07A | |
Orange | #FFA500 | |
Dark Orange | #FF8C00 | |
Coral | #FF7F50 | |
Light Coral | #F08080 | |
Tomato | #FF6347 | |
Orange Red | #FF4500 | |
Red | #FF0000 | |
Hot Pink | #FF69B4 | |
Deep Pink | #FF1493 | |
Pink | #FFC0CB | |
Light Pink | #FFB6C1 | |
Pale Violet Red | #DB7093 | |
Maroon | #B03060 | |
Medium Violet Red | #C71585 | |
Violet Red | #D02090 | |
Magenta | #FF00FF | |
Violet | #EE82EE | |
Plum | #DDA0DD | |
Orchid | #DA70D6 | |
Medium Orchid | #BA55D3 | |
Dark Orchid | #9932CC | |
Dark Violet | #9400D3 | |
Blue Violet | #8A2BE2 | |
Purple | #A020F0 | |
Medium Purple | #9370DB | |
Thistle | #D8BFD8 | |
Dark Blue | #00008B | |
Dark Cyan | #008B8B | |
Dark Magenta | #8B008B | |
Dark Red | #8B0000 |
Paleta segura:
|
|
|
|
|
|
El particular estamento While Select de Axapta
X++ usa el estamento Select para obtener registros desde la base de datos.
El estamento Select se escribe desde código como cualquier otro estamento X++. Antes de usar un estamento select debemos declarar primero las variables para las tablas de la base de datos a las cuales hará referencia.
En X++ una variante del estamento while, while select, nos permite crear una iteración que nos vaya obteniendo todos los registros que cumplan un determinado criterio. El criterio de selección se define usando expresiones basadas en operadores y variables.
Hay que tener en cuenta que el tipo base str no puede usarse en las expresiones dado que su longitud es indefinida. Para los strings debemos usar los tipos de datos extendidos.
static void SelectStament(Args _args) { CustTable custTable; CustTrans custTrans; TransDate fromYear = SystemDateGet(); ; while select custTable join custTrans where custTrans.accountNum == CustTable.accountNum && custTrans.transDate >= fromYear { info(strfrm("%1 %2", custTable.accountNum, custTrans.transDate); } }
Vemos en el ejemplo como usar el estamento select en X++. Las tablas CustTable y TransTable están relacionadas, los registros de CustTrans que tengan una fecha de transacción mayor o igual a la fecha del sistema que obtenemos con la llamada a la función SystemDateGet() serán devueltos.
Destacamos que se declara la variable que contendrá el valor que nos devuelve SystemDateGet(). Con ello conseguimos no utilizar directamente SystemDateGet() en el select, lo cual relentizaría el proceso pues la llamada a SytemDateGet() se ejecutaría en cada iteración.
El estamento select de X++ no es precisamente lo mismo que el estamento select del SQL Standard. Además X++ no implementa todas las palabras claves del SQL Standard. Si estamos acostumbrados a escribir estamentos SQL, debemos de familiarizarnos con el estamento select de X++.
En próximas entradas iremos publicando todas las palabras claves disponibles en X++ para el estamento select.
¡Hola Mundo!
Como no podía ser de otra forma os saludamos con el típico Job con el que los programadores ejecutamos cuando nos enfrentamos a un nuevo entorno.
static void HolaMundo(Args _args)
{
;
Box::info("¡Hola Mundo!", "Bienvenidos a AxaptaMente");
}
Si lo ejecutamos obtendremos la típica ventana de bienvenida: