JavaScript, HTML, CSS e... !
12 commenti

Riacquisire il focus con google.script.host.close()

Eseguire una funzione al click su un bottone in uno Spreadsheet e far tornare il Focus su una cella

Nell'articolo 'Bottoni che eseguono script in Spreadsheet con Google Apps Script' ho illustrato come sia possibile, in pochi passaggi, associare una funzione Apps Script ad un bottone all'interno di uno Sheet al fine di eseguire le operazioni desiderate al click su di esso.

Uno degli inconvenienti di questa funzionalità è che, dopo il click sul bottone, nonostante sia possibile posizionare automaticamente il cursore su una specifica cella dello Sheet, il focus sul foglio di calcolo viene perso pertanto coloro che hanno la necessità di scrivere direttamente da tastiera all'interno della cella selezionata si renderanno subito conto che nessun carattere viene acquisito.

Considerando che la documentazione ufficiale informa che per spostare il focus nel browser dell'utente da una finestra di dialogo o una barra laterale, nelle applicazioni della G Suite (Moving browser focus in G Suite), basta chiamare semplicemente il metodo google.script.host.editor.focus(), una prima soluzione potrebbe essere quella di avvalersi di un bottone personalizzato inserito all'interno della sidebar ed associare a quel bottone la funzione desiderata in Apps Script per poi fargli eseguire il metodo appena descritto, come nell'esempio direttamente presente nella documentazione ufficiale, editor.focus().

Tuttavia, sulla base di queste premesse, ho effettuando dei test affinché fosse possibile ottenere un comportamento simile sfruttando i bottoni personalizzati all'interno del foglio di calcolo.

Ho riscontrato che è possibile! Il risultato non è il massimo dell'eleganza ma per un uso interno di un applicativo il sistema funziona a dovere.

Il concetto gira intorno ad un uso indiretto della sidebar, considerando che il focus da essa all'editor viene passato non solo con il metodo precedentemente descritto bensì anche dopo la sua chiusura.
Per chiudere programmaticamente una sidebar esiste il metodo close(), pertanto nello specifico, l'idea è quella di invocare il metodo per aprire una sidebar vuota e chiuderla immediatamente dopo il suo caricamento tramite la chiamata di tipo HTML Service: google.script.host.close()

Il codice mostrato di seguito svolge quanto appena descritto:

Codice main.gs:

function inserisciNuovaRiga() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  sheet.insertRowBefore(2);
  showSidebar();
  var range = sheet.getRange("A2");
  sheet.setActiveRange(range);
}

function showSidebar() {
  var html = HtmlService.createHtmlOutputFromFile('sidebar');
  SpreadsheetApp.getUi().showSidebar(html);
}

Codice sidebar.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body onload="google.script.host.close();">
    
  </body>
</html>

Il requisito per il suo funzionamento, nel caso specifico, è che la funzione inserisciNuovaRiga() venga assegnata al bottone personalizzato in modo che, al click su di esso, una nuova riga venga sotto l'intestazione (con sheet.insertRowBefore(2)) per poi chiamare il metodo per aprire la sidebar che, subito dopo il suo caricamento (ovvero all'onload) esegue l'API asincrona lato client google.script.host.close() (nata appositamente per la chiusura di finestre di dialogo e barre laterali in Docs, Sheets e Forms che contengono pagine HTML Services) così da chiudersi automaticamente. In questo momento il focus tornerà al foglio di calcolo e la cella definita sarà selezionata e pronta per ricevere in input i caratteri immessi da tastiera.

Un risultato visivo del codice di cui sopra è il seguente, Fig. 1:



eseguire una funzione al click su un bottone in uno spreadsheet e far tornare il focus su un cella

Fig. 1 - Funzione eseguita al click su un bottone in uno Spreadsheet e Focus tornato su un cella


La parte poco elegante di questo approccio è che per un breve lasso di tempo, ogni volta che si clicca sul bottone per eseguire la funzione richiesta, comparirà e sparirà la sidebar.

