// 1 de noviembre de 2020 · Daniel García Mejía

Enviar datos desde el script de carga de Qlik

Qlik Sense permite el análisis interactivo de datos, pero a veces solo quieres enviar datos a los usuarios por correo electrónico. Este tutorial describe cómo enviar una tabla de datos por email durante el proceso de carga utilizando Qlik Web Connectors y HTML, y comenta algunas de las otras cosas que puedes hacer con el conector SMTP gratuito.

Por qué enviar datos desde el script de carga de Qlik

QlikView tiene un par de características muy útiles que Qlik Sense no proporciona directamente: la QMC envía alertas por correo cada vez que falla una tarea, y la funcionalidad de Alertas. El uso del conector SMTP dentro de Qlik Web Connectors te permite replicar esa funcionalidad y, además, hacer más.

El conector SMTP es uno de los conectores estándar (es decir, gratuitos) que se proporcionan con Qlik Web Connectors. Lo que veremos aquí es empujar una tabla de datos agregados a una dirección de correo en cada actualización de los datos.

Enfoque de la solución

Normalmente, en una aplicación Sense cargas una serie de filas de detalle y después construyes tablas y gráficos que ofrecen vistas agregadas. Como vamos a enviar los datos desde el script de carga, tenemos que realizar las agregaciones nosotros mismos en este punto.

Para mostrar los datos agregados en un correo, usaremos HTML para construir una tabla, con un poco de CSS para que se vea ordenada. El conector SMTP permite pasar el cuerpo del correo en la URL o vincularlo a un archivo local. Como nuestra tabla puede crecer, la escribiremos en un archivo HTML en disco y le diremos al conector que lo tome de ahí.

Antes de empezar: requisitos previos

La solución asume que tu versión de Sense admite el comando URL IS (introducido en la versión de febrero de 2018) y hace referencia al conector SMTP de Qlik Web Connectors, por lo que conviene usar una versión actualizada de QWC.

Configuración de bibliotecas

Esta aplicación requiere dos bibliotecas:

  1. Una conexión web llamada GenericWeb. Puede apuntar a cualquier página web válida, ya que reemplazaremos la URL más adelante en el código.
  2. Una conexión de carpeta llamada TempData a un almacén temporal en tu servidor o escritorio Sense (por ejemplo c:\temp). Como ahí quedará una copia de tus datos, asegúrate de que sea una ubicación segura.

Subrutina de codificación

Algunas de las variables que conforman la URL que se pasa a Qlik Web Connectors deben estar codificadas para URL: los caracteres que podrían malinterpretarse se cambian por una secuencia de escape.

