[AX 2012 R3 – How To] Compilación CIL Completa

Esta tarea tiene estrecha relación con el .NET Framework, donde la idea central es compilar el código de Dynamics AX a CIL (Common Intermediate Language) que el .NET Framework pueda utilizar.
Generalmente es necesaria la compilación CIL para los siguientes escenarios:

  • Servicios AIF.
  • Trabajos por lotes.
  • Funciones .NET que reemplazan a funciones del X++.

Debemos tener en cuenta dos escenarios para la compilación CIL:

  • Incremental: Compila únicamente los cambios realizados en una determinada función o tarea.
  • Full: Convierte el código X++ a código CIL que el CLR del .NET Framework lo puede entender.

Para realizar una compilación incrementar debemos seguir la siguiente ruta: Nos posicionamos en el objeto (dentro del Entorno de Desarrollo) que queremos aplicar el CIL Incremental y… Generar > Generar CIL de incremento (Ctrl + Shift + F7).

Para realizar una compilación Full debemos seguir la siguiente ruta: Generar > Generar CIL Completo.
Estas operaciones pueden tomar mucho tiempo dependiendo de la cantidad de objetos que tengamos. Normalmente hablamos de 20 minutos. Esperamos los resultados y listo.

[AX 2012 R3 – How To] Error TTS (Transaction Tracking)

Este tipo de errores nos aparecen cuando intentamos insertar, modificar o eliminar datos de una tabla.
Pues involucra a las transacciones realizadas en ellas.

El error (en inglés, para este caso) se puede visualizar de la siguiente manera: 1

Cuando el TTSLevel es superior a 0 (cero) indica que la base de datos se encuentra en un estado erróneo. Específicamente, el AX queda en un estado inestable o simplemente se «cuelga» o «bloquea» nuestro cliente AX. Para solucionar el problema, simplemente debemos abortar todas las transacciones cuyo estado sea superior a 0. Lo podemos hacer creando un Job simple y ejecutándolo.

El infolog mostraría la transacción que ha quedado abierta o con errores.

static void resetTTS(Args _args)
{
while (appl.ttsLevel() > 0)
{
info(strfmt("Nivel %1 abortado",appl.ttsLevel()));
ttsAbort;
}
}

Artículo basado en la publicación de Deepak Agarwalaquí.

[AX 2012 R3 – How To] Consumir servicios Web externos

En esta ocasión, voy a demostrar cómo consumir un servicio web desde AX. El artículo que se encuentra en el MSDN es muy bueno para empezar, pero no esa API de Bing ya no está disponible.

Básicamente, vamos a verificar si nuestro JSON es válido y el resultado lo mostraremos en el infolog del AX.

Prerrequisitos

Para completar este tutorial se necesita:

  1. Microsoft Visual Studio 2010+.
  2. Visual Studio Tools for Dynamics AX 2012.
  3. Librería JSON.NET.

Librería DLL en .NET

Ahora, utilizando las herramientas de Visual Studio para Dynamics AX 2012 crearemos un proyecto de tipo «Librería de Clase en C#» y allí escribiremos el código necesario:


using Newtonsoft.Json;
using System.Net;

namespace TestJSON
{
public class Prueba
{
public string getData()
{
var url = "http://validate.jsontest.com/?json=%7B%22key%22:%22value%22%7D";

var client = new WebClient();
string jsonData = client.DownloadString(url);

var records = JsonConvert.DeserializeObject(jsonData);


return records.ToString();
}
}
}

Ahora, iremos a la carpeta donde están las dll generadas, las vamos a copiar en el Servidor y Cliente de AX Para el servidor la ruta se parece a:
C:Program FilesMicrosoft Dynamics AX60ServerMicrosoftDynamicsAXbin

Para el cliente la ruta se parece a:
C:Program Files (x86)Microsoft Dynamics AX60ClientBin

En el AX vamos a agregar la referencia a dichas dlls:
1

Por último, vamos a crear un Job donde llamaremos a la librería y ejecutaremos el siguiente código:


static void Job16(Args _args)
{
TestJSON.Prueba pr;
str resultado;
;

pr = new TestJSON.Prueba();
resultado pr.getData();

info(resultado);
}

De esta manera se consume un servicio web, en este caso, en formato JSON.

[AX 2012 R3 – How To] Consumir servicios Web externos

En esta ocasión, voy a demostrar cómo consumir un servicio web desde AX. El artículo que se encuentra en el MSDN es muy bueno para empezar, pero no esa API de Bing ya no está disponible.

