[JavaScript] Calcola il percorso più breve tra due punti su una griglia

Vediamo oggi come creare in JavaScript una griglia sulla quale posizionare due punti e trovare il percorso più breve evitando degli ostacoli.

A titolo di curiosità ho svolto un esercizio simile (ma senza l’uso di Nodi) in Python: [python] Esercizio su funzioni ricorsive e calcolo del percorso minore possibile

Il risultato che vogliamo ottenere sarà simile a questo (avere la possibilità di impostare una dimensione e il numero di ostacoli). Versione semplice:

Versione un po’ più complicata:

Questo esercizio è consultabile anche al seguente link.

Procediamo con ordine e andiamo anzitutto a creare una classe per gestire le singole celle e quelle ad esse collegate. Vogliamo creare un sistema collegato a nodi, che rappresenti la connessione tra tutte le celle. Definiamo perciò una classe nel modo seguente:

In particolare voglio mettere in evidenza il metodo addVicino(nodo)

Vogliamo che ogni nodo sia interconnesso con il proprio vicino, quindi se abbiamo due nodi A e B allora A avrà nei vicini B e B avrà nei vicini A.

Costruiamo adesso la classe che creerà la mappa. Nel codice ho inserito i commenti ai vari metodi:

In particolare vorrei soffermarmi sul controllo dei vicini con il metodo nMaxVicini(nodo,percorso)

Durante la ricerca del percorso voglio evitare tutti quei percorsi che si annodano a serpentina, perché tanto non sarebbero mai il percorso migliore. Se un percorso è così annodato, significa che esiste un nodo che ha almeno 3 vicini, durante la costruzione almeno 2 (ricordiamoci che il nodo successivo non è stato ancora aggiunto). Quindi ogni nodo, durante la costruzione, non deve avere più di un vicino.

Completiamo il tutto con la creazione della griglia vera e propria:

E naturalmente con un po’ di CSS:

E infine la pagina HTML per mettere il tutto insieme.

Vediamo infine un esempio funzionante del codice.

Vedi articolo

[JavaScript] Esercizio per realizzare il gioco del campo minato

Vediamo come realizzare un prototipo del gioco del campo minato, ideato da Robert Donner e Curt Johnson e pubblicato nel 1990 nella raccolta Microsoft Entertainment Pack 1 per Windows 3.1. Negli anni successivi il gioco divenne famoso anche con il nome Prato Fiorito.

Il gioco si basa sullo scoprire le mine nascoste nel campo, quando si scopre una cella che non contiene mine questa può essere vuota, oppure avere un numero che ci indica quante mine limitrofe sono presenti. Il risultato che vogliamo ottenere sarà simile a questo:

Per questo esercizio ho utilizzato il font Digital Counter 7, sviluppato da Sizenko Alexander

Anzitutto abbiamo bisogno di creare lo spazio per il nostro gioco. Creiamo quindi una pagina HTML come nel codice seguente:

Ogni cella del gioco dovrà contenere 4 proprietà diverse:

  1. indicatore se c’è o meno una mina
  2. indicatore se la cella sia o meno aperta
  3. il conteggio delle mine limitrofe
  4. indicatore se è stata messa o meno una bandierina

Faccio notare come i punti 3 e 1 possono essere riassunti in un’unica variabile, all’occorenza.

Creiamo quindi anzitutto un oggetto opportuno nel modo seguente:

Dentro a $(document).ready(function() {}); andiamo ad inizializzare il resto del gioco come segue.

Anzitutto popoliamo il nostro campo di celle:

Andiamo poi a distribuire tutte le mine, in base al numero prescelto.

Costruiamo ora una funzione ricorsiva per il controllo delle mine medesime.

Aggiungiamo anche una funzione per quando il gioco sarà finito e vorremo visualizzare tutte le mine:

A questo punto aggiungiamo una funzione per consentire il click sulle singole caselle:

E una per aggiungere le bandierine:

Il file JavaScript nel suo complesso sarà simile al seguente:

Affinché il tutto funzioni abbiamo bisogno anche di un po’ di CSS:

E il gioco è fatto.

Qui è possibile trovare una versione funzionante del gioco (con qualche aggiunta extra).

Vedi articolo

[javascript] Uncaught TypeError: Cannot read property ‘msie’ of undefined

Dalla versione jQuery 1.9 alcune funzionalità sono state deprecate, tra le quali anche quella di $.browser. Questo pò produrre errori come: Uncaught TypeError: Cannot read property 'msie' of undefined

