A seguito di alcune richieste, sto preparando uno script per automatizzare l’apertura e la chiusura di un modulo Google in orario e data stabiliti in anticipo. La procedura è appena impostata, e ha bisogno di essere testata. Se vuoi prendere parte al test:
- usa la procedura solo per le prove, non su moduli diffusi correntemente; se lo fai, sii consapevole dei possibili malfunzionamenti
- sei libero di testare usando codice e istruzioni qui sotto, e di riutilizzare il codice secondo i termini della licenza dei materiali di questo sito CC BY-NC-SA 4.0
- se hai domande o segnalazioni veloci, utilizza i commenti in fondo a questo post
- ti chiedo comunque, se puoi, di dare un riscontro finale segnalando sia il funzionamento corretto, che malfunzionamenti, errori o funzionalità che andrebbero migliorate o aggiunte usando questo modulo: https://forms.gle/UtE8Yhd6wqVnXMtf7; a questo serve il test
- lo script testato e definitivo sarà pubblicato su questo blog non appena pronto
Istruzioni per il test
- crea il modulo Google che ti servirà per il test; vai nel menu in alto a destra, 3 pallini verticali, e apri Editor di script, quindi dai un nome al progetto di test
- elimina la funzione vuota predefinita, incolla il codice che trovi qui sotto e salva con l’icona apposita
- controlla che sia selezionata (sulla barra dell’editor in alto) la funzione onOpen, quindi clicca su Esegui ed accetta le autorizzazioni
- torna nel modulo, clicca l’icona a forma di puzzle Componenti aggiuntivi e scegli la voce con il nome del progetto che hai appena assegnato al test
- scegli Imposta inizio e fine compilazione, segui le indicazioni per impostare apertura e/o chiusura automatica e testa il funzionamento – più sotto trovi alcune indicazioni per i test da effettuare
Cosa fa lo script
- permette di impostare data e ora di apertura e di chiusura del modulo, entrambe o una sola delle due
- crea uno/due attivatori automatici, che all’ora stabilita attivano e/o disattivano la raccolta delle risposte senza intervento manuale del proprietario
- se viene scelta una data di inizio, l’attivatore inoltre si occupa di disattivare la raccolta delle risposte da subito, per poi riaprirla quando indicato
- ad ogni nuova impostazione, elimina di default tutti gli attivatori precedenti, per non generare potenziali conflitti nascosti – attenzione a questo aspetto, se crei attivatori manualmente sullo stesso modulo, questi andranno persi
- effettua alcuni controlli sui dati inseriti, per prevenire errori nel formato di data e ora
- accetta la data in diversi formati (dd/mm/yyyy, dd-mm-yyyy, dd.mm.yyyy); accetta giorni, mesi e ore ad una cifra sia con lo 0 iniziale che senza; si occupa di normalizzare automaticamente tutte queste varianti
Cosa non fa lo script
- non permette di inserire un tempo massimo di compilazione slegato da ora di inizio e fine
- non permette interazione con il compilatore; le impostazioni agiscono solo a monte, a livello di modulo del proprietario
- in caso si voglia impostare sia l’inizio che la fine, permette di impostare solo un intervallo di tempo: non è possibile indicare più finestre di compilazione (ad es. dal 2 al 9 gennaio 2021, e anche dal 3 al 9 marzo 2021)
Cosa testare
- verifica che apertura e chiusura del modulo avvengano effettivamente agli orari indicati
- prova ad inserire date e orari volutamente errati, e verifica che vengano segnalati correttamente gli errori
- prova ad inserire le varianti di formato data e ora indicate sopra, con o senza lo 0 iniziale nei valori ad una cifra
- controlla nell’interfaccia dell’editor che vengano creati gli attivatori giusti, e che aprendoli abbiano i dettagli corretti rispetto alle impostazioni che hai dato
- controlla se vengono segnalati errori imprevisti
- se hai dimestichezza con Apps Script, controlla il codice e fornisci suggerimenti per migliorarlo
Il codice
// lo script permette di impostare un inizio e/o una fine di compilazione del modulo // se impostate, verranno creati degli attivatori automatici che apriranno e/o chiuderanno il modulo automaticamente function onOpen() { // la funzione crea un menu aggiuntivo nell'interfaccio grafica di moduli, da cui sarà possibile gestire tutta la procedura var ui = FormApp.getUi(); ui.createAddonMenu().addItem('Imposta inizio e fine compilazione', 'impostaInizioFine').addToUi(); } function impostaInizioFine() { // funzione principale, avviata dal menu Componenti aggiuntivi var ui = FormApp.getUi(); var regexData = new RegExp(/^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/); var regexOra = new RegExp(/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/); // viene chiesto all'utente se vuole impostare data di inizio compilazione // diversamente, si passa alla richeista di impostazione di fine compilazione var impostaInizio = ui.alert(`Vuoi impostare una data e ora di inizio compilazione? Scegli SÌ per impostarle, NO per proseguire con il passaggio successivo.`, ui.ButtonSet.YES_NO); if (impostaInizio == ui.Button.YES) { var dataInizio = acquisisciDataOra(ui, `Inserisci la data di inizio compilazione. Rispetta il formato gg/mm/aaaa, ad es 15/12/2020.`, regexData); var oraInizio = acquisisciDataOra(ui, `Inserisci l'ora di inizio compilazione. Rispetta il formato hh:mm, ad es 10:30.`, regexOra); var inizio = new Date (dataInizio.split(dataInizio.charAt(dataInizio.length - 5)).map(x => normalizzaDataOra(x)).reverse().join('-') + 'T' + oraInizio.split(':').map(x => normalizzaDataOra(x)).join(':')); } var impostaFine = ui.alert(`Vuoi impostare una data e ora di fine compilazione? Scegli SÌ per impostarle, NO per proseguire con il passaggio successivo.`, ui.ButtonSet.YES_NO); if (impostaFine == ui.Button.YES) { var dataFine = acquisisciDataOra(ui, `Inserisci la data di fine compilazione. Rispetta il formato gg/mm/aaaa, ad es 15/12/2020.`, regexData); var oraFine = acquisisciDataOra(ui, `Inserisci l'ora di fine compilazione. Rispetta il formato hh:mm, ad es 10:30.`, regexOra); var fine = new Date (dataFine.split(dataFine.charAt(dataFine.length - 5)).map(x => normalizzaDataOra(x)).reverse().join('-') + 'T' + oraFine.split(':').map(x => normalizzaDataOra(x)).join(':')); } if ((inizio) & (fine) & (fine <= inizio)) { ui.alert(`Hai inserito un termine della compilazione precedente o uguale all'inizio della compilazione. Rivedi i dati inseriti, quindi potrai proseguire.`); // impostaInizioFine(); return; } var stringaProcedi = ''; if (inizio) { stringaProcedi += `Hai selezionato l'inizio della compilazione per le ore ${oraInizio} del ${dataInizio}: il modulo verrà ora chiuso, e riaperto al momento stabilito.`; } else { stringaProcedi += `Non hai selezionato un inizio della compilazionem il modulo resterà compilabile o meno già da ora in base all'impostazione manuale che darai.`; } if (fine) { stringaProcedi += `Hai selezionato la fine della compilazione per le ore ${oraFine} del ${dataFine}: il modulo verrà chiuso automaticamente in quel momento.`; } else { stringaProcedi += `Non hai selezionato una fine per la compilazione del modulo: continuerà ad accettare risposte fino ad un tuo intervento manuale.`; } stringaProcedi += `Se questi dati sono corretti, clicca OK per procedere, altrimenti scegli ANNULLA. Nota che procedendo verranno eliminati gli eventuali attivatori precedentemente associati allo script.`; var procedi = ui.alert(stringaProcedi, ui.ButtonSet.OK_CANCEL); // se premuto Annulla, termina lo script if (procedi == ui.Button.CANCEL) { return; } // se premuto Ok, elimina i trigger precedentemente impostati var triggers = ScriptApp.getProjectTriggers(); for (var i = 0; i < triggers.length; i++) { ScriptApp.deleteTrigger(triggers[i]); } // imposta trigger di inizio compilazione, se impostata if (inizio) { // disattiva compilazione da questo momento disattivaCompilazione(); // imposta trigger per inizio compilazione ScriptApp.newTrigger('attivaCompilazione') .timeBased() .at(inizio) .inTimezone('Europe/Rome') .create(); } // imposta trigger di fine compilazione, se impostata if (fine) { ScriptApp.newTrigger('disattivaCompilazione') .timeBased() .at(fine) .inTimezone('Europe/Rome') .create(); } } // --------- funzioni ausiliarie // acquisisce risposta dal prompt, e verifica la corrispondenza del formato data/ora // se non corrisponde, avvisa l'utente e ripete la richiesta function acquisisciDataOra(ui, promptText, regex) { var response = ui.prompt(promptText).getResponseText(); if (!regex.test(response)) { ui.alert(`Errore nell'inserimento dei dati. Premi OK e riprova.`); response = acquisisciDataOra(ui, promptText, regex); } return response; } // aggiunge lo 0 se mancante in ora, giorno e mese function normalizzaDataOra(x) { if (x.length == 1) { x = "0" + x; } return x; } function attivaCompilazione() { var form = FormApp.getActiveForm(); form.setAcceptingResponses(true); } function disattivaCompilazione() { var form = FormApp.getActiveForm(); form.setAcceptingResponses(false); }
Ho provato lo script, ho impostato la data e l’ora di inizio e fine, ha modificato l’accettazione delle risposte, però non ha dato la possibilità di rispondere nell’intervallo di tempo inserito.
ciao Mario, quale errore o messaggio di preciso? sembrerebbe più un problema di impostazioni del modulo che dello script. con quale account hai provato ad inviare le risposte? controlla che nelle impostazioni sia tutto ok per quanto riguarda limitazione o meno al dominio, limite ad una risposta, ecc.
Daniele, non da nessun errore, ho impostato il modulo libero e senza raccolta di email ed ho lanciato il modulo in una finestra in navigazione in incognito.
Primo problema è che se metto una data di inizio anteriore alla data corrente comunque mi blocca le risposte, secondo problema è che non si attiva il modulo all’ora stabilita, terzo problema è che al termine dell’ora stabilita non si blocca il modulo.
1) è normale, deve funzionare così. per le prove basta impostare un orario di 1-2 minuti avanti rispetto al momento in cui si imposta e funziona, oppure non impostare l’inizio. 2 e 3) probabilmente solo un problema di fuso orario; spesso i progetti di apps script partono con fuso orario New York. di conseguenza gli attivatori ci sono e funzionano, ma a diverse ore di distanza per questa questione. nel nuovo editor non c’è attualmente modo di modificarlo, quindi per ora bisogna tornare indietro momentaneamente al vecchio editor (tasto apposito in alto a destra), selezionare File > Proprietà del progetto, quindi nella prima scheda Informazioni selezionare il fuso orario giusto e salvare. a questo punto si può anche tornare al nuovo editor. le operazioni di impostazione andranno ripetute, quindi dovrebbe funzionare tutto
Grazie Daniele, ha funzionato cambiando il fuso orario.
Potresti aggiungere che venga automaticamente inviato il modulo delle scelte effettuate fino a quel momento quando arriva la scadenza impostata?
Sarebbe molto importante.
Scusa Daniele, ma anche la visualizzazione del tempo rimanente sarebbe importante. Potresti aggiungerla?
non ho ben capito i contorni delle richieste:
1. cosa vuoi di preciso che venga inviato e a chi? il riassunto di tutte le risposte? una notifica? l’ultima risposta? il foglio di lavoro che le contiene? e a chi? al proprietario del modulo? al compilatore?
2. chi deve visualizzare il tempo rimanente e dove? il proprietario quando apre il modulo? il compilatore? in questo secondo caso non è possibile, apps script non offre strumenti per agire sull’interfaccia del compilatore, ma solo su quella del proprietario che modifica il modulo originale
Mi spiego meglio. Supponiamo che l’alunno che risponde al modulo abbia 5 minuti di tempo per rispondere a 3 domande, ha risposto alle prime due ed ha selezionato la risposta alla terza domanda, però sta pensandoci e nel frattempo scadono i 5 minuti. Vorrei che allo scadere del tempo a disposizione il modulo venga automaticamente inviato come se l’alunno avesse cliccato su invia, registrando così tutte le sue risposte.
Peccato che non si possa visualizzare il tempo rimanente.
Grazie.
nessuna delle cose che chiedi è possibile da Apps Script in modo nativo. non ci sono metodi e funzioni che agiscono sull’interfaccia utente – cioè sul modulo visualizzato dal compilatore – ma solo sull’interfaccia dell’editor – il proprietario o collaboratore nel momento in cui creano, impostano e modificano il modulo. ci sono componenti aggiuntivi che fanno quello che chiedi, ma necessariamente si appoggiano su servizi esterni: aprono il modulo Google all’interno di una pagina web terza, e su quella pagina gestiscono visualizzazione del tempo rimanente, invio automatico allo scadere del tempo… in questo modo però si apre un capitolo complicato sull’utilizzo dei dati: devi permettere che questi servizi terzi accedano all’account Google di ogni alunno! quindi dovrebbero essere servizi super-fidati, va guardata bene la privacy policy, andrebbe fatta informativa ad hoc; e non potendo tu vedere il codice sorgente, devi proprio fidarti parecchio di quello che fanno. inoltre la gestione del tutto diventa un po’ più laboriosa: ogni utente deve avere account su servizio terzo, accedere, autorizzare…
Mi servirebbe uno script che all’ avvio del modulo (o all’inizio) mi chiede utente e password e ne controlli esistenza su un file (su drive) che si chiama “anagrafica” e che esiste mi riporti dei dati anagrafici nel modulo ….