lunes, 19 de noviembre de 2012

QlikView Power Tools

Parece interesante, es una serie de herramientas para un Administrador de Qlikview Server, tirando a avanzado.
Si bien, aún no me puse a jugar lo dejo publicado para el que no las conoce y le puedan servir y para recordarme de alguna forma que tengo que revisarlas :P

QlikCommunity: PowerTools

miércoles, 14 de noviembre de 2012

Dimensiones Dinamicas

Buscando otra cosa, me encontré con este que me pareció un ejemplo copado de lo util que puede ser el uso de variables: Dynamic Dimensions in QlikView Chart

Resumiendo un poco, el tipo crea una variable donde arma una lista de campos por los que quiere evaluar un gráfico de barras, y con un botón que aumenta el indice va "recorriendo" las diferentes dimensiones que enumero en la variable. 
Con mucha menos complicación esto lo hubiera logrado usando grupos jerárquicos o ciclicos (Grupo Jerárquico "Dinámico"), pero bueno, fue su primer post sobre Qlikview, una solución bastante buena encontró sin conocer los grupos de dimensiones.

Tamaño de fuente de una dimensión y/o expresión 1

Bueno, definitivamente esto es algo que Qlikview tiene para mejorar. 
Si bien uno tiene la opción para editar el Formato de Texto en dimensiones y expresiones, no es posible editar el formato desde acá pues no existe código script para hacerlo (al menos hasta la versión 10 que es en la que lo probé), lo cual imposibilita colocar condiciones para mostrar los datos de una u otra manera.

Mucha gente recomienda probar con tags como <B> y <H1>, tal y como se haría en un entrañable HTML, pero nadie publico resultados positivos al respecto y personalmente no observe cambio alguno donde lo apliqué.

En caso de las expresiones de una tabla simple o pivotante podemos colocar condiciones de formato directamente en las propiedades del gráfico, solapa Efectos Visuales.


Para los gráficos que no tienen esta solapa, la recomendación para mostrar dimensiones y/o expresiones en un formato u otro es crear 2 expresiones iguales, con distinto formato y mostrarla u ocultarla según corresponda. Una forma de "mostrar y ocultar" la expresión seria colocando en la expresión: if(condicion,calculo,0)De esta manera, cuando no se cumpla la condición, la expresión no se visualizará por ser 0 su valor.

Un ejemplo de esto mismo:
Por claridad defino 3 expresiones, una que será condición de cual "color" mostrar y a la vez el calculo a realizar.



Análogo a Bajo esta la expresión Alto donde la condición es cond>1500. Y el resultado que obtenemos es un una barra que varia de color según si tenemos mas de 1500 horas por mes.



Un detalle, llegan a ver que la separación de las columnas varia? eso se debe a que siempre deja el espacio para las 3 barras, la solución es apilar las columnas. Para esto tampoco podríamos tener la expresión auxiliar cond, pues las barras flotarían ejeje. 

Con cond y apilando (dicho sea de paso, usando esta característica es como se puede graficar un gantt en Qlikview).
 Sin expresión auxiliar cond:

viernes, 9 de noviembre de 2012

Definir variables desde un archivo plano - Parte 2

Ampliando mi excel de variables me encontré con el siguiente caso.
Si una variable contiene una expresion que utiliza otra variable aún no declarada, la variable queda definida con un error interno:


En la imagen, se puede apreciar como al leer de la tabla V, en la variable l_val la expresión utiliza  la variable vMesActAñoAnt, pero al crear la variable vBASE_VENTAS queda un internal_error. Esto se debe a que intenta evaluar la variable vMesActAñoAnt que aún no existe.

La solucion fue un ligero cambio en el codigo:

FOR i = 1 TO NOOFROWS('V')
     l_var = PEEK('V.NOMBRE', $(i)-1, 'V');
     $(l_var) = '='&PEEK('V.EXPRESION', $(i)-1, 'V');
NEXT i;

De paso, también le concatené el igual adelante (=), para no tener que poner $(=variable) cada vez que la quiero usar en una expresión, de ese modo solo tengo que poner el nombre de la variable. Por ej. SUM(vBASE_VENTAS)

jueves, 8 de noviembre de 2012

Definir variables desde un archivo plano - Parte 1

Una de las utilidades mas lindas que tienen las variables en QV es que podemos guardar en ellas código y luego reutilizarlo donde queramos.

