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

    ResponderBorrar
  2. Hola Enrique, no se si aun esta abierto a consultas este blog, pero probe el caso que mencionas y funciona bien, cuando tenemos 2 dimensiones.

    El caso que tengo yo es que tengo solo 1 tabla, en la que quiero armar un grid en un WP, pero que cierto dato se utilice para las columnas y el resto a las filas.

    Explico mejor:

    1) tengo esta tabla temporal, que cargo con resultados del consumo de un webservice:

    -CodigoProd (CCAR)
    -Proveedor (A,B,etc)
    -PlanTarifario (1,2,etc)
    -Precio (100,110,etc)

    Codigo proveedor PlanTarifario Precio
    CCAR A 1 100
    CCAR A 2 120
    CCAR A 3 130
    CCAR A 4 140
    CCAR A 5 150
    CCAR B 1 100
    CCAR B 2 120
    CCAR B 3 130
    CCAR B 4 140
    CCAR B 5 150
    CCAR C 1 100
    CCAR C 2 120
    CCAR C 3 130
    CCAR C 4 140
    CCAR C 5 150
    CCAR D 1 100
    CCAR D 2 120
    CCAR D 3 130
    CCAR D 4 140
    CCAR D 5 150
    CMMT A 1 200
    CMMT A 2 210
    CMMT A 3 220
    CMMT A 4 230
    CMMT A 5 240
    CMMT B 1 200
    CMMT B 2 210
    CMMT B 3 220
    CMMT B 4 230
    CMMT B 5 240
    CMMT C 1 200
    CMMT C 2 210
    CMMT C 3 220
    CMMT C 4 230
    CMMT C 5 240
    CMMT D 1 200
    CMMT D 2 210
    CMMT D 3 220
    CMMT D 4 230
    CMMT D 5 240


    2) Necesito en las columnas los proveedores sin repetir (A,B,C,etc)

    Necesito en las filas codigo(CCAR) y para cada codigo los planes tarifarios(1,2,etc) y para cada plan tarifario su correspondiente precio ubicado en la columna correspondiente al proveedor(A,B,C,etc).

    Lo estaba analizando con tabla dinamica de Excel y necesitaria que quede asi:


    A B C D E
    CCAR 1 120,00 151,30 98,10 0,00 200,41
    2 265,00 238,85 234,90 0,00 238,85
    3 286,00 264,35 261,90 0,00 272,00
    4 286,00 264,35 261,90 283,00 0,00
    5 316,00 288,15 288,90 0,00 0,00
    CMMT 1 120,00 151,30 98,10 0,00 200,41
    2 265,00 238,85 234,90 0,00 238,85
    3 286,00 264,35 261,90 0,00 272,00
    4 286,00 264,35 261,90 283,00 0,00
    5 316,00 288,15 288,90 0,00 0,00

    No me doy cuenta si este es el metodo para resolver esta necesidad o si tengo que intentar otra cosa.

    Muchas gracias!

    ResponderBorrar
  3. Lo podes hacer con un corte de control con un for each anidado y grabar cuando cambia el primer codigo.

    ResponderBorrar
  4. Hola Enrique estoy probando asignar la propiedad grid.columns = &col, y no lo está tomando, probé poner esa asignación en diferentes eventos load de la grilla start refresh y nada sigue mostrando 1 sola columna

    ResponderBorrar

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

Aplicación monolítica o distribuida?

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.