Nota: Utilizzando .showModalDialog(html, ' ') al posto di .showSidebar(html) otterremo lo stesso risultato a livello pratico ma aggiungeremo in più un fastidioso cambiamento del colore di fondo dovuto all'aprirsi della modal fino alla sua chiusura automatica nonché la modal risulterebbe molto più invasiva rispetto alla barra laterale.

Tags

Michele Pisani

Michele Pisani

Sviluppatore Javascript ed esperto in Digital Analytics

L'esperienza nel settore Digital Analytics unita ad anni di sviluppo in Javascript ha trovato la massima espressione in Google Apps Script che mi ha permesso, con estrema facilità e poche righe di codice, di realizzare potenti applicazioni interattive e processi automatizzati integrati con i prodotti della G Suite.

Come contattarmi
scrivi un commento

12 Commenti

  1. Saturday, January 19, 2019 alle ore 15:45 Saver

    Ciao Michele, ti volevo chiedere se è possibile richiamare, come script di un bottone su foglio di calcolo, una funzione creata adhoc passando anche un parametro, oppure capire, visto che la stessa funzione viene invocata da più bottoni fifferenti, qual è il bottone che è stato cliccato. Grazie.

    Rispondi a questo commento
    • Sunday, January 20, 2019 alle ore 22:56 Michele PisaniAutore

      Ciao Saver,
      non credo sia possibile gestire i parametri direttamente da tale funzionalità.

      Puoi eventualmente utilizzare dei workaround come ad esempio, nel caso in cui il dato da passare come parametro derivi da un input dell'utente puoi utilizzare una funzione che richiama un prompt, con Browser.inputBox, e gestire il valore che verrà inserito.
      Alternativamente, puoi inserire il valore del parametro che dovrai passare alla funzione in una cella (magari di un foglio di appoggio) e all'interazione con il bottone, invece che passarlo come parametro, andarlo a recuperare dalla cella con getRange().

      Rispondi a questo commento
  2. Saturday, July 27, 2019 alle ore 17:07 roberto codutti

    buon giorno
    premetto che sono "neofita" della programmazione di scripts google, ma di recente mi stavo interessando alle google forms per la loro facilità di gestione. Per una richiesta che mi è stata fatta da un amico vorremmo ,tramite le forms gestire una sottoiscrizione indirizzata a degli utenti (sono delle associazioni che cooperano con il Banco Alimentare), per un corso che il banco tiene in determinate giornate (5). Avrei bisogno quindi di gestire una specie di "stato" della disponibilità di posti nelle giornate in cui un ente si iscrive.
    Secondo Lei è possibile "passare" questa informazione alle forms o reagire alla conferma di inserimento se non c'è più disponibilità ?
    .. poi per aggiornarmi sulla programmazione .. sono in attesa del Suo libro.
    Cordiali saluti
    Roberto Codutti

    Rispondi a questo commento
    • Sunday, July 28, 2019 alle ore 00:24 Michele PisaniAutore

      Ciao Roberto,
      i Google Forms non supportano l'esecuzione del codice al momento della compilazione del modulo, per esigenze della tipologia descritta può essere utile creare una web app con Apps Script.

      Alternativamente, rimanendo in ambito dei Google Forms, un'idea potrebbe essere quella di attivare la raccolta delle email dell'utente che compila il form ed avvalersi del trigger onFormSubmit(). In questo modo al momento dell'invio del form puoi eseguire una funzione che verifica la disponibilità dei posti ed invia una notifica via mail all'indirizzo dell'utente.

      Spero di averti dato un valido spunto :)

      Rispondi a questo commento
  3. Monday, March 28, 2022 alle ore 11:44 Iolanda

    Buongiorno,
    io ho un foglio con molte righe e quando lo apro avrei necessità di puntare il puntatore del mouse sulla prima riga vuota del foglio. Per fare questa operazione generalmente premo Ctrl+Freccia giù, ma volendo automatizzare questa operazione si può fare con App Script? Ho letto sia questo articolo che questo: https://www.appsscript.it/tutorial/bottoni-che-eseguono-script-in-spreadsheet-con-google-apps-script/
    ma essendo un'assoluta neofita non sono riuscita a creare uno script apposito.
    Chiedendo su un forum mi è stata suggerita questa soluzione che tuttavia non funziona:

    function onOpen() {
    var ss = SpreadsheetApp.getActive();
    var rgSel = ss.getActiveRange().getRow()
    if(rgSel === 1 ){
    var rMax = ss.getLastRow()+1;
    ss.getRange('A'+rMax).activate()
    }
    }
    function onSelectionChange() {
    onOpen()
    }



    C'è soluzione? :) La ringrazio per qualsiasi consiglio potrà darmi.

    Rispondi a questo commento
  4. Friday, October 21, 2022 alle ore 16:55 Benedetto

    Salve Michele,
    vorrei aggiungere al seguente script la possibilità di inserire contestualmente ( quando crea un nuovo numero di riferimento) nella cella I9 la data odierna :

    function incrementaValoreCellaB9() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getActiveSheet();
    var cell = sheet.getRange(21, 22);
    cell.setValue(cell.getValue() + 25);
    }


    Mi sa consigliare che stringa aggiungere?

    Grazie mille in anticipo per l'aiuto

    Rispondi a questo commento
    • Friday, October 21, 2022 alle ore 17:02 Michele PisaniAutore

      Ciao Benedetto,
      potrebbe esserti utile la funzione Utilities, ad esempio la seguente:

      Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")

      Rispondi a questo commento
      • Friday, October 21, 2022 alle ore 17:39 Benedetto

        Ciao Michele,
        grazie mille per la sollecita risposta, non sono molto pratico ...potresti indicarmi dove aggiungerla in riferimento a quello che ti ho inviato

      • Friday, October 21, 2022 alle ore 18:18 Michele PisaniAutore

        Ciao Benedetto,
        la mia mission è rendere autonomi e consapevoli chi si approccia a questo mondo.
        Do degli input nei commenti basati su un codice funzionante come visto nel video e lo faccio a in modo gratuito e per passione, il codice pronto gratuito non è utile né a me né a te né a nessuno.
        Per ottenere il risultato desiderato hai bisogno di specificare il range dove vuoi scrivere, e scrivere quello che ti ho inviato prima. La logica è pressoché la stessa di quello che hai già riportato, ti basta solo prendere consapevolmente di cosa fanno le varie righe. Sono certo che ci riuscirai in bene tempo.
        Nel mio canale trovi anche un corso gratuito sul JavaScript Semplificato per chi vuole iniziare a programmare, che ti fornirà i concetti basilari per ottenere il massimo risultato con il minimo sforzo :)

  5. Friday, October 21, 2022 alle ore 20:26 Benedetto

    ok grazie ..non riesco a capire come inserirlo all'interno dello stesso script ...
    sto cercano in rete ma non ho trovato nulla

    no problem e buon weekend!

    Rispondi a questo commento
    • Sunday, October 23, 2022 alle ore 15:49 Benedetto

      Ciao Michele,
      non riesci proprio a darmi la stringa completa collegata alla mia ...mi faresti veramente una GRANDE cortesia.... praticamente deve aggiornare contestualmente la data all'incremento del numero di riferimento con un unico script.........

      function incrementaValoreCellaB9() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getActiveSheet();
      var cell = sheet.getRange(21, 22);
      cell.setValue(cell.getValue() + 25);
      }

      scusami ancora ... ma non sono riuscito a farlo!

      Buona serata

      Rispondi a questo commento

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato.I campi contrassegnati da un * sono obbligatori
Puoi utilizzare i seguenti tag nei commenti:
[bold]testo[/bold] se vuoi evidenziare un testo con il grassetto[code]function helloworld() { }[/code] se vuoi pubblicare una porzione di codice[url]https://www.appsscript.it[/url] se devi riferirti ad un indirizzo web