Body zdarma Java týden
Využij podzimních slev a získej od nás až 40 % bodů zdarma! Více zde
Pouze tento týden sleva až 80 % na Java e-learning!

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

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

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. Budeme pokračovat jeho zpracováním a uložením 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).

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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

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ářů.


 

 

Článek pro vás napsal Jan Hora
Avatar
Jak se ti líbí článek?
3 hlasů
Autor se poslední 4 roky věnuje programování pro Google Suite.
Předchozí článek
Google Apps Script - Získání externích dat - Kurzy ČNB II
Všechny články v sekci
Google API
Aktivity (2)

 

 

Komentáře

Avatar
Erik Šťastný:19. září 14:20

Ty jo to je dost hustý, uvažuju, že ušetřím 50 korun měsíčně za hosting a přepíšu si své scriptíky co něco takového tvoří do téhle Google srandy :)

 
Odpovědět 19. září 14:20
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Hora
Redaktor
Avatar
Jan Hora:20. září 8:41

Určitě doporučuju :-) Dá se s tím dělat milion věcí. A nemusíš pak řešit jak nějaká data prohlížet když jsou v tabulce. Můžeš si je filtrovat, sdílet, exportovat do PDF, dělat grafy. A všechno můžeš dělat podle potřeby ručně nebo skriptem. Prostě krása :-D

 
Odpovědět  +1 20. září 8:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.