FoxPress – Septiembre 2003

 

Usando DinamiCube en Visual FoxPro

http://www.fpress.com/

 

          Por Luis Guerra             DC_Demo.zip

 

 

El presente artículo está escrito con la intención de dar a los desarrolladores de Visual FoxPro una introducción e ideas para agregar a las aplicaciones que desarrollan capacidades de Consultas Dinámicas muy parecidas a las tablas pívot de Excel o a los cubos que se crean con los Servicios de Análisis de SQL Server 2000 o similares, también llamados Cubos.

 

Para lograr este objetivo he usado el DynamiCube, que es un control ActiveX. El control DynamiCube es un control que permite obtener y mostrar enormes cantidades de datos almacenados en bases de datos relacionales en una forma resumida y tabulada que ayuda al usuario final a realizar decisiones precisas. Los datos numéricos pueden ser obtenidos de múltiples Fuentes, tabulados, resumidos y presentados al usuario en un cubo multidimensional. El usuario final puede manipular la vista, mover dimensiones y cambiar el orden para responder mejor a sus necesidades de análisis. DynamiCube es n-dimensional y está limitado solamente por los recursos disponibles del entorno de la PC donde se ejecuta. Cada dimensión consiste de un número finito de puntos de datos. Estos puntos de datos son usados para localizar un elemento de datos individual.

 

Para poder simplificar algunas explicaciones, en algunos casos me voy a referir al control DynamiCube simplemente como cubo. En principio se va a crear un formulario y se le va pegar el control DynamiCube al mismo. El control aparece en la lista de controles como la clase DCube Class. Tal como se ve en la figura siguiente:

 

 

Una vez seleccionado el control, hacemos clic en Ok y se mostrará el control como un rectángulo con fondo blanco al cual le pondremos ‘oleCube’ en la propiedad Name, tal como se puede observar en la siguiente figura:

 

 

El control DynamiCube soporta varias tecnologías para acceder a datos. Para ver cuales son las tecnologías y cual deseamos usar hacemos clic secundario sobre el control y seleccionamos ‘DCube Class Properties’, como observamos en la siguiente figura:

 

 

Después de lo cual se mostrará una ventana con varias páginas en la primera de las cuales se mostrará un combobox correspondiente al tipo de conexión (Connection Type) con una lista de tecnologías que se pueden usar para acceder a datos.

 

 

Como se ve, se pueden usar varias tecnologías entre las que destacan ODBC, ADO (OLE DB) y DAO, además del modo Unbound que permite llenar los datos del cubo en tiempo de ejecución. El modo Unbound tiene la ventaja de que se puede llenar el cubo desde cualquier fuente de datos de que dispongamos en tiempo de ejecución, pueden ser cursores, vistas, tablas, variables de memoria, arreglos, etc. La desventaja es que no se puede diseñar el DynamiCube en tiempo de desarrollo, lo que sí se puede hacer con las otras tecnologías de acceso a datos tales como el ODBC que permite crear una instrucción SELECT en tiempo de desarrollo lo que es usado para diseñar el cubo, esto se hace en la página Layout de la misma ventana de propiedades del DynamiCube y que facilita enormemente el diseño del mismo. Vamos a dar un vistazo rápido de cómo se diseñaría el DynamiCube con una conexión ODBC a una base de datos SQL Server 2000 y cómo se vería:

 

Primero se define el tipo de conexión, luego la cadena de conexión así como la instrucción SELECT-SQL que obtendrá los datos:

 

 

Luego está la página Time Series que permite definir algunos tipos de datos relacionados a fechas que podrían usarse como datos del cubo tales como año, trimestre, mes y semana. En este caso no se va a usar ninguno de esos campos, pero se muestra por cuestiones didácticas:

 

 

Luego, se definen los campos que se van a mostrar y su posición dentro del cubo, para esto se va a la página Layout y se pulsa el botón Retrieve Fields para que en la lista aparezcan todos los campos que el SELECT hace disponible, de los cuales se van a usar algunos, esto se hace arrastrando el campo desde la lista hasta la posición deseada:

 

 

En la página Fields, se pueden cambiar los títulos o encabezados que van a tener los campos en tiempo de ejecución:

 

 

En la página Preferences, se puede cambiar el aspecto que va a tener el cubo, para lo cual hay varios comboboxes y checkboxes que corresponden a diferentes partes del mismo y que sirven para darle un estilo personalizado ante el usuario final, aunque desde mi punto de vista los valores predeterminados son buenos.

 

 

 

En la página Printer, se va a especificar el encabezado, pie de página, márgenes y justificación cuando se imprima o se haga una vista preliminar de la impresión, así como si se desea que se repitan en cada página los encabezados:

 

 

 