Per risolvere il problema è sufficiente aggiungere la seguente istruzione dopo aver importato jQuery:

 

Vedi articolo

Simulazione sull’espansione del contagio da Coronavirus (COVID-19)

Se stai cercando informazioni sul Coronavirus (COVID-19) ti raccomando di visitare i seguenti siti ufficiali:

Informazioni sul Coronavirus in Italia (Ministero della Salute)

Informazioni sul Coronavirus nel mondo (Organizzazione Mondiale della Sanità)

Panoramica delle condizioni del Coronavirus (Organizzazione Mondiale della Sanità)

Domande e risposte sul Coronavirus (Organizzazione Mondiale della Sanità)

Io non sono un medico e il presente articolo è stato ispirato da quello pubblicato sul The Whashington Post: Why outbreaks like coronavirus spread exponentially, and how to “flatten the curve” 

Quello che mi interessa in questa sede è dare uno spunto di programmazione a tutti quelli che, come me, ora sono chiusi in casa ed hanno voglia di ingannare il tempo con qualcosa di diverso dal solito (insomma, buttandosi a fare un po’ di programmazione!).

Spero che questo sia anche un ottimo esempio del perché, in questo momento, dobbiamo fare di tutto per restare il più possibile a casa ed evitare il contatto con gli altri, per la nostra e la loro salute, anche se sono nostri familiari o amici.

Fatte queste premesse arriviamo a noi: quello che vogliamo fare è costruire un simulatore, similmente a quanto dimostrato dal The Whashington Post, su come si possa espandere un’epidemia e quanto sia utile ridurre al minimo l’interazione tra i vari membri della popolazione.

Il simulatore è costruito interamente in JavaScript utilizzando l’elemento canvas del HTML5.

La versione interattiva del simulatore, realizzato come illustrato nell’articolo, si trova in fondo all’articolo

Quello che vogliamo costruire è un simulatore come questo di seguito:

I parametri in input che vogliamo passare al simulatore saranno:

  1. la popolazione totale (800 nel mio caso)
  2. il numero di malati iniziali (ne basta anche solo 1)
  3. il numero di quelli che restano fermi
  4. il tempo di guarigione in millisecondi (3000 nel mio caso)

Giocando un po’ con il simulatore ci accorgeremo subito del perché restare a casa è in questo momento fondamentale.

Partendo dai parametri precedenti e impostando a 0 il numero di quelli fermi otterremo una curva simile alla seguente:

In questo caso il contagio ha raggiunto un picco massimo del 81% della popolazione, infettando tutti quanti alla fine della simulazione. Nella realtà questo picco rappresenta il massimo impatto sul sistema sanitario, che nella realtà sarebbe al collasso se dovesse avvenire qualcosa di simile.

Se aumentiamo il numero della popolazione che sta ferma (200 individui, ovvero il 25%) abbiamo una curva simile alla seguente:

Notiamo che il picco massimo è sceso leggermente, arrivando al 68%, ma restando comunque molto alto.

Attuando misure più restrittive e fermando il 75% della popolazione, ossia 600 individui su 800, avremo una curva come la seguente:

Il picco si è dimezzato in questo caso, arrivando ad un massimo del 39%. Con misure ancora più restrittive, arrivando a fermare 700 individui, quindi l’87,5% della popolazione, si arriva a picchi ancora inferiori, ma non inesistenti (si parla del 21%):

Questo modello rappresenta, sebbene in linea di massima, molto bene la situazione attuale. Le misure restrittive servono principalmente per evitare il collasso del sistema sanitario e dare la possibilità ai medici di occuparsi di tutti quanti i pazienti più gravi, cosa che in caso contrario sarebbe impossibile. Il contagio allungherà così la sua presenza nel tempo, ma verrà anche abbattuto il suo impatto sulla società.

Inutile dire come questa simulazione sia molto approssimativa e non tiene conto di altri fattori, tra il quale anche il decesso dei malati.

Detto tutto questo arriviamo al codice vero e proprio. Anzitutto creiamo l’interfaccia in HTML nel modo seguente:

Procediamo adesso con il codice in JavaScript, che riporto di seguito con i commenti all’interno del codice:

Infine riporto di seguito l’esempio funzionante, per chiunque lo volesse testare al volo (inserisci i parametri e premi INIZIA):

Popolazione Malati iniziali Fermi T. guarigione