sub Encode(vEncodeMe, vEncoded)
  let vEncoded = replace(replace(replace(replace(replace(replace(replace(
    vEncodeMe, ':', '%3a'), '/', '%2f'), '?', '%3f'), '=', '%3d'), '\', '%5c'), '@', '%40'), ' ', '+');
end sub

El primer parámetro es el valor a codificar; el segundo es una variable que se rellena con el valor codificado.

Establecer constantes

Estas tres variables almacenan algunos valores de entorno. vQwcConnectionName es el nombre de la conexión web, vConn acorta nuestra URL más adelante y vEmailFile define dónde se escribirá el archivo (debe coincidir con la carpeta de la biblioteca anterior).

let vQwcConnectionName = 'lib://GenericWeb/';
let vConn = 'http://localhost:5555/data?connectorID=NotificationConnector';
let vEmailFile = 'c:\temp\EMailOutput.html';

La URL de tu Qlik Web Connector puede diferir; si tu instancia de QWC está en otra máquina, usa el nombre de máquina o dominio en lugar de localhost.

Configuración SMTP

Ahora definimos la configuración de la conexión SMTP. Algunas variables usan la subrutina Encode; otras no la necesitan.

call Encode('notifyme@email.com', vMailRecipients);
call Encode('smtp.gmail.com', vSMTP);
let vPassword = 'XXXXXXXXXXXXXXXXXXXXXXXX';
call Encode('someaddress@gmail.com', vFromEmail);
call Encode('Sending data from Sense Load Script', vSubject);
call Encode(vEmailFile, vEmailContent);
let vUseSSL = 'True';
let vSSLMode = 'Implicit';
let vPort = '465';

Los ajustes anteriores son para una cuenta de Gmail; adapta la configuración a tu servidor SMTP. Como este proceso solo sirve para enviar correos, es buena idea crear una cuenta específica para este propósito.

La contraseña debe codificarse antes de introducirla aquí. Puedes hacerlo desde la interfaz de Qlik Web Connectors (https://localhost:5555/ → conector SMTP, en Conectores Estándar): al probar la conexión con éxito, el código generado incluye la versión codificada de la contraseña. Ten en cuenta que se trata de una codificación bidireccional, así que quien tenga la contraseña codificada podría, en teoría, revertirla: de ahí el consejo de usar una cuenta dedicada.

Obtener algunos datos

Aquí traes los datos de origen de la tabla que quieras enviar. Este ejemplo usa datos de GapMinder a través de nuestra biblioteca genérica:

Population:
CROSSTABLE (Year, Population)
LOAD "Total population" as Country,
  [2011.0] as [2011], [2012.0] as [2012], [2013.0] as [2013],
  [2014.0] as [2014], [2015.0] as [2015]
FROM [$(vQwcConnectionName)]
(URL IS [https://docs.google.com/spreadsheet/pub?key=phAwcNAVuyj0XOoBL_n5tAQ&output=xlsx],
 ooxml, embedded labels, table is Data);

Agregar esos datos

Cuando creas una tabla en Qlik Sense, das unas dimensiones y unas medidas, y obtienes una fila por cada combinación de dimensiones. Necesitamos crear esa misma tabla en el script con una instrucción GROUP BY:

AnnualData:
LOAD Year,
  num(sum(Population), '#,##0') as [World Population],
  num(max(Population), '#,##0') as [Largest Population],
  num(avg(Population), '#,##0') as [Country Average]
RESIDENT Population
GROUP BY Year;

En este caso creamos una fila por año. Cada dimensión adicional debe añadirse tanto a la lista de carga como a la instrucción GROUP BY. Ten en cuenta que en el script no tienes acceso a Set Analysis, así que prueba las expresiones antes.

Cargar la cabecera de la tabla HTML

Vamos a escribir el contenido de una tabla Qlik en un archivo para enviarlo como correo HTML. Primero, el preámbulo:

EMailOutput:
LOAD [<!--EMailOutput-->] INLINE [
<!--EMailOutput-->
<html><head><style>
tr:first-child td {font-weight: bold; background-color: #dddddd;}
h3 {font-family: Arial; font-size: 12pt;}
td {border-left:1px solid #555; border-top:1px solid #555; font-family: Arial; font-size:9pt; text-align:left; padding: 2px 10px;}
table {border-right:1px solid #555; border-bottom:1px solid #555; border-collapse:collapse;}
</style></head><body>
<h3>Population stats for past five years</h3>
<table>
<tr><td>Year</td><td>World Population</td><td>Largest Population</td><td>Country Average</td></tr>
];

El nombre del campo se escribirá en el archivo de salida, por eso lo hemos puesto como un comentario HTML. La hoja de estilo permite que la tabla de datos sea mucho más sencilla.

Añadir la tabla de datos

Ahora formateamos cada fila como HTML y la concatenamos:

CONCATENATE (EMailOutput)
LOAD '<tr><td>' & Year &
  '</td><td>' & replace([World Population], ',', '&#44;') &
  '</td><td>' & replace([Largest Population], ',', '&#44;') &
  '</td><td>' & replace([Country Average], ',', '&#44;') &
  '</td></tr>' as [<!--EMailOutput-->]
RESIDENT AnnualData
ORDER BY Year DESC;

Fíjate en el replace: codificamos las comas de los números porque, al llamar a STORE más adelante, se colocan comillas dobles alrededor de los valores que incluyan comas, y eso rompería nuestro HTML. Si no usas la coma como separador de miles, puedes prescindir de los reemplazos.

Añadir el pie de la tabla

Igual que empezamos con la cabecera, ahora concatenamos el pie:

CONCATENATE (EMailOutput)
LOAD [<!--EMailOutput-->] INLINE [
<!--EMailOutput-->
</table></body></html>
];

Estamos construyendo el HTML por trozos; del mismo modo podríamos montar varias tablas y fragmentos de texto. No estamos limitados a una sola tabla.

Escribir el HTML en un archivo

Escribimos la tabla construida a un archivo que el conector SMTP pueda usar. Es un simple STORE, como el que probablemente uses para escribir QVD, pero indicando que sea texto:

STORE EMailOutput INTO [lib://TempData/EmailOutput.html] (txt);

Si tu biblioteca apunta a un servidor web, esta salida puede publicarse en una página: una forma estupenda de sacar datos de Sense hacia un panel de pared.

Enviar el correo

Por último, enviamos el email. Se hace extrayendo datos de una página web (como cualquier otra llamada de Qlik Web Connector), con la diferencia de que esta llamada interactúa con un servidor para enviar datos, no solo recibirlos:

SendEmail:
LOAD status as SendEmail_status,
  result as SendEmail_result,
  filesattached as SendEmail_filesattached
FROM [$(vQwcConnectionName)]
(URL IS [$(vConn)&table=SendEmail&SMTPServer=$(vSMTP)&useSSL=$(vUseSSL)&SSLmode=$(vSSLMode)&Port=$(vPort)&Password=$(vPassword)&to=$(vMailRecipients)&subject=$(vSubject)&message=%40file%3d$(vEmailContent)&fromName=Sense&fromEmail=$(vFromEmail)&appID=],
 qvx);

Los tres campos que devuelve la consulta confirman si el envío fue correcto. Para hacerlo a prueba de balas, usa PEEK sobre esos valores y verifica el resultado. En la URL verás todas las variables que hemos configurado; la clave es el parámetro message=, que apunta al archivo con el contenido que escribimos en disco.

Puedes generar la mayor parte de este código desde la interfaz de Qlik Web Connectors, pero aquí lo hemos parametrizado con variables para que sea más fácil de configurar y mantener.


En Digital Fox Data resolvemos este tipo de automatizaciones —y todo lo demás del script de carga— con nuestra consultoría Qlik, y enseñamos a tu equipo a dominarlas en nuestros cursos de Qlik. ¿Tienes un reto con Qlik? Hablemos.

// ¿tienes dudas?

¿Tienes dudas? Estamos aquí para ayudarte

En Digital Fox Data, estamos aquí para ayudarte a aprovechar al máximo el poder de tus datos. Si tienes preguntas o deseas más información sobre cómo nuestras soluciones de Business Intelligence pueden impulsar tu negocio, no dudes en contactarnos. Juntos encontraremos la mejor estrategia para transformar tus datos en decisiones.