Utilizzando Google Moduli per la didattica, molti insegnanti avvertono la mancanza di alcune funzionalità che permettano di utilizzarli come verifiche digitali: ad esempio la possibilità di impostare ora e data di apertura e chiusura, oppure il tempo massimo per svolgere la prova, magari con un timer che indica il tempo rimasto allo studente. Lo anticipiamo fin da subito: ad oggi molte di queste possibilità non sono opzioni di Google Moduli. Né si possono ottenere, come spesso proponiamo su questo blog, con la programmazione di Apps Script.
Questo perché allo stato attuale tutte le funzioni e i metodi degli script relativi ai moduli agiscono solo sull’interfaccia dell’editor. Modificano cioè la visualizzazione del proprietario o del collaboratore che crea e imposta il modulo. Non agiscono invece sull’interfaccia dell’utente che compila: non è quindi possibile interagire con gli studenti mostrando il tempo rimasto, chiudendo automaticamente il modulo allo scadere, e così via. Possiamo quindi ottenere nativamente o con Apps Script solo alcune delle funzionalità indicate sopra.
Questo articolo offre la procedura definitiva e testata rispetto a quella già proposta in via sperimentale nell’articolo Test – Aprire e chiudere automaticamente modulo Google. Puoi controllare i commenti di quel post per alcune richieste e relative risposte.
I componenti aggiuntivi: vantaggi e avvertenze
I componenti aggiuntivi di Google Moduli offrono spesso qualche modalità di lavoro aggiuntiva che nelle verifiche si può rivelare utile. Bisogna però prestare particolare attenzione in questo caso. Alcuni di essi – FormLimiter, per citare uno dei più famosi – offrono solo alcune opzioni base tra quelle elencate sopra. Agiscono cioè solo sull’interfaccia dell’editor, e semplificano l’impostazione di scenari che si possono raggiungere anche con gli script.
Altri invece – per fare un esempio, Extended Forms – mostrano possibilità più avanzate, ma lo fanno ad una condizione ben precisa. L’utente finale (lo studente nel nostro caso) non apre più direttamente il modulo Google nella pagina nativa; il modulo viene invece aperto all’interno di un’altra pagina web, di proprietà del gestore del componente aggiuntivo. Proprio perchè il modulo viene incorporato in una pagina web diversa, è possibile mostrare al compilatore tutto quello che normalmente è precluso nell’interfaccia utente di Moduli. Questo comporta però – oltre a qualche passaggio più laborioso nell’impostazione – il concedere al componente aggiuntivo l’accesso ai dati dell’account Google. Di conseguenza, dobbiamo avere grande fiducia nello sviluppatore, controllare adeguatamente il trattamento dei dati, e valutare in che modo questo influisce anche sui dati di chi compila (che per noi spesso saranno studenti non maggiorenni) e non solo di chi crea il modulo.
Utilizzare Apps Script
Al di là delle avvertenze particolari appena accennate, in alcuni casi potremmo desiderare di non utilizzare componenti aggiuntivi esterni, anche se fidati. Le stesse funzionalità offerte dai componenti aggiuntivi che non si appoggiano su servizi esterni possono essere facilmente implementate con Apps Script. L’ambiente di programmazione interno e integrato in G Suite implica diversi vantaggi. Primo fra tutti, nel nostro caso, la possibilità di leggere il codice sorgente e sapere esattamente cosa fa. Quando andiamo ad accettare i permessi, se siamo noi ad inserire il codice in Apps Script possiamo controllare di preciso cosa succede, se i dati restano all’interno del dominio o meno, ecc. Aspetto da non sottovalutare in ambito scolastico.
Abbiamo già visto precedentemente come limitare i Moduli Google in base al numero massimo di risposte, utile non tanto in caso di verifiche o test, quanto più per uno scenario di iscrizioni a numero chiuso. Vediamo in questo post una delle funzionalità che può facilmente adattare Google Moduli per le verifiche, o attività analoghe. Impostiamo una data e ora di apertura e di chiusura del modulo. Possiamo decidere di impostare una sola delle due, oppure entrambe: lo script attiverà e disattiverà automaticamente la raccolta delle risposte in base alle impostazioni date.
Apertura e chiusura automatica del modulo
Prima di tutto crea il modulo che vorrai utilizzare, struttura domande e risposte e modifica le impostazioni in base alle tue esigenze. Poi segui le indicazioni qui di seguito: trovi un promemoria veloce e spiegazioni più dettagliate, scegli quelle che preferisci, portano allo stesso risultato.
A. Indicazioni veloci
Se hai già usato Apps Script, ti basta seguire questi passaggi
- 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 prima di sottoporre il modulo agli studenti
B. Percorso dettagliato
Se non hai confidenza con l’ambiente di Apps Script, queste indicazioni riportano lo stesso percorso indicato sopra in maniera più dettagliata:
- vai nel menu in alto a destra, clicca sui 3 pallini verticali, e quindi su Editor di script

- clicca in alto su Progetto senza nome, dai un nome a tua scelta al progetto e clicca su Rinomina