Con un po’ di pazienza e qualche altro accorgimento (per esempio che i pallini non possano essere generati fuori dalle pareti) si può implementare la simulazione per avere anche diverse zone isolate.In questo caso notiamo come una zona isolata aiuti ulteriormente a ridurre il numero di contagiati e mantenere anche parte della popolazione sana, benché nessuno stia fermo.

Per costruire la zona isolata possiamo predisporre le pareti nel modo seguente:

Dobbiamo inoltre prendere qualche altro accorgimento, ma questo lo lascio per chi ha voglia di provarci per conto proprio. 🙂

Vedi articolo

[javascript] Realizzare un gioco di carte tipo Memory utilizzando jQuery

Obiettivo: realizzare un semplice gioco di carte tipo Memory, utilizzando JavaScript e il framework jQuery.

Per chi non conoscesse il Memory, il gioco consiste nel cercare di indovinare le coppie di carte uguali. All’inizio possono venir mostrate tutte le carte (se vogliamo dare un’aiuto iniziale) che poi vengono coperte; a quel punto si tirano su due carte per volta per vedere se sono uguali: se lo sono le lasciamo scoperte, altrimenti le ricopriamo e procediamo col sollevare un’altra coppia e così via.

La versione giocabile del gioco, realizzato come illustrato nell’articolo, si trova in fondo all’articolo

Il gioco può essere elaborato in diverse varianti, a fini di questo semplice esercizio prendiamo in considerazione le seguenti regole:

  1. Al primo turno vengono mostrate per un attimo tutte le carte, dopodiché vengono nascoste
  2. Quando il giocatore solleva due carte uguali queste vengono lasciate scoperte e vengono assegnati dei punti
  3. Se le carte non sono uguali le ricopriamo nuovamente
  4. Per ogni coppia di carte scoperte assegniamo dei punti, determinati anche in base allo scorrere del tempo (prima si scoprono e più punti si guadagnano); diamo un punteggio maggiorato se le carte vengono trovate uguali in sequenza
  5. Una volta che tutte le carte sono state scoperte il gioco finisce

Prima di procedere oltre nello sviluppo del programma vediamo di cosa avremo bisogno (e cosa ho utilizzato):

Detto questo il risultato che vogliamo ottenere sarà simile a questo qua:

Costruiamo adesso l’idea del programma, che andremo a sviluppare come una singola classe in JavaScript che conterrà tutte le varie funzioni.

Il funzionamento lo potremmo riassumere in questo modo:

Cominciamo quindi costruendo la nostra pagina in HTML che conterrà lo script, per farla utilizziamo il prototipo base di Bootstrap nel modo seguente:

Alla riga 15 abbiamo il pezzo di codice che riguarda il contenitore del gioco, nel mio caso un div. Questa parte si ricollega a quella direttamente utilizzata nel javascript, nel file carte.js.

Affinché la classe funzioni in questo modo dobbiamo far sì che il costruttore accetti per argomento un dizionario e lo utilizzi per parametrizzare le opzioni dell’oggetto. Cominciamo quindi costruendo anche la nostra classe nel modo seguente:

Nel nostro costruttore dichiareremo le impostazioni come una variabile globale this.impostazioni = {}. Faccio notare che, a differenza di altri linguaggi di programmazione, le variabili (eccettuati i casi dei getter e dei setter) non possono essere dichiarate a livello di classe, ma esclusivamente dentro i metodi. Il prefisso this fa sì che la variabile sia globale, sebbene con alcune specifiche eccezioni che vedremo.

Implementiamo ulteriormente la classe nel modo seguente:

Per far sì che le impostazioni dell’utente si sovrappongano alle impostazioni predefinite utilizziamo l’istruzione this.impostazioni = Object.assign({},this.impostazioni,impostazioni). In questo modo uniamo i due dizionari in un nuovo dizionario vuoto e trascriviamo tutto su this.impostazioni. In questo caso è molto importante l’ordine, difatti this.impostazioni viene assegnato prima di impostazioni, dizionario che contiene la parametrizzazione a livello utente. Così le nuove impostazioni andranno a sovrascrivere quelle precedenti, creando il dizionario definitivo delle impostazioni.

Adesso andiamo a creare il metodo di caricamento nella maniera seguente:

Qui stiamo utilizzando due metodi che non abbiamo ancora dichiarato, ovvero this.creazioneStile() e this.creazioneHome(). Con this.contenitore = $(this.impostazioni.contenitore); intercettiamo il contenitore predefinito in precedenza e applichiamo, successivamente gli stili di base. Avrei potuto utilizzare anche un file CSS separato per la parametrizzazione degli stili, ma allo scopo di esercizio ho preferito fare tutto tramite JavaScript all’interno della classe stessa.

