13. GENERÁTOR SESTAV 13.1. Základní informace Generátor sestav je účinný prostředek jazyka COBOL pro vytváření tiskových sestav. Umožňuje uživateli uvést v sekci REPORT SECTION podrobný a přehledný popis výstupní tiskové sestavy a provést v PROCEDURE DIVISION tisk této sestavy pomocí příkazů INITIATE, GENERATE a TERMINATE. Tyto příkazy mají sice z hlediska uživatele velmi jednoduchý formát, znamenají však pro Generátor sestav pokyn k provedení mnoha složitých operací. Každou tiskovou sestavu lze ovšem vytisknout i bez Generátoru sestav pomocí ostatních příkazů jazyka COBOL (především IF, MOVE, ADD, WRITE, GO atd.). Generátor sestav však umožňuje převést těžiště problému z příkazů na popisy a navíc udělá podstatnou část práce za programátora sám automaticky na základě popisů dodaných programátorem. Tím se práce programátora zjednoduší, její objem se podstatně zmenší (neboť odpadne mechanické rozpisování stále týchž algoritmů) a značně se též zmenší nebezpečí logických chyb (neboť k těm dochází daleko častěji v příkazech než v popisech). Uživatel nemusí znát strukturu a logickou stavbu programu vygenerovaného Generátorem sestav a nemusí se o ni nijak zajímat. Nejprve zavedeme některé pojmy, které se budou vyskytovat v následujícím textu: Tiskovou sestavou rozumíme jakoukoliv posloupnost řádků vytisknutých na tiskárně. Generátor sestav dovede mimo přímého výstupu na reálnou tiskárnu též zapisovat vytvořené logické věty i na výstupní médium jiného typu (disk, disketu, magnetickou pásku, atd.). Je pak již záležitostí uživatele, kdy, jak a kolikrát vytiskne tyto logické věty na tiskárně; přitom vytiskne-li uživatel tyto logické věty beze změn (s výjimkou odstranění identifikačního znaku zařazeného klauzulí CODE), bude tvar vytisknutých stránek přesně stejný jako při přímém výstupu na tiskárnu. V této kapitole používáme pro určitost termíny týkající se konečného tvaru tiskové sestavy vytisknuté na tiskárně, mluvíme tedy o "tisku", "řádcích", "posuvu papíru v tiskárně", "přechodu na novou stránku" apod. Přesný smysl těchto termínů u výstupního média jiného typu lze zjistit např. prostudováním funkce příkazu WRITE (viz. 8.7.1.). Ve zdrojovém programu je tisková sestava representována klauzulí RD a k ní příslušnými popisy položek. Veškeré příkazy a klauzule týkající se zpracování určité tiskové sestavy se vždy odkazují k téže klauzuli RD resp. k položkám k ní příslušejícím. Termínem sestava označujeme přesně vzato klauzuli RD a k ní příslušející popisy položek; nehrozí-li však nebezpečí omylu, používáme termín "sestava" i pro vytvářenou tiskovou sestavu. Vztah mezi sestavou (RD) a tiskovou sestavou je tedy analogický ke vztahu mezi souborem (SELECT a FD) a souborem dat. Princip Generátoru sestav je založen na tom, že v běžné tiskové sestavě (např. při statisticko-ekonomických zpracováních) je možno rozlišit jen několik málo typů řádků. Některý typ řádku se v tiskové sestavě vyskytuje jen v jediném "exempláři" (většinou se to týká řádků stojících na začátku nebo na konci celé tiskové sestavy), jiný typ řádku se vyskytuje v jediném "exempláři" na každé stránce (týká se tzv. hlavičky stránky nebo závěru stránky) a další typ řádku (a takových typů bývá obvykle většina) se v tiskové sestavě vyskytuje mnohonásobně, v mnoha "exemplářích". Každý typ řádku takto plní určitou přesně vymezenou funkci a při každém svém výskytu v tiskové sestavě obsahuje vždy týž počet tisknutých položek, přičemž každá z těchto položek má vždy stejné umístění na řádku, stejnou délku, stejný typ, stejnou strukturu a stejný účel; pouze konkrétní obsah těchto položek je v každém "exempláři" řádku jiný. Někdy se v tiskové sestavě opakují nejen řádky určitého typu, ale dokonce i posloupnosti několika řádků; každá taková posloupnost má při každém svém výskytu vždy týž počet řádků (se stejnými rozestupy mezi řádky), přičemž řádky na odpovídajících si místech patří ke stejnému typu v tom smyslu, jak je popsáno výše. Takové posloupnosti řádků se používají především u některých hlaviček nebo součtových řádků apod. Pro každý z těch typů řádků nebo celých posloupností řádků musí uživatel popsat za RD právě jednu položku s číslem úrovně 01 následovanou položkami k ní podřízenými. Popis určité položky s číslem úrovně určuje společný formát i účel těch řádků, které náleží k typu odpovídajícímu této 01. Odpovídá-li 01 (spolu s podřízenými položkami) určitému typu posloupnosti řádků, určují tyto popisy počet řádků každého výskytu takové posloupnosti řádku, rozestupy mezi řádky v posloupnosti a formáty jednotlivých řádků. Termínem skupina sestavy (zkráceně skupina) označujeme položku s číslem úrovně 01 popsanou za RD spolu se všemi položkami k ní podřízenými. Dojde-li k tisku (přesněji říkáme: vytvoření) takovéto skupiny sestavy, vytiskne se řádek (případně posloupnost řádků) s popsaným formátem. Pokud dochází k vytvoření určité skupiny sestavy opakovaně, vytiskne se vždy jeden "exemplář" řádku (resp. posloupnosti řádků) patřící k příslušnému typu. Takto určité skupině sestavy (01) odpovídá v tiskové sestavě několik (vyjímečně žádný, někdy jediný, většinou však mnoho) tzv. vytisknutých skupin sestavy. Pokud nehrozí nebezpečí omylu, používáme termín skupina sestavy (resp. skupina) i pro vytisknutou skupinu sestavy. Celá tisková sestava je pak složena z těchto jednotlivých vytisknutých skupin sestavy. K upřesnění předešlého odstavečku je třeba dodat, že mohou existovat též skupiny sestavy (01), které nejsou určeny k tisku, nýbrž k provedení určitých netiskových akcí, a při jejichž vytváření se žádné řádky nevytisknou. Vztah mezi skupinou sestavy (01) a vytisknutou skupinou sestavy je tedy analogický ke vztahu mezi popisem logické věty souboru (01) a logickou větou souboru dat. Je plně záležitostí uživatele, zda podle plánovaného tvaru chystané tiskové sestavy správně a rozumně rozhodne, které řádky resp. posloupnosti řádků budou téhož typu a které různých typů, a jaký popis skupiny sestavy každému jednotlivému z těchto typů odpovídá. Ve většině případů je však situace zcela samozřejmá a nepřipouští dvojí řešení. V popisu první položky každé skupiny sestavy (tj. s číslem úrovně 01) je povinná klauzule TYPE, která udává účel této skupiny sestavy (a tím též účel řádků, které jí v tiskové sestavě odpovídají). Říkáme též, že klauzule TYPE určuje typ skupiny sestavy. Podrobný popis je uveden v 13.5.1.; zde uvádíme pouze schématické rozdělení typů, jak je potřebujeme v dalším textu: 1) REPORT HEADING (záhlaví sestavy, zkráceně RH). Vytváří se pouze jednou jakožto první skupina celé tiskové sestavy. Bývá zvykem jí věnovat celou první stránku tiskové sestavy, není to však nutné. 2) REPORT FOOTING (závěr sestavy, zkráceně RF). Vytváří se pouze jednou jakožto poslední skupina celé tiskové sestavy. Je možné jí věnovat celou poslední stránku tiskové sestavy, není to však nutné. Skupina RF se většinou vůbec nepopisuje a nepoužívá. 3) PAGE HEADING (záhlaví stránky, zkráceně PH). Vytváří se na každé stránce tiskové sestavy jakožto první skupina na stránce (obvyklá a vždy používaná "hlavička stránky"). 4) PAGE FOOTING (závěr stránky, zkráceně PF). Vytváří se na každé stránce tiskové sestavy jakožto poslední skupina na stránce. Skupina PF se většinou vůbec nepopisuje a nepoužívá, může však být výhodné vytisknout takto na konci každé stránky název celé tiskové sestavy pro rychlejší hledání v tunách papíru běžně obklopujících každého programátora. Používání skupiny PAGE FOOTING však může značně zpomalit tisk sestavy na tiskárně. 5) DETAIL (detailní skupina, zkráceně DE). Označuje základní typ; jedná se o ty skupiny sestavy, z nichž se obvyklá tisková sestava převážně skládá (např. řádek pro jednoho zaměstnance, jeden materiál apod.). Pokud má mít tisková sestava "základní stavební kameny" různých typů, lze popsat i několik různých skupin sestavy (01) typu DETAIL. 6) CONTROL HEADING (řízené záhlaví, zkráceně CH). Tato skupina sestavy se vytváří pouze v případě, že došlo k tzv. řídicí změně, jak říkáme situaci, kdy uživatel změnil hodnotu některé z tzv. řídicích položek (viz klauzuli CONTROL). Skupina CONTROL HEADING za normálních okolností předchází před posloupností skupin typu DETAIL, které všechny mají touž určitou společnou vlastnost; většinou však nebývá vůbec popisována a používána. 7) CONTROL FOOTING (řízený závěr, zkráceně CF). Také tato skupina sestavy se vytváří pouze při řídicí změně. Za normálních okolností zakončuje posloupnost skupin typu DETAIL, které všechny mají touž určitou společnou vlastnost. Skupiny CONTROL FOOTING bývají popisovány a používány téměř vždy, a to především k vytváření dílčích součtů na jednotlivých hierarchických úrovních anebo k vytváření celkových součtů. Skupiny CONTROL FOOTING jsou jedním z nejdůležitějších prostředků Generátoru sestav. Poznámka: V rámci jedné sestavy (RD) smí být každá ze skupin typu RH, PH a PF popsána nejvýše jednou. Skupin typu CH a CF může být popsáno i více, a to pro každou z definovaných řídících položek a dále též pro nejvyšší úroveň zvanou FINAL nejvýše jedna skupina CH a nejvýše jedna skupina CF (viz klauzuli CONTROL). Skupin DE může být popsán libovolný počet. Příklad: Pro ilustraci uvádíme jednu stránku jednoduché tiskové sestavy. Vpravo v závorkách je u každého řádku uveden typ skupiny. SESTAVA *U37* - POCTY DETI STRANKA 005 (PH, 1.řádek) PRACOVNIK ZAVOD STREDISKO POCET DETI (PH, 2.řádek) POCTY DETI PRO ZAVOD 008 (CH ZAVOD) STREDISKO 81 (CH STREDISKO) NOVAK 008 81 3 (DE) POSPISIL 008 81 1 (DE) PROCHAZKA 008 81 1 (DE) SOUCET PRO STREDISKO CISLO 81 6 (CF STREDISKO) STREDISKO 84 (CH STREDISKO) BLAHA 008 84 0 (DE) DANIEL 008 84 12 (DE) POLAK 008 84 1 (DE) SOUCET PRO STREDISKO CISLO 84 13 (CF STREDISKO) SOUCET PRO ZAVOD CISLO 008 19 (CF ZAVOD) POCTY DETI PRO ZAVOD 009 (CH ZAVOD) STREDISKO 92 (CH STREDISKO) DVORAK 009 92 2 (DE) . . . SESTAVA *U37* - POCTY DETI - KONEC STRANKY (PF) Řídicími položkami jsou zde ZAVOD a STREDISKO. Řídicí změna nižší úrovně nastává při změně hodnoty položky STREDISKO, řídící změna vyšší úrovně nastává při změně hodnoty položky ZAVOD. Cobolský program, který by tiskl takovouto sestavu, by mohl vypadat například takto: IDENTIFICATION DIVISION. PROGRAM-ID. DETI. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT VSTUP ASSIGN S-VSTUP. SELECT TISK ASSIGN 'PRN'. DATA DIVISION. FILE SECTION. FD VSTUP. 01 FILLER. 02 PRACOVNIK PIC X(10). 02 ZAVOD PIC XXX. 02 STREDISKO PIC XX. 02 POCET-DETI PIC 99. FD TISK RECORD 42 REPORT JOSEF. REPORT SECTION. RD JOSEF CONTROL ZAVOD STREDISKO PAGE 65 FIRST DETAIL 5 LAST DETAIL 59 FOOTING 63. 01 TYPE PH LINE 1. 02 COLUMN 1 PIC X(26) VALUE 'SESTAVA *U37* - POCTY DETI'. 02 COLUMN 29 PIC X(7) VALUE 'STRANKA'. 02 COLUMN 37 PIC 999 SOURCE PAGE-COUNTER. 02 LINE 3 COLUMN 3 PIC X(37) VALUE 'PRACOVNIK ZAVOD STREDISKO POCET DETI'. 01 TYPE CH ZAVOD LINE PLUS 3. 02 COLUMN 1 PIC X(20) VALUE 'POCTY DETI PRO ZAVOD'. 02 COLUMN 22 PIC XXX SOURCE ZAVOD. 01 TYPE CH STREDISKO LINE PLUS 2 NEXT GROUP PLUS 1. 02 COLUMN 1 PIC X(9) VALUE 'STREDISKO'. 02 COLUMN 11 PIC XX SOURCE STREDISKO. 01 CHLAP TYPE DE LINE PLUS 1. 02 COLUMN 3 PIC X(10) SOURCE PRACOVNIK. 02 COLUMN 14 PIC XXX SOURCE ZAVOD. 02 COLUMN 22 PIC XX SOURCE STREDISKO. 02 COLUMN 34 PIC Z9 SOURCE POCET-DETI. 01 TYPE CF STREDISKO LINE PLUS 2. 02 COLUMN 1 PIC X(26) VALUE 'SOUCET PRO STREDISKO CISLO'. 02 COLUMN 28 PIC XX SOURCE STREDISKO. 02 SOUCET-STR COLUMN 34 PIC Z9 SUM POCET-DETI. 01 TYPE CF ZAVOD LINE PLUS 2. 02 COLUMN 1 PIC X(22) VALUE 'SOUCET PRO ZAVOD CISLO'. 02 COLUMN 24 PIC XXX SOURCE ZAVOD. 02 SOUCET-ZAV COLUMN 34 PIC Z9 SUM SOUCET-STR. 01 TYPE PF LINE 65. 02 COLUMN 1 PIC X(42) VALUE 'SESTAVA *U37* - POCTY DETI - KONEC STRANKY'. PROCEDURE DIVISION. OPEN INPUT VSTUP OUTPUT TISK. INITIATE JOSEF. VETA. READ VSTUP AT END TERMINATE JOSEF CLOSE TISK VSTUP STOP RUN. GENERATE CHLAP. GO TO VETA. Pro zjednodušení nejsou v předešlém příkladu popsány skupiny REPORT HEADING, CONTROL HEADING FINAL, CONTROL FOOTING FINAL a REPORT FOOTING, které by mohly být též použity. Generátor sestav provádí tyto nejdůležitější funkce, jejichž podrobný popis je uveden v následujících odstavcích: 1) Umožňuje určit rozmístění jednotlivých skupin sestavy na stránce, a to buďto pomocí absolutního pořadového čísla řádku anebo relativně vzhledem k naposledy vytisknuté skupině. 2) U položek, které mají být tisknuty, umožňuje určit jejich umístění na řádce tiskárny, jejich typ a délku a dále způsob dosazování jejich hodnoty, tzn. určit, zda položka má konstantní hodnotu (VALUE) nebo zda se její hodnota získává přesunem z jiné položky (SOURCE) anebo zda se jedná o sumátor, jehož hodnota se získá načítáním (SUM). 3) Umožňuje definovat tzv. sumátory, v nichž se načítají zadané numerické položky (v předešlém příkladu je sumátorem nižší úrovně SOUCET-STR a sumátorem vyšší úrovně SOUCET-ZAV). Dále umožňuje definovat, za jakých okolností budou tyto sumátory nulovány (viz klauzule SUM a RESET). 4) Umožňuje uživateli popsat v deklarativní části PROCEDURE DIVISION pro každou ze skupin sestavy deklarativní sekci typu "USE BEFORE REPORTING", která bude vyvolána vždy před tiskem této sestavy. V této deklarativní sekci může uživatel provést libovolné akce, které nemůže nebo nechce provést pomocí Generátoru sestav (viz 13.7.). 5) Vytváření tiskové sestavy řídí uživatel pomocí příkazů INITIATE a TERMINATE (a případně ještě SUPPRESS PRINTING) uvedených v PROCEDURE DIVISION). a) Zpracování sestavy je nutno zahájit příkazem INITIATE, jenž provádí určité inicializační akce (je tedy analogický příkazu OPEN při zpracování souboru). b) Dále může uživatel (většinou mnohonásobně) provádět příkazy GENERATE, které automaticky vytvářejí tiskovou sestavu (jsou tedy analogické příkazu WRITE při zpracování souboru): - Provádějí posuv papíru v tiskárně včetně přechodů na novou stránku, při nichž tisknou skupiny PAGE HEADING a PAGE FOOTING. - Testují řídicí položky a při řídicí změně provádějí předepsané akce (mezi jiným tisk skupin CONTROL HEADING a CONTROL FOOTING). - Provádějí předepsané přičítání k sumátorům a v předepsaných situacích též nulování sumátorů. - Naplňují položky CBL-CTR, PAGE-COUNTER, LINE-COUNTER a PRINT-SWITCH definované Generátorem sestav. - Tisknou patřičné skupiny typu DETAIL. - Při tisku kterékoliv skupiny provádějí přesuny zadané pomocí klauzulí SOURCE. - Vyvolávájí zadané deklarativní sekce typu "USE BEFORE REPORTING". - První příkaz GENERATE tiskne skupinu REPORT HEADING. c) Zpracování sestavy je nutno ukončit příkazem TERMINATE, který vytiskne poslední skupiny CONTROL FOOTING a nakonec ještě skupinu REPORT FOOTING (je tedy analogický příkazu CLOSE při zpracování souboru).