En la página Color, se pueden especificar los colores que van a tener diferentes partes del DynamiCube, tales como colores de fondo y de letras de los encabezados así como de los datos:

 

 

 

Y por último en la página Fonts, se podrá especificar los tipos de letras para cada parte del cubo:

 

 

 

Luego hacemos clic en el botón Ok y ejecutamos el formulario, el cubo se verá más o menos de la siguiente forma:

 

 

El usuario final puede mover los campos de un sitio a otro, es decir, hacer que los campos estén como columnas, filas y/o páginas (área superior del DynamiCube, también se le llama área de filtro, más adelante veremos por qué), los campos de datos (las cantidades) no se pueden mover. De esa forma el usuario puede construir varios reportes de acuerdo a cómo haya distribuido los campos, por ejemplo, puede arrastrar el campo Mes hasta el área de los campos fila, pero al costado derecho del campo Cuenta, con lo cual el cubo se vería así:

 

 

Además si se desea podemos cambiar el campo al área de campos de columna, con lo cual, el cubo quedaría así:

 

 

Pero eso no es todo, se pueden filtrar los datos como sea necesario, por ejemplo podemos abrir el campo Año como un dropdown y se mostrarán los datos correspondientes, se mostrarán, en este caso, los años 2002 y 2003:

 

 

 

Si deseamos ver solamente los datos del año 2002, quitamos el check del año 2003 y luego hacemos clic en cualquier parte del cubo para que se cierre el dropdown y mostrar sólo los datos del año 2002:

 

 

Similarmente, sí sólo deseamos ver los datos del primer semestre del año 2002, basta con abrir el dropdown del campo Mes y quitar el check de los meses correspondientes al segundo semestre:

 

 

El cubo se mostrará así:

 

 

Como se ha visto, se puede diseñar cómo uno desea ver el cubo, en tiempo de desarrollo, todo desde la ventana de propiedades del DynamiCube. Para cada opción hay una propiedad disponible que también se puede acceder mediante programación, aunque sería más complicado hacerlo así. Los resultados son muy buenos, por no decir excelentes.

 

Ahora volviendo al tema central de este artículo, nos concentraremos en el uso del DynamiCube en modo Unbound para poder acceder a los datos desde una consulta de tablas VFP o desde un cursor VFP y realizar una rutina para llenar los datos del cubo.

 

Lo primero que se debe hacer es poner la propiedad AutoYield del objeto _VFP en falso para que el Dynamicube funcione bien, (esto sólo es necesario en el modo Unbound). Esto lo podemos hacer en el evento INIT del Dynamicube:

 

_Vfp.AutoYield= .F.

 

Luego debemos poner la propiedad DCConnectType en modo Unbound y la propiedad AutoDataRefresh en falso, lo último es para evitar que el DynamiCube intente cargar datos cuando se crea el control y se muestre un mensaje de advertencia cuando se ejecuta el formulario, esto es debido a que aún no se han creado los campos. Esto se puede hacer desde la ventana de propiedades de Visual FoxPro o mediante código en el evento Init del control oleCube:

 

This.DCConnectType= 99   && Modo Unbound.

This.AutoDataRefresh= .F.   && Evite que se muestre el mensaje de advertencia.

 

También, si deseamos tener los encabezados con letras azules y fondo verde claro, lo hacemos desde la ventana de propiedades del DynamiCube:

 

 

Los cuales equivalen a las propiedades FieldsForecolor y FieldsBackColor, lo que también se puede hacer mediante programación, naturalmente que en esta última forma se pueden especificar muchos más colores que los disponibles en la ventana de propiedades, pero lo que se debe saber es el valor numérico equivalente al color deseado.

 

En este ejemplo vamos a usar la tabla DATOS.DBF, ya creada, la cual vamos a agregarla al entorno de datos del formulario. No es necesario que sea una tabla, en aplicaciones reales, sería un cursor generado desde un SELECT-SQL y que tenga datos no-normalizados, similares a los necesarios para un reporte. La tabla que vamos a usar tiene los siguientes datos:

 

 

Luego se va a armar la distribución de los campos, con sus encabezados, en el evento Init del formulario de la siguiente forma:

 

 

** Crear los campos del DynamiCube.

With This.oleCube.Fields

  .DeleteAll()   && Borra todos los campos (si existe alguno).

  .Add( "division", "División", 2)   && División como fila.

  .Add( "region", "Región", 1)      && Región como columna.

  .Add( "ganancia", "Ganancia", 3)  && Ganancia como datos.

EndWith

 

 