Delle istruzioni precedenti è molto importante passare l’opzione this.contenitore.css("position", "relative"); che definirà la posizione del contenitore come relativa. In questo modo potremo utilizzare internamente i riferimenti assoluti per posizionare i vari elementi. Senza la dichiarazione di posizione relativa in modo esplicito, gli elementi interni si sarebbero posizionati rispetto al primo oggetto genitore del contenitore che abbia una posizione dichiarata esplicitamente.

Per il metodo this.creazioneStile() procediamo nel modo seguente:

Sostanzialmente creiamo una sezione <style></style> all’interno del codice dentro la quale andremo ad aggiungere tutti gli stili. Per evitare sovrapposizioni esterne al contenitore anteponiamo ad ogni stile il descrittore in CSS del contenitore con this.impostazioni.contenitore. Infine aggiungiamo il gruppo di stile nell’intestazione con l’istruzione $('html > head').append(stile);

Dentro questo metodo procederemo ad aggiungere via via i vari stili di cui abbiamo bisogno.

Per il metodo this.creazioneHome() procediamo aggiungendo la seguente porzione di codice:

In questo metodo andremo a creare this.creazioneGioco() che verrà richiamato al click su START nella schermata di inizio. Quello che mi interessa in particolare durante questo passaggio è l’utilizzo di this. All’interno dell’evento click this si riferisce all’elemento oggetto del click. Di conseguenza non è più utilizzabile per riferirsi agli oggetti della classe. Per poterlo utilizzare dobbiamo riassegnarlo ad una variabile locale nel metodo genitore, come per esempio var questo = this;

In questo modo dentro l’evento di click potremo utilizzare l’istruzione questo.creazioneGioco(); che richiama un metodo della classe medesima (che dobbiamo ancora creare).

Per la creazione del gioco procediamo nel modo seguente:

Siccome il gioco potrà essere creato diverse volte, per esempio quando si riavvia durante la partita, oppure dopo che si è vinto, ci dobbiamo assicurare che tutte le variabili di gioco vengano inizializzate, ed eventualmente reimpostate, qui.

I metodi che mi interessano in particolare sono:

  1. this.carte = $.merge($.merge([], this.impostazioni.immagini), this.impostazioni.immagini); che ci consente di creare le 16 carte di cui avremo bisogno. Ricordiamoci che le carte sono in coppie quindi le 8 carte iniziali dovranno essere duplicate. Per farlo voglio unire lo stesso dizionario, dentro this.impostazioni.immagini, a se medesimo. Affinché la funzione $.merge non crei un puntatore sul vettore, continuando ad aggiungere le solite immagini ad ogni riavvio successivo e quindi scombinando il gioco, bisogna usare il trucco di chiamare il metodo con un vettore vuoto a cui viene accodato il vettore originale, con l’istruzione $.merge([], this.impostazioni.immagini). Adesso abbiamo creato un vettore completamente nuovo, che potremo poi accodare al solito vettore di prima ripetendo il passaggio una seconda volta. Se non si procede in questo modo al primo riavvio del gioco si rischieranno di avere 3 o 4 carte dello stesso tipo, perché in totale non saranno più 16 ma 32, poi 48 ecc.
  2. this.carte.sort(() => Math.random() - 0.5); che ci permette di ordinare casualmente le carte. Non è un metodo particolarmente efficiente e non produce nemmeno un livello di casualità particolarmente affidabile. Per generare una password non sarebbe quindi molto opportuno, ma per gli scopi che ci servono ai fini del gioco va benissimo, specialmente per la sua brevità di scrittura. Questa scrittura è anche la medesima di this.carte.sort(function(){ return Math.random() - 0.5; });
  3. $('#combo'+this.impostazioni.idunivoco).hide(); che nasconde il contenitore delle combo (poi vedremo meglio)
  4. for(var i = 0; i < 16; i++ ) this.creaCarta(i); che inserisce le carte nell’ordine casuale determinato dal primo punto

Procediamo adesso con la creazione del menu utilizzando this.creazioneMenu();

Faccio notare che il metodo di “restart” è praticamente identico al metodo che abbiamo visto per lo “start” nella home. Stessa procedura. Nel menu abbiamo aggiunto una voce per il punteggio corrente, una per il tempo trascorso e il tasto che consenta di ricominciare.