En mi caso necesito aplicar el siguiente calculo a 8 graficos distintos: 
(if(PASOS <13, acumY/PASOS, acumY/12)-(if( PASOS<13, (acumXY - ((acumX * acumY)/PASOS)) / (acumX2 - (pow(acumX,2)/PASOS)),(acumXY - ((acumX * acumY)/12)) / (acumX2 - (pow(acumX,2)/12)))*if(PASOS <13, acumX/PASOS, acumX/12)))+(if( PASOS<13,(acumXY - ((acumX * acumY)/PASOS)) / (acumX2 - (pow(acumX,2)/PASOS)),(acumXY - ((acumX * acumY)/12)) / (acumX2 - (pow(acumX,2)/12))))*MESAÑO

Esta claro que el día que tenga que cambiar este calculo voy a preferir cambiarlo en una sola vez en lugar de hacerlo 8 veces, así que voy a guardar el calculo en un excel y con eso defino una variable que reutilizare en los 8 gráficos.

El Excel: variables.xlsx

El código para generar cada una de las variables declaradas en el excel:

QUALIFY *;
V:
LOAD NOMBRE,
EXPRESION
FROM ..\..\..\CFG\variables.xlsx (ooxml, embedded labels, table is Hoja1);

UNQUALIFY*;

FOR i = 1 TO NOOFROWS('V')
l_var = PEEK('V.NOMBRE', $(i)-1, 'V');
l_val = PEEK('V.EXPRESION', $(i)-1, 'V');
SET $(l_var) = $(l_val);
NEXT i;

DROP Table V;

Ejemplo de utilización de la variable en un gráfico:  SUM($(=v_estimaicon_lineal))

miércoles, 31 de octubre de 2012

Grupo Jerárquico "Dinámico"

El problema:
Tengo el detalle de Gastos con apertura por niveles, y los mismos están des-balanceados (digamos que no todas las aperturas llegan hasta el mismo nivel) En la imagen se puede apreciar que Compras no tiene Nivel 4, mientras que Gastos Operativos si lo tiene.


Ahora bien, al querer representar estas aperturas en un gráfico de linea con un grupo jerarquice como dimensión, si selecciono Compras (Nivel 3) no tengo datos (pues no tiene apertura para Nivel 4) y queda:


Es evidente que nos interesa evitar esta situación, por la falta de estética y confusiones que puede generar.
Lo que hacemos es colocar una condición como la que sigue en las dimensiones del grupo jerárquico con problemas. Siempre recordando colocar la misma condición en la etiqueta, para que varíe según la dimensión a mostrar.


El codigo:
=IF(GetPossibleCount( AJUS.DESCRIPCION5 ) >0,Capitalize(AJUS.DESCRIPCION5), Capitalize(AJUS.DESCRIPCION4))
Como queda al intentar navegar Compras:

Como queda al intentar navegar Otros Ingresos:

martes, 30 de octubre de 2012

Cadena de Recarga

Lo usual es empezar toda cadena de recarga con un .BAT que haga backups. Así que sin mas,  eso es lo que vamos a hacer :)

1) Al ser la primer tarea de recarga un programa externo, añadimos la tarea de recarga desde acá, :


2) En la linea de comando colocamos una sentencia de ejecución como si ejecutáramos el programa desde el CMD de Windows.

En mi caso: "E:QlikviewPRDCMDCOPY.BAT E:QlikviewPRDDATASAPQVD*.QVD E:QlikviewBACKUPDATASAPQVD"

Donde, mi COPY.BAT no es mas que un copy.
@ECHO OFF ECHO "ESTE PROGRAMA RECIBE 2 PARAMETROS. ORIGEN Y DESTINO" 
COPY %1 %2 
3) Ahora solo queda comenzar a crear las tareas de recarga de los QVW en el orden de ejecución que corresponda a partir de esa tarea colocandola como disparador.

En caso que los qvw que quieren schedulear no esten visibles en Source Documents deben añadir la ruta de los mismos en el QDS.

Estoy algo corto de tiempo así que no estoy cubriendo algunas situaciones que mas adelante comentaré, si algo no queda claro o necesitan alguna mano trataré de ayudar. Imagino que es algo que siempre se supo.

viernes, 26 de octubre de 2012

Minimizar Automático

Si la idea es que al activar el objeto "A", este ocupe el mismo espacio en donde esta el objeto "B", ambos deberán tener marcada la opción de Minimizado Automático.


