Depurar Report (SSRS) Dynamics AX con Visual Studio 2008

1 Estrella2 Estrella3 Estrella4 Estrella5 Estrella (Sin calificar)
Cargando…
Escrito por René Roca el . Posteado en X++

En Dynamics AX  los informes de Reporting Services, permiten insertar una Lógica de Negocios. Esta lógica del negocio puede ser llamadas a código X + +  del AOT o a código C # directamente en el informe de SSRS.

En el caso que nos interese poder depurar el código C # cuando sea necesario. Podemos utilizar el depurador de Visual Studio 2008 integrado sin embargo es necesario seguir ciertos pasos:

Necesitamos una máquina, donde estén instalados los siguientes componentes:

  • Microsoft Dynamics AX 2009 Cliente
  • Microsoft Dynamics AX 2009 Reporting Tools
  • Microsoft SQL Server 2005 o 2008 Reporting Services
  • Microsoft Dynamics AX 2009 Extensiones de informes
  • Microsoft Visual Studio 2008

Nota:
En el ejemplo que proponemos, utilizaremos un informe que se base en Microsoft SQL Server Analysis Services (SSAS), para extraer losdatos. Por lo tanto, necesitamos tener los cubos defecto por defecto de Dynamics AX

A continuación detallamos los pasos que tenemos que seguir para depurar el siguiente informe Cust.CashInflowvsCashOutflow:

Nota: Es importante para implementar la solución en Visual Studio, incluso si los informes de SSRS ya se habían implementado y nohan sido modificados!)

  1. Inicie el cliente de Dynamics AX, abra la ventana de AOT e ir al AOT \ bibliotecas de informes
  2. Haga clic con el botón derecho del ratón en la biblioteca informe de Clientes (CUST) y seleccione Editar en Visual Studio en el menú contextual
  3. Espere hasta que el IDE de Visual Studio arranque totalmente.
  4. Asegúrese de que la configuración activa de la solución está en depuración (para comprobar la configuración de Activa, vamosr a Build – Configuration Manager…)
  5. Volvemos a generar la solución completa mediante la selección Build – Build Solution
  6. Implementar la solución de Microsoft SQL Server Reporting Services, seleccionamos Build – Deploy Solution

Nota: Es importante implementar la solución en Visual Studio, incluso si los informes de SSRS ya se habían implementado y no han sido modificados!)

  • Abrimos el informe CashInflowvsCashOutflow desde la ventana del Explorador de soluciones de Visual Studio
  • En la ventana del Explorador de Informe desplegamos los métodos del nodo de datos y hacemos doble click en GetDefaultCompany
  • Colocamos un punto de interrupción en cualquier línea de código
  • Iniciamos Internet Explorer y vamos a la pagina del Administrador de informes de Reporting Services
  • Hacemos clic en la carpeta Dynamics
  • Volvemos a Visual Studio y seleccionamos Tools – Attach to Process desde el menú
  • Nos aseguraremos que las opciones how processes from all users y Show processes in all sessions están activadas
  • El siguiente paso es diferente según la versión de Microsoft SQL Server Reporting Services:
    • Si estamos utilizando Microsoft SQL Server 2008 Reporting Services:
      En la lista de los procesos seleccionaremos reportingservicesservice.exe
    • Si estamos utilizando Microsoft SQL Server 2005 Reporting Services:
      En la lista de procesos seleccionaremos w3wp.exe
  • Volvemos a la página del Administrador de informes de Reporting Services, en el navegador Web y ejecutamos el informe Cust.CashInflowvsCashOutflow.FullPage
  • Acto seguido, veremos como el proceso se detiene en el punto de interrupción que hemos puesto en Visual Studio.

 

Nota:
En Windows Vista y Windows Server 2008 no tenemos que asegurar que ejecutamos Visual Studio con privilegios de Administrador

Agregar funcionalidad Ir a la tabla principal

1 Estrella2 Estrella3 Estrella4 Estrella5 Estrella (Sin calificar)
Cargando…
Escrito por René Roca el . Posteado en X++

En Axapta, existe la funcionalidad Ir a la tabla principal, cuando nos situamos encima de un registro el cual es el código de otra tabla, como por ejemplo el campo código de cliente, este registro nos identifica en la tabla de Clientes, a un cliente.

En ocasiones, la funcionalidad de ir a la tabla principal no está activa si por ejemplo estamos usando un campo que no está vinculado con una tabla, como podría ser al crear un desplegable de filtro en un formulario, que nos muestre los códigos de cliente.

Si queremos habilitar la funcionalidad de Ir a la tabla principal en estos casos, tendremos que sobre escribir el método JumpRef() del desplegable o campo que estemos utilizando.

A continuación os pongo un ejemplo de cómo quedaría el método modificado para acceder a la tabla de clientes:

public void jumpRef()
{
	EmplTable 		emplTable;
	Args 			args;
	MenuFunction 	menuFunction;
	;
 
	emplTable = EmplTable::find(this.text());
 
	if (emplTable)
	{
		args = new Args();
		args.caller(element);
		args.record(emplTable);
 
		//Llamamos al formulario de clientes
		menuFunction = new MenuFunction(menuitemdisplaystr(EmplTable), MenuItemType::Display);
		menuFunction.run(args);
	}
}

Acceso Axapta una instancia por usuario

