Fullmenu null

 

17 February 2018

Caso de Uso

Este script no tiene un caso de uso práctico como tal sino que pretende demostrar la forma de mejorar el interface gráfico de los mismos para conseguir una mejor interacción con el usuario.

En este caso vamos a mostrar un diálogo donde cargaremos en una tabla una hoja de Google y el usuario podrá interactuar con los valores recuperados.

Dependencias

Nuestro script va a necesitar las siguientes dependencias agrupadas por funcionalidad:

@GrabConfig(systemClassLoader=true)
@Grab(group='org.groovyfx',module='groovyfx',version='8.0.0',transitive=true, noExceptions=true)
@Grab(group = 'com.puravida.groogle', module = 'groogle-sheet', version = '1.4.1')

import groovy.transform.Canonical
import groovyx.javafx.beans.FXBindable
import javafx.collections.FXCollections
import javafx.collections.ObservableList

import static groovyx.javafx.GroovyFX.start

import com.google.api.services.sheets.v4.SheetsScopes
import com.puravida.groogle.GroogleScript
import com.puravida.groogle.SheetScript

Por un lado vamos a necesitar las dependencias de GroovyFX para la parte visual y por otro vamos a necesitar Groogle para la parte de interactuar con GoogleSheet

Business

Nuestro negocio va a ser realmente muy simple. Vamos a representar cada fila de la hoja de cálculo mediante un objeto FxRow el cual contiene dos valores recuperados de esta así como un valor calculado por aplicación (coordinate) y otro que se actualiza tras la interacción del usuario con la fila en cuestión (derivate)

enum Status {
    ON, OFF
}

@Canonical
class FxRow {
    @FXBindable String coordinates
    @FXBindable String name
    @FXBindable Status status
    @FXBindable String derivate
}

rows=FXCollections.observableArrayList([])
self = this

Para la carga de este modelo vamos a usar una función loadFile la cual leerá la hoja de cálculo e inicializará el array de FxRows. Esta función será llamada únicamente cuando el usuario así lo desee pulsando un botón de la vista

def loadFile(){
    SheetScript.instance.withSpreadSheet args[0], { spreadSheet ->
        withSheet 'Hoja 1',{
            int idx = 2
            def googleRows = readRows("A$idx", "B${idx + 100}")
            while (googleRows ) {
                googleRows.eachWithIndex{ gRow, rIdx->
                    self.rows << new FxRow(coordinates: "A${idx+rIdx}",
                            name:gRow[0],
                            status: gRow[1]=='on'?Status.ON:Status.OFF,
                            derivate: ''
                    )
                }
                idx += googleRows.size()
                googleRows = readRows("A$idx", "B${idx + 100}")
            }
        }
    }
}

Vista

La vista se compone de un botón que activará una action y una tabla que mostrará de forma dinámica el array de FxRows. Así mismo podremos interactuar con los objetos en las columnas name y status de tal forma que podríamos actualizar la hoja, calcular valores o en definitiva cualquier acción que requiera el negocio.

start {
    actions {
        fxaction(id: 'loadFile',onAction: {loadFile()})
    }
    stage(title: 'VisualSheet', height: 600, visible: true) {
        scene(fill: BLACK, width: 800, height: 250) {
            hbox(padding: 60) {
                button( loadFile, text:'Load')
            }
            hbox(padding: 60) {
                tableView(selectionMode: "single", cellSelectionEnabled: true, editable: true, items: bind(self,'rows')) {

                    tableColumn(editable: false, property: "coordinates", text: "Row", prefWidth: 50)

                    tableColumn(editable: true, property: "name", text: "Name", prefWidth: 150,
                            onEditCommit: { event ->
                                FxRow item = event.tableView.items.get(event.tablePosition.row)
                                item.name = event.newValue
                            }
                    )

                    tableColumn(editable: true, property: "status", text: "Status", prefWidth: 150, type: Status,
                            onEditCommit: { event ->
                                FxRow item = event.tableView.items.get(event.tablePosition.row)
                                item.status = event.newValue
                                item.derivate = event.newValue==Status.ON ? "Yes" : "NO"
                            }
                    )

                    tableColumn(editable: false, property: "derivate", text: "Calculada", prefWidth: 150)
                }
            }
        }
    }
}

Esto es una imagen de cómo podría quedar la aplicación:

visual sheet

Script
//tag::dependencies[]
@GrabConfig(systemClassLoader=true)
@Grab(group='org.groovyfx',module='groovyfx',version='8.0.0',transitive=true, noExceptions=true)
@Grab(group = 'com.puravida.groogle', module = 'groogle-sheet', version = '1.4.1')

import groovy.transform.Canonical
import groovyx.javafx.beans.FXBindable
import javafx.collections.FXCollections
import javafx.collections.ObservableList

import static groovyx.javafx.GroovyFX.start

import com.google.api.services.sheets.v4.SheetsScopes
import com.puravida.groogle.GroogleScript
import com.puravida.groogle.SheetScript
//end::dependencies[]

//tag::business[]
enum Status {
    ON, OFF
}

@Canonical
class FxRow {
    @FXBindable String coordinates
    @FXBindable String name
    @FXBindable Status status
    @FXBindable String derivate
}

rows=FXCollections.observableArrayList([])
self = this
//end::business[]

//tag::load[]
def loadFile(){
    SheetScript.instance.withSpreadSheet args[0], { spreadSheet ->
        withSheet 'Hoja 1',{
            int idx = 2
            def googleRows = readRows("A$idx", "B${idx + 100}")
            while (googleRows ) {
                googleRows.eachWithIndex{ gRow, rIdx->
                    self.rows << new FxRow(coordinates: "A${idx+rIdx}",
                            name:gRow[0],
                            status: gRow[1]=='on'?Status.ON:Status.OFF,
                            derivate: ''
                    )
                }
                idx += googleRows.size()
                googleRows = readRows("A$idx", "B${idx + 100}")
            }
        }
    }
}
//end::load[]

//tag::login[]
GroogleScript.instance.applicationName='101-scripts'
clientSecret = new File('../google/client_secret.json').newInputStream()
SheetScript.instance.groogleScript=GroogleScript.instance.login(clientSecret,[SheetsScopes.SPREADSHEETS])
//end::login[]

//tag::view[]
start {
    actions {
        fxaction(id: 'loadFile',onAction: {loadFile()})
    }
    stage(title: 'VisualSheet', height: 600, visible: true) {
        scene(fill: BLACK, width: 800, height: 250) {
            hbox(padding: 60) {
                button( loadFile, text:'Load')
            }
            hbox(padding: 60) {
                tableView(selectionMode: "single", cellSelectionEnabled: true, editable: true, items: bind(self,'rows')) {

                    tableColumn(editable: false, property: "coordinates", text: "Row", prefWidth: 50)

                    tableColumn(editable: true, property: "name", text: "Name", prefWidth: 150,
                            onEditCommit: { event ->
                                FxRow item = event.tableView.items.get(event.tablePosition.row)
                                item.name = event.newValue
                            }
                    )

                    tableColumn(editable: true, property: "status", text: "Status", prefWidth: 150, type: Status,
                            onEditCommit: { event ->
                                FxRow item = event.tableView.items.get(event.tablePosition.row)
                                item.status = event.newValue
                                item.derivate = event.newValue==Status.ON ? "Yes" : "NO"
                            }
                    )

                    tableColumn(editable: false, property: "derivate", text: "Calculada", prefWidth: 150)
                }
            }
        }
    }
}
//end::view[]