Lo malo es que no importa si los objetos se pisan entre si o no, todos los objetos con esta opción activa se minimizaran al activar cualquier otro objeto que también tenga la opción tildada. Así que para cualquier otro caso no queda otra mas que crear objetos de texto transparentes sobre los objetos minimizados con acciones de minimizar y restaurar.

Por ej. me interesa que los dos Top n (CH01 y CH02) se activen siempre juntos y que alternen con un gráfico de tortas (CH03). Para esto creo 2 objetos de texto con transparencia 100% [1](en las imágenes pondré 50% para que ustedes los distingan), en la capa superior (para "pisar" los gráficos minimizados) [2] y con las acciones Minimizar Objeto  y Restaurar Objeto[3].
[1] 

[2] 

[3]
Acciones del "botón" superior: 
 

Donde queda de la siguiente forma:

Al presionar sobre el botón superior:


Y sobre el inferior:


Obviamente es indispensable no olvidarse de bloquear los objetos para que al cliquear sobre los mismos no terminen corridos y deje de funcionar : )

Marcando todos los objetos puedo bloquearlos a la vez:


martes, 23 de octubre de 2012

Cambiar el color de la leyenda de expresión

Es facil, pero a veces no todos lo encuentran tan rápido, y que mejor que un video para ver exactamente donde encontrar la opción que buscamos?  : )


miércoles, 26 de septiembre de 2012

Como dibujar circulos en Qlikview

Fácil, fácil, fácil! Buen dato publicado en BI Review.

Crear un objeto de texto, y en la solapa Diseño de las propiedades marco "Esquinas Redondeadas" y pongo 100% en el Angulo de Redondeo.

miércoles, 5 de septiembre de 2012

"POP-UP"

La solucion a este asunto es realmente sencilla, pero como siempre el objetivo es facilitar lo mas posible la vida a quien empieza voy a mostrar hasta lo mas basico.

Para lanzar mensajes en forma de POP-UP podemos utilizar directamente la herramienta de Alertas que ofrece QV, accediendo al menú Herramientas -> Asistente de Alerta llegamos a un Wizard con la explicación de cada opción de las Alertas, asi que no hace falta explicar nada de esto.

Sin embargo, la manera en la que resolví "lanzar un pop-up" en esta ocasión fue simplemente mostrando y oculando un objeto de texto.

En mi caso, un botón debe abrir un .QVW que aún no existe y para evitar el desagradable mensaje de error indicando que el archivo no existe lo reemplace por una advertencia mas amigable. 


El desagradable mensaje de error:

La condición de visualización del mensaje:

La acción del mensaje (para que al hacer clic sobre el mensaje, este desaparezca):

La acción del botón:

Como queda el bello "POP-UP":

viernes, 31 de agosto de 2012

Qualify, Join y Asociatividad

No es ninguna novedad que aterrizar al "mundo de la asociatividad" después de años de bases de datos relacionales puede ser complicado, en particular, cuando tenemos varias tablas con campos de nombres muy genéricos, como son: "DESCRIPCIÓN", "IMPORTE", "CANTIDAD", etc. 
Si bien lo usual es renombrar estos campos "conflictivos", es bastante tedioso hacerlo cuando la cantidad de campos es considerable. La solución rápida y conocida para este tipo de casos es aplicar la función QUALIFY, si aún no la utilizaron activa entre JOINs les adelanto que puede ser algo engorroso.

Para el caso particular con el que voy a trabajar, tengo 2 pares de tablas iguales (ZC y JER), donde cada par de tablas corresponde a una estructura de balance diferente (ACON y AJUS). Cada una de estas 4 tablas las tengo en 4 .QVDs distintos generados en la primer etapa de STG, que se relacionan a través de la tabla de hechos (GLT0). 

Usando QUALIFY  y UNQUALIFY sin complicarse demasiado el modelo nos quedaría:

El código para AJUS:

EL MODELO:


Ahora bien, dejando a un lado las razones técnicas o ideológicas que me motivaron, mi intención es que los campos con igual nombre se diferencien solo por el tipo de estructura de balance y no por el nombre de la tabla, lo que me permitiría trabajar con los campos con mas "homogeneidad" por así decirlo.
Si intentara etiquetar a dos tablas con el mismo nombre, digamos "AUX", teniendo el QUALIFY activo, los nombres de los campos de la primer tabla quedarían AUX.nombreCampomientras que en la segunda tabla quedarían AUX-1.nombreCampo. Pero renombrar una tabla después de cargarla no modifica los nombres de los campos de la misma, de modo que con pocas modificaciones de codigo puedo llegar a mi objetivo.


