Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 7 - Google Apps Script - Získání externích dat - Kurzy ČNB III

V minulé lekci, Google Apps Script - Získání externích dat - Kurzy ČNB II, jsme získali data ze serveru ČNB jako textový řetězec.

Dnes budeme zpracovávat kurzovní lístek a uložíme si ho do tabulky.

Zpracování kurzovního lístku

Data z ČNB v textovém tvaru máme, zkusíme si napsat funkci, která je rozporcuje do tvaru vhodného k uložení do tabulky. Může vypadat například takto:

function porcuj_data(kurzy, datum) {
  var radky = String(kurzy).split('\n'); // rozdělí celý text podle znaku pro nový řádek
  var prvni_radek = String(radky.shift()); // z pole odeber první řádek a pro jistotu ho převeď na text
  var dilky = prvni_radek.split(' '); // rozděl podle mezery, jako první část by mělo být datum kurz. lístku
  if(dilky[0] != datum){ // začátek kurzovního lístku se neshoduje s datem, které potřebujeme
    return false; // funkce nevrátí data, ale hodnotu false
  }
  var radek;
  var arr_vyst = []; // pole na výstupní data
  for(var i = 0;i < radky.length; i++){ // cyklus přes všechny zbývající řádky (první řádek už v poli není)
    radek = String(radky[i]).split('|'); // rozděl řádek na dílky podle znaku |
    if(radek.length == 5){ // kontrola, jestli řádek obsahuje správný počet položek
      arr_vyst.push(radek) // přidej řádek do pole
    }
  }
  return arr_vyst;
}

Většina kódu je asi jasná již z komentářů. Nejprve se zbavíme prvního řádku a zkontrolujeme, jestli je na něm správné datum. Pokud ne, funkce končí a vrátí false. Jinak projdeme zbývající řádky, rozdělíme každý z nich podle znaku '|' a postupně je přidáme do výstupního pole, které funkce vrátí.

Kontrola, jestli je počet dílků pět, je z důvodu, že na konci vráceného textu je prázdný řádek, který po rozdělení bude obsahovat jen jeden dílek a havarovalo by nám vložení dat do tabulky. Obdobně bychom mohli například hlídat délku řádku a řádek s nulovou délkou přeskočit.

Zápis kurzů na list tabulky

Na samotný zápis ani nebudeme samostatnou funkci psát. Napíšeme si rovnou funkci, která provede celou operaci načtení a uložení najednou a bude později volána časovým spouštěčem:

function zpracuj_kurzy() {
  var dnes = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'dd.MM.yyyy'); // dnešní datum v českém tvaru DD.MM.RRRR

  var sheet = zaloz_list(dnes); // založ list, nebo vrať existující
  sheet.clear(); // smaž obsah i formátování

  var kurzy_txt = nacti_data_z_cnb(kurzy_url, dnes); // získej kurzy jako text
  var kurzy = porcuj_data(kurzy_txt, dnes); // rozděl a vrať ve formátu pro vložení do tabulky

  if(kurzy === false) { // na začátku dat není datum dnes
    var range = sheet.getRange(1,1); // vyber buňku A1
    range.setValue('Kurzy nenalezeny'); // zapiš do ní text
  }else{
    var range = sheet.getRange(1,1, kurzy.length, 5); // vyber oblast pro data
    range.setValues(kurzy); // vlož data
    nastav_vzhled(sheet); // upraví vzhled listu
    smaz_prazne_bunky(sheet); // smaž prázdné buňky v tabulce
  }
}

Z komentářů by snad měla být funkčnost jasná, přidáme jen několik poznámek.

Vidíme první použití knihovny Utilities, která nám z javascriptového objektu Date vyrobí řetězec ve tvaru 'DD.MM.RRRR'.

Metoda sheet.clear() vymaže jak data, tak i případné formátování buněk, velikost písma, orámování, podbarvení atd.

Možnosti mazání jsou širší. Lze mazat samostatně data a zachovat formátování metodou clearContents(), smazat formátování a ponechat data pomocí clearFormats(), nebo pomocí clearNotes() smazat poznámky.

Pokud funkce porcuj_data() vrátí false, zapíšeme tuto informaci na list do buňky A1. V případě, že jsou data načtena správně, vložíme je do tabulky příkazem range.setValues(kurzy).

Před vlastním vložením dat je třeba vybrat oblast (range), která musí počtem řádků a sloupců odpovídat množství dat. Jakmile velikost oblasti a dat nesouhlasí, vkládání dat skončí chybou.

Vidíme, že ve funkci se výběr oblasti provádí takto:

var range = sheet.getRange(1, 1, kurzy.length, 5);

čili počet řádků určíme z délky pole kurzy, ale počet sloupců máme natvrdo zadaný. V případě, že by ČNB do kurzovního lístku například přidala další sloupec, skript by nám přestal fungovat.

Podobně, pokud by se v kurzovním lístku vyskytla chyba a na některém řádku byly jen 4 sloupce, vkládání by havarovalo, protože počet sloupců máme nastavený na 5.

Ještě si ukážeme funkce nastav_vzhled() a smaz_prazne_bunky(), o kterých jsme zatím nemluvili a které se volají po vložení dat.

nastav_vzhled()

