Automatización y Personalización en la Analítica de Datos: Más allá de los límites aparentes

Dec 18, 2024


En el mundo de la analítica de datos, uno de los mayores desafíos no siempre está en el análisis en sí, sino en lograr que las plataformas, bases de datos y herramientas trabajen de manera fluida para entregar resultados impactantes. Hace poco tuve la oportunidad de liderar un proyecto que representó un gran reto de integración, pero también una oportunidad para demostrar cómo la creatividad técnica puede superar limitaciones aparentes.

Caso 1: Actualización automática de Google Docs desde Google Sheets y MySQL

El primer objetivo era que un documento de Google Docs se actualizara automáticamente con gráficos provenientes de Google Sheets, el cual estaba conectado a una base de datos MySQL. Esto debía ocurrir el mismo día de cada mes, sin intervención manual.

La solución combinó:
- Vistas optimizadas en la base de datos MySQL para preprocesar los datos necesarios.
- Google Apps Script, con el que se realizo todo el proceso de extracción de la información de la base de datos y se programaron tareas automáticas usando el sistema de disparadores de tiempo.
-Sincronización dinámica entre hojas de cálculo y el documento, asegurando que los gráficos siempre reflejaran los datos más recientes.

Aqui la parte del codigo en App Script

function executeMultipleQueries() {
  try {
    // Conexión a MySQL
    var connection = Jdbc.getConnection(
      'jdbc:mysql://direcion_op:3306/nombre_db', // Reemplaza con tu host y base de datos
      'tu_usuario_db', // Tu usuario
      'tu_contraseña' // Tu contraseña
    );

    // Obtiene la hoja donde están definidas las consultas
    var mainSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Consultas");
    if (!mainSheet) {
      SpreadsheetApp.getUi().alert('Crea una hoja llamada "Consultas" y define las consultas.');
      return;
    }

    // Lee las consultas desde la hoja "Consultas"
    var queries = mainSheet.getRange(2, 1, mainSheet.getLastRow() - 1, 2).getValues(); // Asume que tienes una lista desde A2:B (Consulta, Nombre Hoja)

    queries.forEach(function(queryInfo) {
      var query = queryInfo[0]; // Consulta SQL en la columna A
      var sheetName = queryInfo[1]; // Nombre de la hoja en la columna B

      if (!query || !sheetName) {
        Logger.log('Consulta o nombre de hoja vacíos. Consulta omitida.');
        return;
      }

      // Crea o selecciona la hoja para los resultados
      var resultSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
      if (!resultSheet) {
        resultSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName);
      }
      resultSheet.clear(); // Limpia la hoja de resultados

      // Ejecuta la consulta y escribe los resultados
      var statement = connection.createStatement();
      var results = statement.executeQuery(query);

      // Obtiene los metadatos de la consulta
      var metaData = results.getMetaData();
      var colCount = metaData.getColumnCount();

      // Escribe los encabezados
      for (var col = 1; col <= colCount; col++) {
        resultSheet.getRange(1, col).setValue(metaData.getColumnName(col));
      }

      // Escribe los datos
      var row = 2; // La primera fila es para los encabezados
      while (results.next()) {
        for (var col = 1; col <= colCount; col++) {
          resultSheet.getRange(row, col).setValue(results.getString(col));
        }
        row++;
      }

      // Cierra el statement
      results.close();
      statement.close();
    });

    // Cierra la conexión
    connection.close();
    Logger.log('Todas las consultas se ejecutaron correctamente.');

    // Simula el clic automático en el popup
    SpreadsheetApp.getActiveSpreadsheet().toast('Consultas ejecutadas y datos exportados.', 'Mensaje');
  } catch (error) {
    Logger.log('Error al conectar con MySQL o ejecutar las consultas: ' + error);
    SpreadsheetApp.getUi().alert('Error: ' + error.message);
  }
}

// Programa para que se ejecute el día 9 de cada mes
function scheduleMonthlyExecution() {
  ScriptApp.newTrigger("executeMultipleQueries")
    .timeBased()
    .onMonthDay(4)
    .atHour(9) // Cambia la hora según prefieras
    .create();
}



El resultado: un flujo automatizado que elimina la necesidad de actualizaciones manuales, permitiendo a los equipos concentrarse en el análisis de los datos, en lugar de perder tiempo en tareas repetitivas.