1 Estrella2 Estrella3 Estrella4 Estrella5 Estrella (Sin calificar)
Cargando…
Escrito por René Roca el . Posteado en X++

Si deseamos controlar en acceso por usuario en Dynamics Ax y que un usuario solo tenga abierta una sesión y una licencia, impidiendo que un usuario tenga dos instancias de Dynamics AX abiertas a la vez, podemos realizar la siguiente modificación en la clase Info, método StartupPost

void startupPost()
{
	int 				cuentaSesionActiva = 0;
	UserId 				IdUsuario;
	SysClientSessions 	_SysClientSessions;
	;
	 
	IdUsuario = curuserid(); 	// Capturamos el id del usuario
 
	while select RecId from _SysClientSessions order by login_time desc
		  where _SysClientSessions.userId == curuserid() && _SysClientSessions.Status == 1
	{
		if (_SysClientSessions.RecId)
			cuentaSesionActiva = cuentaSesionActiva + 1; //Acumula el número de logins activos del usuario en el sistema
		else
			cuentaSesionActiva = 0;
	}
	 
	if (cuentaSesionActiva > 1)
	{
		infolog.shutDown(false);
	} 
}

Método para Exportar tabla a Excel

1 Estrella2 Estrella3 Estrella4 Estrella5 Estrella (Sin calificar)
Cargando…
Escrito por René Roca el . Posteado en X++

En algunas ocasiones, nos interesa exportar el contenido de una tabla de Axapta al Excel.

A continuación os dejo un Job, que pasando el TableId, nos exportará y abrirá la información de la tabla de Axapta en Excel, mostrando la cabecera de cada campo y su contenido.

static void DAXExport(TableId tableId)
{
	DictTable dt;
	DictField df;
	Common c;
 
 
	CommaIO cio;
	Container con, conSkip;
 
	int field, counter;
	str line, fieldName;
	str fileName;
	;
 
	StartLengthyOperation();
 
	//Access Table based on TableId
	dt = new DictTable(tableId); //For Table schema
	c = dt.makeRecord();         //To access records
	c.selectForUpdate(false);
 
	//Create temporary file
	fileName = strFmt('%1\\ax_%2.csv', WinAPI::getTempPath(), dt.name());
	cio = new CommaIO(fileName, "W");
 
	if(cio)
	{
		cio.outFieldDelimiter(';');
 
		//Column header
		line = "";
		for(field = 1; field <= dt.fieldCnt(); field++)
		{
			//Skip System Columns
			switch(dt.fieldName(dt.fieldCnt2Id(field)))
			{
				case 'modifiedDateTime':
				case 'dEL_ModifiedTime':
				case 'modifiedBy':
				case 'modifiedTransactionId':
				case 'createdDateTime':
				case 'dEL_CreatedTime':
				case 'createdBy':
				case 'createdTransactionId':
				case 'dataAreaId':
				case 'sequenceNum':
				case 'recVersion':
				case 'unionAllBranchId':
				case 'rowNumber':
				case 'RecId':
				case 'TableId':
				conSkip = conins(conSkip, maxint(), field);
				break;
 
				default:
				con = conins(con,field,dt.fieldName(dt.fieldCnt2Id(field)));
			}
		}
 
		cio.writeExp(con);
		con = conNull();
 
		//Table records
		while select c
		{
			line = "";
			for (field = 1; field <= dt.fieldCnt();field++)
			{
				if(0 == confind(conSkip, field))
				con = conins(con, field, c.(dt.fieldCnt2Id(field)));
			}
 
			cio.writeExp(con);
			con = conNull();
 
			counter++;
		}
	}
 
	EndLengthyOperation();
	info(strfmt("%1 registros de la tabla '%2' exportados", counter, dt.name()));
 
	//Open CSV file in registered app
	WinAPI::shellExecute(fileName);
}

Ejecutar sentencias SQL contra BBDD de forma directa

1 Estrella2 Estrella3 Estrella4 Estrella5 Estrella (Sin calificar)
Cargando…
Escrito por René Roca el . Posteado en X++

En alguna ocasión, aunque no es nada recomendable, necesitamos ejecutar sentencias SQL directamente contra la base de datos desde Axapta sin pasar por el framework que utiliza Dynamics para ello.

Es posible que por ejemplo tengamos que hacer un drop table o algo parecido, para ello, crearemos en la clase Global, el siguiente método:

server static void DAXExecuteSQL(str    _sql)
{
	/* Método para ejecutar directamente sql sobre base de datos - www.dynamicsax.es */
	str                           ddl = '';
	SqlStatementExecutePermission ssep;
	Statement                     statement;
	Connection                    connection;
	;
 
	ddl = _sql;
 
	connection = new Connection();
	connection.ttsbegin();
 
	ssep = new SqlStatementExecutePermission(ddl);
	ssep.assert();
	statement = connection.createStatement(ResultSetType::Dynamic, ResultSetConcurrency::Updatable);
 
	// BP deviation documented
	statement.executeUpdate(ddl);
	connection.ttscommit();
}

Para utilizar el método desde cualquier parte de Axapta, simplemente tendremos que usar la siguiente llamada:

DAXExecuteSQL('Delete custTableTmp');

Esta llamada borrará la tabla CustTableTmp, igual que si lo ejecutáramos desde la consola de SQL Server