Po funkci nastav_vzhled() budeme chtít zvýraznit první řádek, nastavit šířku sloupců a pár dalších drobností. Možnosti formátování jsou samozřejmě daleko větší. V podstatě cokoliv, co lze v tabulce nastavit ručně, je možné nastavit i pomocí skriptu. Naše funkce by mohla vypadat třeba takto:

function nastav_vzhled(sheet) {
  sheet.autoResizeColumns(1, 5); // přizpůsobí šířku sloupců A - E aktuálnímu obsahu
  sheet.setFrozenRows(1); // první řádek zůstane na místě při rolování tabulkou
  var range = sheet.getRange(1, 1, 1, 5); // vyber oblast hlavičky
  range.setBackground('#cccccc'); // nastav hlavičce světle šedé pozadí
  range.setFontWeight("bold"); // nastav hlavičce tučné písmo
}

Funkčnost je asi jasná z komentářů, případně si funkci upravte a vyzkoušejte další možnosti formátování.

smaz_prazne_bunky()

A ještě si ukážeme funkci smaz_prazne_bunky().

Každý nově založený list tabulky má sloupce A - Z a 1000 řádků. Další sloupce i řádky je samozřejmě možné celkem libovolně přidávat. Limitovaní jsme pouze celkovým počtem buněk tabulky, který je momentálně 5 milionů.

Do tohoto limitu se samozřejmě naše skladování kurzů bez problémů vejde, ale pokud budete uvažovat o větší aplikaci v Google Suite, která bude pro ukládání dat využívat tabulky, je dobré o limitu vědět.

S tím souvisí i to, co by měla dělat naše funkce. Pokud víme, že na listu více dat prostě nebude, můžeme nevyužité sloupce a řádky vymazat. Jen musíme dát pozor, abychom nemazali i místa, kde máme data. Funkce může vypadat třeba takto:

function smaz_prazne_bunky(sheet) {
  var data_range = sheet.getDataRange(); // vyber oblast dat
  var posl_radek = data_range.getLastRow(); // číslo posledního řádku
  var posl_sloupec = data_range.getLastColumn(); // číslo posledního sloupce
  var smaz_radku = sheet.getMaxRows() - posl_radek - 1; // kolik řádků smazat
  var smaz_sloupcu = sheet.getMaxColumns() - posl_sloupec - 1; // kolik sloupců smazat
  if(smaz_radku > 0){ // je co mazat?
    sheet.deleteRows(posl_radek + 1, smaz_radku);
  }
  if(smaz_sloupcu > 0){ // je co mazat?
    sheet.deleteColumns(posl_sloupec + 1, smaz_sloupcu);
  }
}

Abychom nesmazali žádná data nám pomůže zajistit metoda sheet.getDataRange(). Ta vybere kompletní oblast obsahující data. Nezáleží na tom, jestli jsou v datech prázdné řádky nebo sloupce, tato metoda vždy vrátí oblast, ve které jsou všechny buňky obsahující nějakou hodnotu.

A pozor, levý horní roh oblasti vždy začíná buňkou A1, i kdyby byla první data třeba až ve sloupci F.

Pak využijeme metody sheet.getMaxRows() a sheet.getMaxColumns(), které vrací celkový počet řádků a sloupců na listu a spočteme si kolik sloupců a řádků je třeba smazat. Počty o jeden snížíme, takže vpravo by nám měl zůstat jeden volný sloupec a dole jeden volný řádek.

Podmínky testující počet řádků a sloupců ke smazání potřebujeme pro případy, kdy funkci pro daný list zavoláme opakovaně. První volání řádky a sloupce smaže a při druhém volání by se skript pokoušel odstranit 0 řádků a 0 sloupců a havaroval by.

No a máme hotovo. Zkuste si funkci zpracuj_kurzy() několikrát spustit a v tabulce se přesvědčte, jestli se kurzy správně ukládají. Můžete list s dnešním datem smazat a funkci znovu spustit. Pokud je vše v pořádku, měl by se list znovu vytvořit a naplnit daty.

Časový spouštěč

Na závěr založíme časový spouštěč, který bude funkci zpracuj_kurzy() spouštět každý den, řekněme v 16:00. Z menu vybereme volbu Upravit -> Spouštěče aktuálního projektu a vpravo dole klikneme na tlačítko Přidat spouštěč.

Postup jsme již probrali v lekci o spouštěčích.

V panelu nastavíme parametry podle následujícího obrázku a vytvoříme spouštěč:

Vytvoření spouštěče v Google Apps Script - Google API

Samozřejmě, že pro otestování spouštěče není třeba čekat do druhého dne. Jednoduše si vytvořte spouštěč, který poběží každou minutu, a po otestování zda vše funguje mu nastavte interval jedenkrát denně.

Líbí se vám Apps Script a tento seriál?
A dočetli jste až do konce?
Pak nezapomeňte na hodnocení ;-)

A na závěr malý domácí úkol. Tipněte si, co se zapíše do tabulky o víkendu, kdy se kurzy nevyhlašují, a napište to do komentářů.


 

Předchozí článek
Google Apps Script - Získání externích dat - Kurzy ČNB II
Všechny články v sekci
Google API
Článek pro vás napsal Jan Hora
Avatar
Uživatelské hodnocení:
7 hlasů
Autor se poslední 4 roky věnuje programování pro Google Suite.
Aktivity