Caso 2: Automatización de tableros en Looker

En Looker, el reto fue distinto: no cuenta con una funcionalidad nativa para actualizaciones programadas específicas basadas en criterios complejos de fechas. Sin embargo, conseguimos implementar una solución personalizada al:

- Añadir columnas de fecha actual en la base de datos para habilitar condiciones que Looker pudiera interpretar directamente.
- Crear campos calculados avanzados en Looker para emular filtros dinámicos de tiempo.

CASE
  -- Primera condición: Si el día actual del mes es mayor o igual a 11
  WHEN EXTRACT(DAY FROM CURRENT_DATE()) >= 11 THEN 
    -- Devuelve la fecha del día 11 del mes actual
    PARSE_DATE(
      "%Y-%m-%d", -- Define el formato de fecha
      CONCAT(
        CAST(EXTRACT(YEAR FROM CURRENT_DATE()) AS STRING), "-", -- Año actual convertido a texto
        CAST(EXTRACT(MONTH FROM CURRENT_DATE()) AS STRING),     -- Mes actual convertido a texto
        "-11"                                                  -- Día 11
      )
    )

  -- Segunda condición: Si estamos en enero (mes = 1)
  WHEN EXTRACT(MONTH FROM CURRENT_DATE()) = 1 THEN 
    -- Devuelve la fecha del día 11 de diciembre del año anterior
    PARSE_DATE(
      "%Y-%m-%d", -- Define el formato de fecha
      CONCAT(
        CAST(EXTRACT(YEAR FROM CURRENT_DATE()) - 1 AS STRING), -- Año anterior convertido a texto
        "-12-11"                                              -- Mes diciembre y día 11
      )
    )

  -- Tercera condición: Cualquier otro caso (día < 11 y no estamos en enero)
  ELSE 
    -- Devuelve la fecha del día 11 del mes anterior
    PARSE_DATE(
      "%Y-%m-%d", -- Define el formato de fecha
      CONCAT(
        CAST(EXTRACT(YEAR FROM CURRENT_DATE()) AS STRING), "-", -- Año actual convertido a texto
        CAST(EXTRACT(MONTH FROM CURRENT_DATE()) - 1 AS STRING), -- Mes anterior convertido a texto
        "-11"                                                  -- Día 11
      )
    )
END

Explicación Detallada de la Lógica

  • Condición 1: Día actual es mayor o igual a 11

    Si el día del mes actual (EXTRACT(DAY FROM CURRENT_DATE())) es 11 o superior, se calcula la fecha del día 11 del mes actual.

    Ejemplo: Si hoy es 15 de diciembre, devolverá 2024-12-11.


  • Condición 2: Estamos en enero

    Si el mes actual (EXTRACT(MONTH FROM CURRENT_DATE())) es 1 (enero), se calcula la fecha del 11 de diciembre del año anterior.

    Esto es necesario porque no hay un "mes anterior" a enero en el mismo año.

    Ejemplo: Si hoy es 5 de enero de 2024, devolverá 2023-12-11.


  • Condición 3: Día actual es menor a 11 y no estamos en enero

    Si no se cumplen las condiciones anteriores, calcula la fecha del 11 del mes anterior.

    Ejemplo: Si hoy es 3 de diciembre, devolverá 2023-11-11.


Estas configuraciones transformaron las limitaciones técnicas en una experiencia de usuario fluida, manteniendo la flexibilidad requerida para el análisis.

Reflexión: Creer en la Automatización como un Habilitador

Ambos proyectos aunque en lectura parecen faciles, realmente me siguen demostraron que, con las herramientas adecuadas y una visión orientada al cliente, es posible adaptar las plataformas a necesidades específicas, incluso cuando parece que las herramientas tienen limitaciones insalvables.

Esto no solo reduce drásticamente el tiempo dedicado a tareas manuales, sino que también abre espacio para lo que realmente importa: analizar los datos de manera más profunda y generar un impacto tangible.

En la era de la automatización y el análisis de datos, el límite está en nuestra capacidad para innovar y cuestionar los métodos tradicionales. 🚀

© Johana 2023. All rights reserved.

© Johana 2023. All rights reserved.

© Johana 2023. All rights reserved.