Una vez que se han definido los campos, lo único que queda por hacer para completar la configuración, o mejor dicho, la construcción del cubo, es llenar con los datos de la tabla que se acaba de mencionar. Esto se realiza a través del evento FetchData del DynamiCube, este evento sólo se dispara en modo Unbound y cuando se ejecuta el método RefreshData():

 

Local lnCampos, laDatos( 1)

 

lnCampos= 3   && Número de campos en DynamiCube.

Dimension laDatos( lnCampos)

Select Datos

Scan

  ** Llena los valores de los campos en el arreglo ‘laDatos’.

  laDatos( 1)= Datos.division

  laDatos( 2)= Datos.region

  laDatos( 3)= Datos.ganancia

 

  ** Agrega los datos al DynamiCube.

  This.AddRowEx( @laDatos)

EndScan

 

Los valores que contiene el arreglo laDatos deben estar en el mismo orden en que se crearon los campos, de lo contrario, se pueden obtener resultados extraños. Se usa el método AddRowEx() para agregar al DynamiCube los datos que se encuentran en el arreglo.

 

Ahora lo último que falta para poder mostrar los datos es usar el método RefreshData(), el cual, al ser llamado, ejecutará el código que se encuentra en el evento FetchData(). En nuestro ejemplo se ha usado un botón que llama al método RefreshData() para mostrar el DynamiCube:

 

 

This.Parent.oleCube.RefreshData()

 

 

El formulario queda así:

 

 

Se pueden mover los campos de tal manera que el DynamiCube quede así:

 

 

O así:

 

 

Para tener una vista preliminar de cómo se imprimiría el cubo se usa el método PrintPreview(), al formulario del ejemplo se le ha agregado un botón ‘Vista preliminar’ el cual llama a dicho método de la siguiente manera:

 

 

This.Parent.oleCube.PrintPreview()

 

 

Lo cual mostrará una ventana como la siguiente:

 

 

En la parte superior de la ventana hay botones desde los cuales se puede Imprimir, configurar la impresora y el tamaño de página, cambiar el ancho y alto de las celdas, avanzar de página si es necesario y por último hacer un Zoom de la vista preliminar.

 

Si se desea imprimir el cubo sin hacer una vista previa se usa el método Print() el cual necesita tres parámetros: el primero si es .T. (verdadero), indica que se desea mostrar una ventana de diálogo de impresión que permite cambiar la impresora predeterminada, si es .F. (falso) no se muestra el diálogo y comienza a imprimir directamente. Los dos restantes parámetros también son obligatorios e indican el primera y última página que se van a imprimir, si se pone -1 en el tercer parámetro, indica que se desea imprimir todas las páginas, estos parámetros son obviados si el primer parámetro es .T. (verdadero). Para llamar al método Print() en el botón, se haría de la siguiente forma:

 

 

This.Parent.oleCube( .F., 1, -1)

 

 

Lo cual comenzaría inmediatamente a imprimir en la impresora predeterminada en ese momento.

 

Para terminar, quiero decir que el DynamiCube puede ser expandido para incluir más dimensiones y más información de resumen. Provee información de soporte de decisión en un formato flexible que los usuarios finales pueden manipular y modificar de acuerdo a sus necesidades de análisis.

 

Otra de las ventajas es que no se necesita de un servidor OLAP o similar para tener la misma funcionalidad y lo bueno es que solo es cuestión de pegar el control en un formulario y programarlo, tarea que se puede simplificar enormemente si se crea una clase que ya tenga toda la funcionalidad descrita, lo cual solo haga necesario indicar los campos, encabezados, distribución y nada más, la clase se encargaría de todo. Por ejemplo, yo he creado una clase que uso en las aplicaciones que desarrollo que permite mostrar el cubo, tener una vista preliminar, imprimirlo y hasta exportarlo a una hoja Excel. Todo eso es posible debido a que el modelo de objetos es completo y da un gran control sobre cada aspecto del cubo.

La versión actual del DynamiCube es la 2.5.1.2. y hay una nueva versión que es llamada ActiveCube 3 la cual es también una gran herramienta e incluso soporta exportación a Excel en forma nativa, la principal desventaja, si se le puede llamar así, es que solamente soporta conectarse con servicios OLAP y aunque tiene un modo Unbound, de lo que he investigado, no se puede hacer lo mismo que con el DynamiCube. Para los interesados, pueden descargar la versión de evaluación desde http://www.datadynamics.com, lo bueno es que las versiones de evaluación son completamente funcionales pero sólo duran 30 días. Sin embargo, vale la pena investigar más a fondo este control que es muy versátil.


FoxPress – Septiembre de 2003