La creazione del timer implicherà due diversi passaggi, nella maniera seguente:

Il metodo contatoreTimer() si richiamerà su se stesso ogni 500 millisecondi su se stessa, aggiornando lo stato del gioco e dichiarando infine la conclusione dello stesso. In tale contesto andremo anche a calcolare il tempo trascorso e ad aggiornarlo nella visualizzazione.

Arriviamo adesso alla parte più importante, quella dove creiamo le carte e definiamo il funzionamento del gioco. Ricordiamoci che ogni carta dovrà essere cliccabile.

Per gestire la rotazione delle carte stiamo utilizzando jQuery Flip, che ci permette sostanzialmente di ruotare gli elementi sia manualmente che ad ogni click.

Per ogni carta, procedendo in ordine, definiamo quindi le singole proprietà di CSS e attribuiamo la caratteristica flip. Dopodiché al click su ogni carta procediamo con l’impostazione della struttura di gioco. Anzitutto verifichiamo che il gioco sia iniziato e che la carta sia cliccabile. Se la carta è giocabile e non è ancora stata aperta, apriamola con $(this).flip(false). Leggiamo il nome della carta con var cartagiocata = $(this).attr('data-nome'). Se la carta attuale non è ancora stata impostata, allora impostiamola e blocchiamo la carta con $(this).attr('data-giocabile',0). In caso contrario vuol dire che abbiamo già aperto una carta e quindi dobbiamo verificare se il risultato sia corretto o meno. Se la carta attuale è uguale a quella giocata allora vuol dire che è tutto corretto; blocchiamo quindi la carta, aumentiamo il conteggio delle carte aperte consecutivamente con questo.consecutivi++, incrementiamo il punteggio con questo.incrementaPunteggio() e conteggiamo il numero totale di carte aperte (8 coppie trovate equivale alla fine del gioco). Se le carte non sono uguali, allora diamo 800 millisecondi all’utente per poterle vedere entrambe e poi richiudiamole e reimpostiamole giocabili.

Nel suo complesso il codice che avremo creato sarà il seguente (ho incluso alcuni altri commenti specifici nel codice, per spiegare i singoli passaggi):

Per chiunque volesse cimentarsi nel gioco ne riporto di seguito anche la versione giocabile. Inutile dire che ci sarebbero ulteriori possibilità di perfezionamento e che nel gioco ci sono anche alcuni bug che accadono quando si clicca troppo rapidamente tra una carta e l’altra.

Facendo un po’ di prove per ora il meglio che sono riuscito a ottenere, senza usare sotterfugi come screenshot e simili, è stato il seguente risultato:

Vedi articolo

[wordpress] Problema video Revolution Slider 6 con Uncaught TypeError: Cannot read property ‘x’ of undefined

Problema: inserendo in Revolution Slider 6 delle slide con video in HTML5 (file mp4 nel caso particolare) lo slider non riesce ad avviarsi e provoca un loop infinito di errori nella console javascript.

Soluzione: l’errore dipende probabilmente da un altro plugin che provoca incompatibilità nel codice. Nel mio caso specifico l’errore era provocato da Enlighter – Customizable Syntax Highlighter. Disattivando il plugin lo slider torna a funzionare.

Nel caso specifico l’errore che si presenta è il seguente.

Uncaught TypeError: Cannot read property 'x' of undefined
at HTMLVideoElement.computePosition (mootools-core-yc.js?ver=3.10.0:4)
at HTMLVideoElement.setPosition (mootools-core-yc.js?ver=3.10.0:4)
at Object.R (revolution.tools.min.js?ver=6.0:46)
at Object.i._initProps (revolution.tools.min.js?ver=6.0:46)
at Object.i._init (revolution.tools.min.js?ver=6.0:46)
at Object.i.render (revolution.tools.min.js?ver=6.0:46)
at Object.i.render (revolution.tools.min.js?ver=6.0:46)
at Object.E._updateRoot.H.render (revolution.tools.min.js?ver=6.0:46)
at Object.i.dispatchEvent (revolution.tools.min.js?ver=6.0:45)
at s (revolution.tools.min.js?ver=6.0:45)

Oltre a cercare di correggere il file revolution.tools.min.js, cosa che sconsiglio caldamente, conviene verificare quali altri plugin stiano utilizzando mootools, perché probabilmente ci sono delle incompatibilità.

Disattivando il plugin in questione lo slider torna a funzionare correttamente.

