Pattern: CrossTable entre 2 dimensiones

Se me ha presentado en varias oportunidades, que en aplicaciones GeneXus WEB necesito tener una tabla de cruces de datos. Esta es una tabla donde se muestre una dimension en las columnas y otra dimension en las filas, poniendo algun indicador (suma o cuenta) en las celdas internas de la tabla.

Ejemplo:

Factura
*NroFactura
Cliente
Producto
Importe

y generar una tabla del tipo

..

Cliente1

Cliente2

Cliente3

Cliente4

Cliente5

Total

Producto1



3000



3000

Producto2

200


100

45


345

Producto3





1

1

Total

200


3100

45

1

3346


Esto es relativamente facil de implementar con el codigo: (el ejemplo va sin TOTALES).

Hay que programar un Webpanel, que unicamente tenga un FreeStyle subfile, con una variable &Texto=C(100). Las columnas se setean en runtime.

Event Load
&Columnas=0
for each Cliente
&Columnas +=1
endfor
Grilla.Columns = &Columnas + 1

//Cargo primer casillero
&Texto='..'
Load

//Cargo Titulos superiores
for each Cliente
// where Condicion de clientes
&Texto=ClienteNombre
&Texto.FontBold=1
Load
endfor

for each Producto
//Cargo Titulo de la fila
&Producto=Producto
&Texto=ProductoDsc
&Texto.FontBold=1
&Texto.Link=link('')
Load
for each Cliente
&Cliente=Cliente
//Cargo la celda con Cliente y Producto Instanciado.
do 'Acumulo'
&Texto.FontBold=0
Load
endfor
endfor

EndEvent // Start

Sub 'Acumulo'
&Importe=0
for each
Where Cliente=&Cliente
Where Producto=&Producto
&Importe += Importe
endfor

If Not &Importe.IsEmpty()
&Texto=str(&Importe)
&Texto.Link=Link(hListoFacturas,&Cliente,&Producto)
else
&Texto.SetEmpty()
&Texto.Link=link('')
endif
EndSub


Estaría bueno implementarlo para la ROCHA (es fácil y de ingenio), aunque aun no hay demasiada documentación sobre como hacerlos.

PD: Ojo que no es aplicable a todos los casos, pues si la matriz generada es muy dispersa o si tenes alguna dimension que sea de una cardinalidad muy grande, puede consumir muchisimos recursos hacerlo.
Queda como ejercicio interesante, hacer un DataProvider que realice la consulta (agrupando por las dimensiones y haciendo la suma/cuenta) y despues procesar el SDT.
El dataprovider deberia hacer
"SELECT DIMENSION1, DIMENSION2,SUM(INDICADOR) FROM TABLA GROUP BY
DIMENSION1, DIMENSION2"

También puede tener problemas de performance si la cardinalidad de la tabla de facturas es muy grande. Hay que usarlo con cariño.

Comentarios

  1. Hola,! tiempo atrás un colega me pasó el link, y probé el tips del CrossTable... espectacular!
    A modo de ejemplo, en un cuadro tenemos 10 filas en la Dimensión 1 y 100 en la Dim.2, La tabla cross es de 100.000 reg... en unos 15 seg. despliega el cuadro resultante... luego hicimos unos cambios a nivel diseño de BD para mejorar los tiempos..
    Es un chichecito..., una solución simple y elegante.
    Edgardo

    ResponderEliminar

Publicar un comentario

1) Lee el post
2) Poné tu opinión sobre el mismo.
Todos los comentarios serán leidos y la mayoría son publicados.

Entradas más populares de este blog

El Sordo

StackOverflow Documentation

Codigo simple