El código para AJUS:

EL MODELO:

Perfecto! Antes de seguir quiero comentar muy por encima algo sobre los modelos de datos asociativos. Como sabrán, QlikView levanta todo a memoria y una vez allí lo trabaja con un modelo asociativo del que, al momento, no hay detalles técnicos publicados por cuestiones de patente. Algunas cosas que si se saben sobre la asociatividad de QV y son de suma importancia son:
  • Las tablas con los mismos nombres de campos se concatenan automáticamente
  • Tablas que comparten nombres de algunos campos se ASOCIAN automáticamente.  La asociación de la que hablo tiene la misma finalidad que un join, pero con el modelo de datos asociativo. Sobre esto QlikTech indica:
En muchos casos tales joins darán como resultado tablas muy grandes. Una de las principales características de QlikView es la posibilidad de hacer asociaciones entre tablas en lugar de unirlas (join), lo cual reduce el uso de memoria, incrementa la velocidad de proceso y ofrece gran flexibilidad. Los joins explícitos deben ser evitados en los scripts QlikView. La funcionalidad keep fue designada para reducir el número de casos donde necesita usar joins explícitos. 
Teniendo en cuenta esto, no haría falta modificar nada mas en nuestro modelo. 
Sin embargo, ahora me gustaría generar nuevos .QVDs con los nuevos nombres de campos y filtrando un poco. Sabiendo que la relación que tengo entre los campos ERGSL y CUENTA es de uno a uno voy procurar un solo QVD por estructura de balance quedando uno para ACON y otro para AJUS en lugar de 2 para cada uno.

El código para AJUS:

EL MODELO:



Adjunto un Paper en ingles sobre Modelo de Dato Asociativo: Associative Model Data

miércoles, 15 de agosto de 2012

Evaluación Técnica

Una pequeña evaluación para Desarrolladores

  1. Como eliminaría una clave sintética?
  2. Que es la referencia circular y como la eliminaría?
  3. Como intentaría reducir la memoria usada por un documento?
  4.  Diferencia entre LET y SET?
  5. Para qué sirve la sentencia INPUTFIELD?
  6. Codifique 3 ejemplos de set analisys (análisis de conjuntos) y explique cada uno.
  7. Cuál es el resultado del siguiente código:


  1. Usó alguna vez una macros en sus aplicaciones? Si lo hizo, cual uso?
  2. Cuáles son los pasos para generar e imprimir un informe en formato PDF?
  3. Codificar la siguiente línea utilizando la sentencia LOAD.
SELECT * FROM TABLE WHERE CODE IN ('a', 'b', 'f');

  1. Enumere los distintos tipos de seguridad que ofrece QlikView. Si implemento alguno, descríbalo.
  2. Se desea que un botón aplique un filtro sobre el campo CUENTA,  de modo que selecciones las cuentas que empiezan con 22 y 23. Que acción utilizaría y con que código?

  1. Cuál de las siguientes opciones es más eficiente en una expresión de gráfico?

OPCIÓN 1
OPCIÓN 2
Hacer un count(OrderID) siendo:
LOAD
             …,
OrderID,
FROM Orders;

Hacer un sum(OrderRecordCounter) siendo:
LOAD
             …,
OrderID,
1 AS OrderRecordCounter,
FROM Orders;


martes, 14 de agosto de 2012

Control de Cargas

Para quienes, como a mi, su primer encuentro con QlikView fue alguien acercándole un manual de Desarrollador, otro de Diseñador y una fecha de entrega para un proyecto, hay muchas cosas que bien pueden considerarse básicas y que no sabemos.
Una de esas cosas tan fundamentales es como controlar las recargas y que hacer en caso de cancelaciones, por lo que intentare arrojar un poco de luz al respecto.

Antes que nada debemos tener presente algunos conceptos previos.

▄ El esquema gráfico de casi cualquier proyecto en QV se divide en tres etapas generales:

DATA: Extracciones puras de las distintas fuentes.
STG: Tratamiento de los datos extraídos. Esta etapa se puede dividir a su vez en varias etapas de STG.
APPS: La etapa de aplicaciones levanta la información tratada o pura (si no se trato) y los presenta en los diferentes tableros.

