Groogle al rescate

Hace ya unos años dediqué un tiempo en desarrollar un DSL (domain specific language) para poder usar los servicios de Google de una forma simple. La implementación la hice, obviamente, en Groovy (de ahí el nombre Groogle como contracción entre Groovy y Google)

Llegué a publicar bastantes releases cubriendo varios servicios como Drive, Sheet, Gmail, People y Calendar pero para ser sincero como no veía mucho interés por parte de la comunidad en el DSL lo fui dejando y dedicandome a otras cosas.

Pero de repente y por casualidad, hablando con una amiga me dice que han tenido un problema con la base de datos y que se va a pasar toda la mañana (con suerte) extrayendo datos de unas 120 hojas de cálculo Google para recuperarlos.

Básicamente, tenía que ir una por una, buscar la hoja correspondiente a diciembre y extraer los 31 valores de una columna, pasarlos a un fichero csv para al final del todo poder importarlos de nuevo a la base de datos.

INFO

No viene al caso el porqué una empresa maneja toda su información en hojas de Google. No creo que sean los únicos

Así que ví la oportunidad para desempolvar Groogle y echarle una mano.

En primer lugar, lo que necesitaba era los identificadores de todas esas hojas de cálculo y como además necesitábamos saber a quién correspondía cada una le dije a mi amiga que fuera recabando esta información (puesto que además era ella la que tenía acceso a las hojas). Simplemente tenía que prepara un fichero parecido a:

Fulanito 123123123123sdafas12312
Meganito 92131231ewewrdsfs112321
....

Los IDs se pueden extraer fácilmente de la URL cuando estás editando la hoja.

Mientras se ponía a esta tarea yo preparé el DSL:

@Grab('com.puravida-software.groogle:groogle-core:3.1.2')
@Grab('com.puravida-software.groogle:groogle-sheet:3.1.2')
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets
import com.google.api.client.json.gson.GsonFactory
import com.google.api.services.sheets.v4.SheetsScopes
import com.puravida.groogle.*
import java.text.SimpleDateFormat

lst = new File("lista.txt").text.split("\n")
sdf = new SimpleDateFormat("yyyy/MM/dd")
file = new File("data.csv")
file.text = "id | fecha | valor\n"

groogle = GroogleBuilder.build {
    withOAuthCredentials {
        applicationName 'test-sheet'
        withScopes SheetsScopes.SPREADSHEETS
        usingCredentials "client_secret.json"
        storeCredentials true
    }
    service SheetServiceBuilder.build(), SheetService
}

centros.eachWithIndex { line, cidx ->
    def kv = line.split(" ")
    def id = kv[0]
    def sheetId = kv[1]

    println id

    groogle.service(SheetService).withSpreadSheet sheetId, {
        withSheet 'Dic23', {
            def day = sdf.parse( "2023/01/01")
            def values = writeRange("J7", "J37").get()
            values.eachWithIndex{ v, idx->
                file << "${kv[0]} | ${sdf.format(day)} | ${v[0]}\n"
                day++
            }
        }
    }
    if( !(cidx % 10) ){
        sleep 1000*60
    }
}

Tras importar las librerías correspondientes e inicializar un par de variables empezamos escribiendo en el fichero a generar unas cabeceras

Usando withOAuthCredentials le diremos a Groogle que el usuario se tendrá que identificar para lo que se abrirá un navegador y el usuario podrá usar su cuenta para dar permisos al script.

Esto lo que quiere decir es que no necesito ejecutar el script en mi equipo, sino que puedo pasarselo tal cual y ella ejecutarlo en su máquina, usando su cuenta de Google (teniendo Groovy instalado claro)

El resto del script es bastante fácil:

  • leemos línea a línea el fichero que ha preparado con los IDs de las hoja

  • withSpreadSheet sheetId abre la hoja con este ID

  • withSheet 'Dic23' abre la pestaña de esa hoja

  • def values = writeRange("J7", "J37").get() leemos de una sola vez todo un rango

  • vamos volcando al fichero cada valor junto con el origen y la fecha

Para evitar que Google nos dé un error por muchas lecturas en poco tiempo metemos una espera cada 10 hojas de un minuto.

Tras un par de pruebas tuvimos listo el fichero completo.

Tiempo ejecución 5-8 minutos

Tiempo que nos llevó preparar el script 30-40 minutos

Conclusión

Sé que puede ser una noñería, pero que de vez en cuando, acuda a un proyecto OpenSource que publiqué hace un tiempo y que pueda resolverle a alguien el evitar estar todo un día realizando una tarea tan pesada como esta que se puede resolver con unas pocas líneas me llenan de orgullo y satisfacción. ;)

2019 - 2024 | Mixed with Bootstrap | Baked with JBake v2.6.7