Vedi articolo

[apps script] Inviare tramite Gmail un’email con allegato da Drive

Questo esempio è la prosecuzione di quanto già visto in [apps script] Inviare tramite Gmail un’email ad un elenco di contatti in Spreadsheet

Voglio apportare solo una piccola modifica al codice per inviare un allegato salvato su Google Drive a tutti i soggetti nella lista. Per i riferimenti di programmazione rimando alla pagina della guida ufficiale.

Per prelevare un file da Google Drive dobbiamo anzitutto ottenere il suo riferimento univoco. Per farlo ci sono diversi modi, nel mio esempio utilizzerò un file pdf come questo qua. Anzitutto lo carico su Drive e poi cliccandoci sopra col destro scelgo Anteprima.

Dal menu in alto a destra seleziono Apri in un’altra finestra.

A questo punto nella barra dell’indirizzo vedrò qualcosa come https://drive.google.com/file/d/1234567890abcdefghijklmnopqrstuvwxyz/view

Copio il codice alfanumerico che ho evidenziato in rosso, che è l’identificativo univoco per ciascun file. Una volta copiato vado a modificare il mio codice nel modo seguente.

In particolare con la prima istruzione aggiunta prelevo il file da Drive, cosa che richiederà dei permessi aggiuntivi.

Mentre con file.getAs(MimeType.PDF) creo il blob del file in formato PDF.

Fatto questo il mio nuovo script invia un’email a ciascun membro della lista con allegato il suddetto file.

Vedi articolo

[apps script] Aggiungere un nuovo foglio a Spreadsheet controllando quelli esistenti

Vediamo come costruire una funzione che ci permetta di creare da apps script un nuovo foglio su spreadsheet ed aggiungerlo a quelli esistenti.

Notiamo che per prendere il riferimento alla cartella esistente utilizziamo:

Il nome del foglio lo vogliamo gestire nel modo seguente: se il nome che stiamo cercando di aggiungere esiste già, allora posponiamo al nome un contatore numerico scritto come (1), (2)… (n). In pratica se esiste già un foglio chiamato Primo Foglio, allora il foglio aggiunto sarà Primo Foglio (1), se esistono entrambi sarà Primo Foglio (2) ecc.

Infine restituiamo il riferimento al foglio appena creato con:

 

Vedi articolo

[apps script] Creiamo una funzione personalizzata che esegua la somma sull’intervallo di uno Spreadsheet

Oggi vediamo come creare una funzione per Spreadsheet con Google Apps Script che permetta di sommare tutti gli elementi di un intervallo passato per argomento, al pari della funzione SUM().

Faccio notare che abbiamo usato parseFloat() su tutti i valori, in modo che se venissero passati valori non numeri la funzione restituirebbe #NUM!.

Una volta inserita la funzione nello script possiamo testarla nel modo seguente:

Vedi articolo

[apps script] Inviare tramite Gmail un’email ad un elenco di contatti in Spreadsheet

Immaginiamo di avere in Spreadsheet un elenco di indirizzi email a cui vogliamo inviare un messaggio personalizzato.

A tale scopo creiamo un nuovo file con un foglio contenente degli indirizzi nel modo seguente:

Adesso creiamo un bottone al quale collegare lo script che andremo a comporre successivamente. Per aggiungere un pulsante nel foglio di calcolo dobbiamo usare un’immagine, a differenza di quanto accadeva in Excel dove si possono inserire pulsanti da interfaccia. All’immagine assoceremo poi uno script.

Per aggiungere un’immagine andiamo su Inserisci > Immagine…

Prendiamo un’immagine dal nostro computer oppure cerchiamola su Google. Dovremmo arrivare ad una situazione come questa:

A questo punto andiamo su Strumenti > Editor di script e aggiungiamo il nostro script.

Con GmailApp.sendEmail() invieremo l’email utilizzando la nostra casella di posta, mentre con Browser.msgBox() lanceremo un messaggio di conferma delle email inviate.

Fatto questo torniamo nello spreadsheet e clicchiamo col destro sull’immagine. Vedremo comparire in alto a destra dei puntini, clicchiamoci sopra per aprire il menù contestuale.

Scegliamo Assegna script… e nella finestra inseriamo il nome della nostra funzione, ovvero InviaEmailAllaLista

Fatto questo possiamo cliccare sul nostro pulsante e testare il nostro nuovo script.

Se abbiamo fatto tutto bene riceveremo un messaggio di conferma.

Vedi articolo