▄ En la consola de QV (Publisher, QMEC o como quieran llamarlo) las encargadas de recargar los distintos .QVW son las "tareas de recarga". Las mismas pueden ejecutarse planificadas por calendario, eventos externos o eventos de otras tareas (Finalización satisfactoria o fallida). De interés para el control de cargas, también tienen un TimeOut y una Cantidad de reintentos que establece cuantas veces intentará recargar en caso de fallar.

▄ Finalmente debemos saber el lugar donde se guarda el log de cada tarea de recarga que ejecuta el QDS (QlikView Distribution Service). Esto lo verificamos desde la consola como se muestra en la siguiente imagen, que si bien no es el lugar exacto donde se graban nos deja muy cerca.


Bien, ahora si empezamos con el Control de Cargas. 

Ante la llegada de un mail de alerta por cancelación debemos, antes que nada, verificar que el alerta no sea falsa, esto no es lo normal pero puede suceder, al menos hasta la versión 10 RS 3.
En mi caso los mails de cancelaciones llegan asi:
Del mail solo me interesa el nombre del .QVW que cancelo, en este caso "DATA_SAP_LP0_FI_HRP_1000". Buscando ese nombre en la ruta que hallamos antes deberían aparecer los logs de los ultimos 30 días de recargas (la cantidad de días guardados puede variar según configuración). De paso obtenemos la ruta exacta donde se guardan los logs. En mi caso: "D:\Qlikview\Logs\DistributionService\2\Log\"


Accediendo a la carpeta del día de la cancelación nos podemos encontrar con 2 o 3 archivos, según si la tarea de recarga tenga distribución o no (sobre distribución ya habrá otro post). Ahora mismo nos interesan los archivos DocumentLog.txt (log de cada sentencia de script ejecutada, es el mismo log que obtendríamos recargando a mano desde QlikView) y TaskLog.txt (log de la tarea de recarga).

Llegados a este punto estamos en condiciones de preguntarnos ¿Cuando una alerta de cancelación es falsa? Bien, recuerdan que las tareas de recarga tienen una cantidad de reintentos máximos? bueno, por lo menos hasta la versión 10 RS 3, a veces, si el primer intento de recarga falla pero el siguiente (o uno de los siguientes) funciona el Publisher "no lo reconoce" y sigue relanzando la recarga, cuando finalmente se queda sin reintentos o timeout envía el alerta de cancelación sin importar si los datos se extrajeron bien o mal. 
Entonces para detectar si el alerta es falsa o no, debemos revisar el DocumentLog y buscar el texto Execution finished, si por cada vez que aparece ese texto arriba dice que falló ("Execution Failed") entonces el alerta es verdadera, de lo contrario habrá sido una falsa alarma.

Dos ejemplos de lo que intento explicar.
Alerta verdadera:

La recarga falla en cada intento y deja de intentar porque se le acaban la cantidad de reintentos o por timeout.

Alerta Falsa:


Si bien el primer intento falla, podemos ver como la segunda vez que finaliza la ejecución no presenta mensaje de cancelación arriba, al contrario tiene un llamado a la rutina final que recupera un timestamp de fin de ejecución, y aún así se relanza nuevamente la recarga.

Una vez que accedemos a la consola las cancelaciones se visualizan con rojo como se ve en las imagenes, tanto si las cancelaciones fueron verdaderas o falsas debemos abrir el arbol de tareas de recarga hasta llegar a una tarea despues de las canceladas y verificar que se haya ejecutado todo mirando la hora de la ultima ejecución.

Para este caso las alertas fueron verdaderas por lo que relanzo las recargas de todo lo que canceló presionando en el boton  . De haber sido falsas debería mirar en la columna Last Execution, si la fecha es posterior a la cancelación de arriba no hará falta relanzar nada, si es anterior a la misma en lugar de relanzar la recarga de lo que esta en rojo bastaría con relanzar las recargas siguientes ya que no se lanzaron como se esperaba.

 

Teniendo en cuenta las etapas que se presentaron en un principio y ya que las cancelaciones fueron en la etapa DATA corresponde relanzar las recargas de las etapas STG y APPS (una vez hayan terminado las bien DATA), pues no puede asegurarse la fiabilidad ni completitud de los datos con los que se recargaron.



Para mi caso STG se divide en "STG de SAP" y "STG de indicadores y APPS" por lo que relanzo la primera y una vez finalizada relanzo la otra etapa.


Una vez haya terminado de recargar el ultimo QVW estaremos en condiciones de reportar la disponibilidad de los datos al usuario y ser felices. Espero que algo de todo lo dicho pueda servir a quien no haya podido hacer los cursos. 

Saludos