Básicamente, vamos a verificar si nuestro JSON es válido y el resultado lo mostraremos en el infolog del AX.

Prerrequisitos

Para completar este tutorial se necesita:

  1. Microsoft Visual Studio 2010+.
  2. Visual Studio Tools for Dynamics AX 2012.
  3. Librería JSON.NET.

Seguir leyendo «[AX 2012 R3 – How To] Consumir servicios Web externos»

[AX 2012 R3 – How To] Aplicar formato a archivo Excel

Este artículo tiene estrecha relación con el anterior. En el artículo anterior veíamos cómo exportar datos a Excel desde el Dynamics AX. En este caso aplicaremos el formato a la cabecera de la hoja y a las celdas.

Aquí quiero mostrar dos cosas: la primera, consiste en aplicar estilos y la segunda, aplicar formato de texto o numéricos a las celdas.
Seguir leyendo «[AX 2012 R3 – How To] Aplicar formato a archivo Excel»

[AX 2012 R3 – How To] Aplicar formato a archivo Excel

Este artículo tiene estrecha relación con el anterior. En el artículo anterior veíamos cómo exportar datos a Excel desde el Dynamics AX. En este caso aplicaremos el formato a la cabecera de la hoja y a las celdas.

Aquí quiero mostrar dos cosas: la primera, consiste en aplicar estilos y la segunda, aplicar formato de texto o numéricos a las celdas.

Estilos

En este caso, vamos a colorear el fondo de las celdas en la cabecera, para ello creamos un método y asignamos el color celda por celda. Este método debe ser llamado desde el método principal export2Excel():


SysExcelWorkSheet formatExcelHeader(SysExcelWorkBook _xlsWorkBook)
{
SysExcelWorkSheet xlsWorkSheet;
SysExcelStyles styles;
SysExcelStyle style;
SysExcelFont font;
SysExcelInterior interior;
SysExcelCells cells;
int indiceColumnas = 1;
;

//Obtenemos los estilos del libro
styles = _xlsWorkBook.styles();

//Creamos un estilo para la cabecera
style = styles.add("Cabecera");

//Aplicamos fuentes
font = style.font();
//Fuente del título en Negritas
font.bold(true);
//Color a partir de RGB. Negro
font.color(WinApi::RGB2int(0,0,0));

//Aplicamos fondo. Amarillo claro
interior = style.interior();
interior.color(WinApi::RGB2int(246,255,159));

//Aplicamos el estilo de Cabecera a la primera fila del archivo.
xlsWorkSheet = _xlsWorkBook.worksheets().itemFromNum(1);

cells = xlsWorkSheet.cells();
//Alineación izquierda para textos, derecha para números
cells.range("A1").horizontalAlignment(-4152); //Derecha
cells.range("B1").horizontalAlignment(-4131); //Izquierda
cells.range("C1:D1").horizontalAlignment(-4152); //Derecha

xlsWorkSheet.rows().item(1).style("Cabecera");

return xlsWorkSheet;
}

Formato

En este caso, vamos a alinear las celdas a la derecha y/o izquierda y colocaremos formato numérico o sólo texto (esto va en el método que carga los datos fila por fila):


//Alineación izquierda para textos, derecha para números
_cells.range(strFmt("A%1",row)).horizontalAlignment(-4152); //Derecha
_cells.range(strFmt("A%1",row)).numberFormat("0"); //Números enteros
_cells.range(strFmt("B%1", row)).horizontalAlignment(-4131); //Izquierda
_cells.range(strFmt("B%1",row)).numberFormat("@"); //Sólo texto
_cells.range(strFmt("C%1:D%1",row)).horizontalAlignment(-4152); //Derecha
_cells.range(strFmt("C%1:D%1",row)).numberFormat("0,00"); //Números con dos decimales

[AX 2012 R3 – How To] Exportar una tabla a Excel

Exportar una tabla a excel es muy simple, desde cualquier formulario en Dynamics AX. Simplemente se debe hacer clic en el ícono con el logo de Microsoft Excel en la barra de herramientas.

Pero ¿Qué ocurre cuando debemos exportar datos modificados o filtrados?

Es ahí donde este tutorial puede ser de ayuda para los desarrolladores de Dynamics AX.
Seguir leyendo «[AX 2012 R3 – How To] Exportar una tabla a Excel»

[AX 2012 R3 – How To] Exportar una tabla a Excel

Exportar una tabla a excel es muy simple, desde cualquier formulario en Dynamics AX. Simplemente se debe hacer clic en el ícono con el logo de Microsoft Excel en la barra de herramientas.

