Az e-mailek létrehozása és személyre szabása
Az <a href=”Link to Part 1”>1. részben</a> megnéztük, hogyan kell adatbázist létrehozni, kezelhető formátumúvá átalakítani, és hogyan működik a createDraft függvény. Most ugyanazzal a createDraft függvénnyel dolgozunk, de ahelyett, hogy mi magunk paramétereznénk, ezt az információt automatikusan a korábban létrehozott CSV-fájlból emeljük át.
A teljes kód hozzáférhető az én Github-fiókomban:
https://github.com/istvanerdo/google-script-autodraft/blob/master/code
Piszkozat létrehozása
Létre kell hoznunk egy személyre szabott piszkozatot a felhasználóinknak. Az alkalmazásnak ezt a részét érteni kell, ezért egyenként megyünk végig az egyes sorokon és elmagyarázom, mit is jelentenek. Kezdésként hozzunk létre egy új szkriptfájlt a projektben.
Hozzunk létre egy függvényt, amely 1 argumentummal (adattal) hajtja végre a feladatainkat, nevezzük így: makeDraft:
function makeDraft(data) {
}
A { } kapcsos zárójelek közé el kezdjük beírni a kódunkat (a //-jellel kezdődő sorok az én megjegyzéseim, vagyis amikor én vagy más a kódot olvassa, érteni fogja, mit is csinálnak a bizonyos részek):
Létrehozunk egy változót („adat” elnevezéssel), amely a CSV-fájlunkból veszi át az adatokat. A javascriptben egy pont és egyenként egy új művelet elhelyezésével több művelet gyorsan egymás után is végrehajtható. Most hívjuk a DriveApp-ot, a .getFileById(„xxxxxxxxxx„) segítségével megnyitunk egy fájlt, a .getBlob() segítségével kinyerjük a tartalmát (a blob alapvetően nem más, mint a nyers adat), majd végül ezt a nyers adatot az alábbiakban látható sztringgé (karakterlánccá) konvertáljuk:
//Get file content
var data = DriveApp.getFileById(„xxxxxxxxxx„).getBlob().getDataAsString()
Nekünk a Sheet.csv adataira van szükségünk, szóval kattintsunk a jobb egérgombbal a meghajtó Sheet1.csv fájljára, majd a „Get shareable link” lehetőségre (magyarul: Megosztható link létrehozása), és a link automatikusan a vágólapra kerül. Ezután cseréljük ki a „xxxxxxxxxx” karaktersort a linkkel, és töröljünk a linkből mindent, ami nem az azonosító része. Ne feledkezzünk meg az idézőjelekről, azoknak a helyükön kell maradniuk.
Az ilyen változóban az a legjobb, hogy adatfelvitelkor az alkalmazás az egyenlőségjel utáni összes dolgot elvégzi.
Tipp: A változók megtekintéséhez használjuk a Logger.log(varname) lehetőséget. Jelen esetben: Logger.log(data). Az alkalmazás fentiekben bemutatott lefuttatása után menjünk a View (Nézet) → Logs (Naplók) lehetőségre.
Adataink a következőképpen néznek majd ki:
Probléma adódott: noha láthatóan több adatsor van, az alkalmazásunk nem ismeri fel őket, úgyhogy valahogyan fel kell ismertetnünk vele. Ez így képzelhető el: jelenleg egyetlen adatsorunk van, amely vesszőkkel és sortörésekkel elválasztott értékekből áll. Nekünk mátrixra van szükségünk, úgyhogy először arra utasítjuk az alkalmazást, hogy amikor sortérést lát, vegye új sorként. Így n darab sorunk lesz. A .split() paranccsal létrehozunk egy másik, allRows elnevezésű változót. A sortörés kódja az \n, vagyis ez lesz az argumentumunk.
//Split into lines
var allRows = data.split(„\n”)
Ugyanúgy néz majd ki, mint korábban, de az alkalmazás tudni fogja, hogy az enterek új sorokat jelentenek:
Most pedig meghatározzuk a sablonjainkat. Én most minden egyes sablonomhoz egyetlen tárgyat használok: a saját esetünkben viszont hozzunk létre változót a sablonunkhoz.
var subject = „Please provide feedback”
Az üzenet megírásához bármilyen szövegszerkesztő használható. Az alkalmazás továbbra sem kezeli karakterként az entereket, ezért azt javaslom, először írjunk enterrel, majd cseréljük ki az entereket \n-re. A később személyre szabni kívánt helyeken hagyjunk egyedi szavakat, a példában láthatók is erre javaslatok. Menjünk vissza a szkripthez és határozzuk meg a listát (ez egy sorbarendezett tétellista), majd illesszük be az üzeneteket vesszővel elválasztva. Így:
var messages = [
„1Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„2Hi $name,\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„3Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit LINK. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„4Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”
]
Fontos, hogy sorrendben írjunk: az 1 számmal jelölt sablon legyen az első, a 2 számmal jelölt a második, és így tovább. Ennek majd a következőkben látjuk a jelentőségét.
Az egyes e-mailekben szerepelni fog az adott személy neve, némelyikükben nem lesz link, lesz olyan amelyiknek 1 linkje lesz, a többinek pedig 2. Az egyes üzenetek elejére írott szám mutatja, hogy az alkalmazás melyik sablonokat használta, aminek később, a piszkozatok tesztelésekor lesz hasznos. Nyugodtan töröljük őket, ha biztosak vagyunk benne, hogy minden esetben a megfelelő sablont használja az alkalmazás. Az eredmények a naplóban jelennek meg:
Ezután végig kell mennünk minden soron (ezt a programozási szaknyelv looping-nak nevezi), és minden egyes sorral kezdeni kell valamit. Határozzunk meg egy „i”-változót, amely a 0 értéket veszi fel. Az allRows ismételten ugyanazt hajtja majd végre rajtuk a .map() segítségével. A Map-nak egy függvény() lesz majd az argumentuma. Ez a függvény végrehajtja majd a szükséges feladatokat a következő 2 argumentummal: adatsor és kulcs:
// Loop through all rows
allRows.map(function(line, key) {
})
A kódnak az ebben a szakaszban olvasható többi részét írjuk a { } kapcsos zárójelek közé.
Az első adatsor csak a címeket tartalmazza, úgyhogy a következő írásával megszabadulunk tőle:
if(key === 0) return
Mivel a számítógépek 0-val kezdik a számolást, ezért az első sor lesz a 0. tétel.
Most pedig határozzunk meg még többet a későbbiekben használandó változók közül. Az egyes adatsorok végén lévő enterektől a .trim() segítségével szabadulunk meg. Ezt csupán elővigyázatosságból tesszük. A mátrix befejezéséhez pedig ismét ráengedjük a .split()-et az adatsorokra. Határozzunk meg egy „cell” elnevezésű változót, amely a vesszőnél elválaszott és a végén enter nélküli adatsor-argumentumunkkal lesz egyenlő.
var cell = line.trim().split(„,”)
Most pedig minden egyes oszlopra létrehozunk egy új változót:
var userId = cell[0]
var displayName = cell[1]
var name = cell[2]
var email = cell[3]
var templateNumber = cell[4]
var search = cell[5]
Ellenőrizzük, hogy ezeket a változókat a konkrét esetnek megfelelően módosítottuk-e, és ügyeljünk a számozásra: az első oszlop a 0., a második az 1. és így tovább.
Egy további változóra van még szükségünk, hiszen – amint az a táblázatban is látható – egyszerre rendelkezünk megjelenített névvel és teljes névvel, és a teljes névből (ha van) a keresztnevet szeretnénk használni, ha pedig üres, akkor a megjelenített nevet. Emlékezzünk, hogy a teljes nevet „name”-nek hívtuk, a megjelenített nevet pedig „displayName”-nek.
var hasName = name && name !== „”
Most van egy hasName változónk, amely akkor IGAZ értékű, ha van névváltozója és nem üres.
Ezután írjunk egy logikai kifejezést, amely először ellenőrzi, hogy a hasName IGAZ-e – ebben az esetben szétbontja a nevet (a szóköznél) két szóra: a kereszt- és a vezetéknévre, és a displayName-t a keresztnévre cseréli le. Az alábbi kód utolsó kifejezése a következőképpen működik: a displayName megegyezik a fullName értékével? Ha igen, akkor a fullName[0] értékét veszi (ilyenkor a nevet 2 szóra bontja, ebből az első van a 0. helyen). Ha nem, akkor a displayName értékét veszi.
// Use first name as displayname
if(hasName) {
var fullName = name.split(” „)
displayName = fullName ? fullName[0] : displayName
}
Most a displayName változó a felhasználó keresztneve lesz, ha megadta a teljes nevét, ha nem, akkor a megjelenített neve.
Érdekesség: A Samebug sok kínai felhasználóval rendelkezik, akiknek a teljes neve gyakran ilyesmi: 林长安. Ilyen esetben nincsen szóköz a kereszt- és a vezetéknév között. Kínában bevett szokás, hogy az emberek akkor is teljes nevükön szólítják egymást, amikor kötetlenül beszélgetnek egymással. Kiderült, hogy az alkalmazásunk a kulturális követelményeket is teljesíti azzal, hogy nem választja el a kínai neveket 🙂
A következő lépésben a különös esetekben alkalmazandó kiegészítő feltételeket határozzuk meg.
Ha az adott személynek nincs e-mail címe, ne történjen semmi:
//Return if no email
if(email === „NULL”) return
A fájl végén néha van egy további üres adatsor, amely hibát generálhat – szóval ha nincs felhasználóazonosító (userId), akkor ne tegyen semmit:
//Return if no user ID
if(userId === „”) return
Már majdnem készen van a piszkozatgenerátor!
Emlékszünk ugye, hogyan határoztuk meg valahol még ennek a fejezetnek az elején az e-mailek sablonjait? Most viszont meg is határozzuk a használandó sablont és kicseréljük a következő szavakat: $name és LINK. Létrehozzuk a sablon elnevezésű változót, amely az üzenetlista konkrét tételével egyezik meg. A sablon száma már megvan a templateNumber változóban, de ellenőrizni kell, hogy tényleg számról van-e szó. Ezért tehát megszorozzuk 1-gyel, hiszen a lista számozása 0-val kezdődik és a mi számaink 1-től vannak. Ezután jön a .replace(), amelynek az első argumentuma az, amit le szeretnénk cserélni, a második argumentuma pedig amire az első argumentumot cseréljük. Egyedi tételek cseréléséhez használjunk idézőjelet, minden szó cseréléséhez pedig használjuk a /yourword/g lehetőséget:
//Set and personalise messages
var template = messages[templateNumber * 1 – 1]
.replace(„$name”, displayName)
.replace(/LINK/g, search)
Sikerült végül létrehoznunk az összes változót: e-mail, tárgy és sablon – vagyis már létrehozhatjuk a piszkozatot:
GmailApp.createDraft(email, subject, template) (az argumentumok magyarul: e-mail, tárgy, sablon)
Ellenőrizzük a kód hibamentességét. Ennek a szakasznak a teljes szkriptje pedig itt olvasható:
function makeDraft(data) {
// Get file content
var data = DriveApp.getFileById(„xxxxxxxxxx„).getBlob().getDataAsString()
// Split into lines
var allRows = data.split(„\n”)
var subject = „Please provide feedback”
var messages = [
„1Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„2Hi $name,\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„3Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit LINK. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”,
„4Hi $name,\n\nLorem ipsum dolor sit amet LINK, consectetur adipiscing elit. Fusce sed.\n\nThank you,\nIstvan\n– \nIstvan Erdo\nCustomer Relations @samebug\nhttps://samebug.io”
]
// Loop through all rows
allRows.map(function(line, key) {
if(key === 0) return
var cell = line.split(„,”)
var userId = cell[0]
var displayName = cell[1]
var name = cell[2]
var email = cell[3]
var templateNumber = cell[4]
var search = cell[5]
var hasName = name && name !== „”
// Use first name as displayname
if(hasName) {
var fullName = name.split(” „)
displayName = fullName ? fullName[0] : displayName
}
//Return if no email
if(email === „NULL”) return
//Return if no user ID
if(userId === „”) return
//Set and personalise messages
var template = messages[templateNumber * 1 – 1]
.replace(„$name”, displayName)
.replace(/LINK/g, search)
GmailApp.createDraft(email, subject, template)
})
}
Ha már nincsenek hibák, akkor futtassuk le és nézzük meg az eredményt.
Az eredmény a következő: 4 piszkozat, mindegyik különböző sablonnal, az e-mail tekintetében NULL-értékű személy nem szerepel, minden $name és LINK helyett az adott felhasználó adatai szerepelnek. Ne aggódjunk a nem linkként formázott (aláhúzás, kék betűszín) linkek miatt, az e-mailek kiküldése után a Google automatikusan formázza őket:
Következtetés és a következő lépés
Hosszú utat jártunk be: létrehoztunk egy teljesen automatikus, egyedi piszkozatokat készítő alkalmazást, amely CSV-fájlból nyeri az adatokat. Most pedig jöjjön a befejező rész: <a href=”Link to Part 3”>3. rész</a>. Ebben elvégezzük az alkalmazásunk utolsó simításait, például szkripteket egyesítünk, hogy ne legyen annyi CSV-fájlunk, valamint létrehozunk egy függvényt, amely időbélyegzőt helyez el az adatbázisunkban a Levél elküldve fejlécű oszlopba.