- elimina la funzione vuota che trovi nell’editor
function myFunction...
avendo cura di eliminare anche tutte le parentesi; quindi copia e incolla il codice che trovi più sotto, e salva con l’icona apposita in alto a sinistra - 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 prima di sottoporre il modulo agli studenti
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)
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); }
Se hai domande sul funzionamento, o incontri problemi nell’impostazione o esecuzione dello script, puoi usare i commenti qui sotto.
Salve, ho incollato il codice nell’editor, salvato e avviato l’esecuzione. Mi chiede di rivedere le autorizzazioni e procedo con account del dominio. Al termine dell’esecuzione viene rilevato un errore che riporto:
15:39:37 Notifica Esecuzione avviata
15:39:37 Errore
Exception: Cannot call FormApp.getUi() from this context.
onOpen @ Codice.gs:7
Ovviamente nei componenti aggiuntivi lo script non viene visualizzato. Come posso risolvere? Grazie
dopo aver concesso le autorizzazioni ed essere tornato nella scheda del modulo Google, hai provato ad aggiornare la pagina? dopo dovresti trovare la voce di menu tra i componenti aggiuntivi (icona a forma di puzzle in alto sulla destra)
Ok con l’aggiornamento della pagina del modulo, funziona. Non capisco quell’errore cosa comporti, ho testato lo script su un modulo di prova. Ora lo stesso voglio utilizzarlo su altri moduli, ma non compare in automatico il tasto dei componenti aggiuntivi. Devo ripetere la procedura per ogni modulo o c’è un modo per visualizzare lo script in tutti i moduli che creo? Grazie mille
sull’errore ti ho risposto nell’altro commento, non fa nulla. la procedura va ripetuta per ogni modulo, il tasto dei componenti aggiuntivi con relativo a voce compare solo dopo aver copiato lo script ed eseguito la prima funzione per concedere le autorizzazioni – eventualmente anche aggiornando la pagina del modulo come hai fatto ora. questo è uno script direttamente collegato al modulo, quindi la procedura va ripetuta per ogni modulo in cui vorrai applicarlo
In realtà aggiornando la pagina del modulo, nonostante l’errore nell’editor, l’icona dei componenti aggiuntivi compare e lo script funziona… mi chiedo cosa comporti quell’errore
ecco, ok. quell’errore non comporta nulla. dice solo che dal lato editor non è possibile eseguire tutte le funzioni che invece vanno eseguite direttamente dall’interfaccia di moduli. prova a vedere se tutto funziona, se rilevi altri errori postali e vediamo
Dalla pagina principale di Apps Script vedo che il progetto è collegato ad un contenitore soltanto, ovvero il modulo di prova. Come posso impostare il riconoscimento dello script ad ogni modulo che creo? Non so se proprio questo è legato all’errore alla riga 7. Grazie per la tua professionalità e preziosi consigli.
Scusami puoi ignorare il commento, mi hai già risposto. GRAZIE, tutto utilissimo.
Buongiorno, volendo invece assegnare al modulo google una durata massima di compilazione, senza usare le estensioni per le ragioni illustrate nell’articolo e che io condivido, lavorando con minorenni, come posso fare? Grazie- Attendo
ciao Lorenza, scusa per la risposta molto tardiva. con questo script non si può fare. bisognerebbe scrivere uno script quasi del tutto diverso, e qualcosa si può fare ma non tutto. di preciso a cosa ti serve? se lo scopo è stabilire una durata di compilazione (ad esempio 30 minuti) dal momento in cui l’utente inizia la compilazione del modulo, questo non è possibile, con nessuno script: non è una funzionalità che Google permette di manipolare al momento, in nessun modo. se invece intendi che dal momento in cui imposto la data di apertura lascio una finestra ad es. di 3 giorni per compilare, si potrebbe fare, ma mi sembra che varierebbe molto poco rispetto a quello che già lo script fa ora: anzichè stabilire che chiudo il 20 novembre, stabilisco che chiudo tra 10 giorni, risultato praticamente identico. o chiedi qualcosa di diverso?
Ciao, è possibile far si che il modulo si apra tutti i giorni ad una certa ora e si chiuda ad un’altra? Ho provato a modificare il tuo script con le mie poche conoscenze ma non ci sono riuscito. Inoltre è possibile, che tu sappia, far sic he solo determinate mail rispondano al modulo. Grazie mille per l’attenzione.
ciao Lorenzo. si può, ma va riscritta una discreta parte dello script. se ti va di condividermi lo script come da te modificato – magari via mail – posso darti qualche dritta
Salve avrei bisogno dello stesso script richiesto dal signor Lorenzo. Avete poi sviluppato lo script? E’ possibile averne una copia? Grazie
salve Gelsomino. non, non abbiamo sviluppato nulla in quella direzione, non ho niente di utile da condividere al momento
lo script funziona perfettamente , complimenti
grazie Roberto, mi fa piacere
Salve, avrei bisogno di sapere se è possibile stabilire un numero massimo di risposte e far chiudere automaticamente il modulo.
P.S. Qualcuno sarebbe così gentile da inviarmi lo script necessario laddove dovesse essere possibile.
Grazie
ciao Cristina, il componente aggiuntivo Form Limiter fa quello che chiedi, facile e veloce. ti può andare bene o vuoi script senza passare da componenti aggiuntivi?
Salve Daniele, da un paio di anni utilizzo Form per raccogliere le richieste di partecipazione alle attività nautiche della mia associazione. Avrei la necessità di aprire e chiudere la raccolta dei dati 3 volte a settimana per un lasso di tempo determinato ( es. dalle 10 del mattino alle 20 della stessa giornata ); il modulo dovrebbe aprirsi e chiudersi automaticamente in tre giorni diversi. Cosa suggerisci ?
Grazie
ciao Bruno. si può fare, ma questo approccio andrebbe a modificare in maniera importante la struttura di base dello script. bisognerebbe prevedere un’articolazione molto maggiore della casistica di inserimento di aperture, chiusure e ricorrenza (come nel tuo caso), e prevedere la conseguente articolazione maggiore dei trigger che aprono e chiudono il modulo. con lo script si fa, ma va riscritto quasi completamente, e diventa decisamente più complesso. non sono a conoscenza di questo tipo di funzionalità in un componente aggiuntivo, magari facendo qualche ricerca tra quelli potresti trovare qualcosa che fa al caso tuo