Pero ¿Qué ocurre cuando debemos exportar datos modificados o filtrados?

Es ahí donde este tutorial puede ser de ayuda para los desarrolladores de Dynamics AX.

En un método crearemos el libro y llamaremos a los métodos que cargan la cabecera y los datos. Primeramente definimos la exportación al Excel:


void export2Excel()
{
SysExcelApplication xlsApplication;
SysExcelWorkBooks xlsWorkBookCollection;
SysExcelWorkBook xlsWorkBook;
SysExcelWorkSheets xlsWorkSheetCollection;
SysExcelWorkSheet xlsWorkSheet;
SysExcelWorksheet xlsWorkSheetToBeDeleted;
SysExcelRange xlsRange;
SysExcelCells cells;
SysExcelCell cell;

str fileName;
;

//Cargar datos temporales
//tmpTable = element.loadTmpTable();

//Nombre de archivo
fileName = FilePathControl.text();

//Iniciamos la instancia de Excel
xlsApplication = SysExcelApplication::construct();

//Creamos el Libro y Hoja de Excel
xlsWorkBookCollection = xlsApplication.workbooks();
xlsWorkBook = xlsWorkBookCollection.add();
xlsWorkSheetCollection = xlsWorkBook.worksheets();
xlsWorkSheet = xlsWorkSheetCollection.itemFromNum(1);

//Celdas corespondientes a la Cabecera
cells = element.fillExcelHeader(xlsWorkSheet.cells());

//Cargar celdas de datos
cells = element.fillExcelData(xlsWorkSheet.cells());

//Eliminar hojas que no se utilizarán
while(xlsWorkSheetCollection.count() > 1)
{
xlsWorkSheetToBeDeleted = xlsWorkSheetCollection.itemFromNum(2);
xlsWorkSheetToBeDeleted.delete();
}

//Ajustar columnas
xlsWorkSheet.columns().autoFit();

//Verificar si el archivo ya existe, para eliminarlo
if(WinApi::fileExists(fileName))
WinApi::deleteFile(fileName);

//Guardar documento Excel
xlsWorkbook.saveAs(fileName);

//Abrir documento Excel
xlsApplication.visible(true);
}

Ahora, procedemos a cargar la cabecera (generalmente corresponde al texto de la columna):


SysExcelCells fillExcelHeader(SysExcelCells _cells)
{
//Reemplazamos la X por el índice(empieza en 1) de columna
_cells.item(1,X).value(fieldPName(TABLA, COLUMNA));
return _cells;
}

Y por último accedemos a los datos para cargar el Excel:


SysExcelCells fillExcelData(SysExcelCells _cells)
{
#AviFiles
real calculatedProportion;
int indiceProgress = 0;
int row = 1; //row = 1 corresponde a la cabecera

int tickCount;
Array rowArr;
COMVariant comArr;
COM comRange;
;

select Count(RecId) from TABLA;

cantidadRegistros = TABLA.RecId;

progress.setCaption("Cargando datos...");
progress.setAnimation(AviTransfer);
progress.setTotal(cantidadRegistros);

//Obtener los datos necesario para cargar los datos.
while select * from TABLA
{
try
{
//Manejar el indicador de Progreso
indiceProgress++;
progress.setText(strfmt("Registro %1 de %2", indiceProgress, int642str(cantidadRegistros)));
progress.setCount(indiceProgress, 1);

//Filas
tickCount = WinAPI::getTickCount();
row++;

// Crear un array para completar la fila completa
rowArr = new Array(Types::String);

// Cargar cada celda
rowArr.value(1, TABLA.COLUMNA);

// Almacenar el Array
comArr = new COMVariant();
comArr.safeArray(rowArr, COMVariantType::VT_BSTR);

//Establecer el rango de columnas, reemplazar X por la letra de columna que corresponde al Excel
comRange = _cells.range(strFmt("A%1:X%1", row)).comObject();

//Agregar fila al rango
comRange.value2(comArr);
}
catch
{

}
}

indiceProgress = 0;
//Cerramos el indicador de progreso
progress.kill();

return _cells;
}

[AX 2012 R3 – How To] Depurar un Reporte

Depurar un reporte que fue asignado con un Data Provider, resulta un poco complicado a primera vista. El principal problema radica en que los reportes suelen almacenarse en tablas temporales o en memoria haciendo que no se pueda depurar.

Pero lo podemos lograr haciendo un pequeño cambio en las propiedades de la tabla temporal y un cambio en la clase que corresponde al Data Provider.
Seguir leyendo «[AX 2012 R3 – How To] Depurar un Reporte»