Odborný článok

Excel sparkline grafy v Delphi: HotXLS a rozšírenie x14

HotXLS vytvára Excel Sparklines (minigrafy) — miniatúrne grafy, ktoré Excel kreslí vo vnútri jedinej bunky — z Delphi a C++Builderu jediným volaním: TXLSXWorksheet.AddSparklineGroup zostaví skupinu minigrafov nad rozsahom údajov a uloženie zošita ju zapíše ako rozširujúci blok x14 do zoznamu extLst hárka, ktorý Excel 2010 a novší vykresľujú a staršie verzie ho preskakujú bez chybových hlásení. Žiadne objekty grafov, žiadne časti kreslenia, žiadne ukotvenia

Scenár, pri ktorom sa oplatí minigrafy mať, je vždy rovnaký. Manažérsky prehľad (dashboard) obsahuje niekoľko stoviek riadkov, jeden pre každý produkt, región alebo účet, pričom každý má dvanásť mesačných hodnôt a na konci každého riadku je požadovaný indikátor trendu. Ak by ste to riešili pomocou reálnych grafov, museli by ste vytvoriť stovky častí DrawingML grafov, z ktorých každá by mala vlastnú XML časť, reláciu a geometriu ukotvenia, nehovoriac o tom, čo by to urobilo s veľkosťou súboru a časom jeho otvárania. Skupina minigrafov je jeden XML blok, ktorý hovorí „nakresli drobnú čiaru z B2:M2 do N2 a z B3:M3 do N3“, čo sa dá veľmi efektívne zopakovať pre ľubovoľný počet riadkov

Prečo sú minigrafy rozšírením x14 a nie bežným grafom?

Minigrafy prišli s Excelom 2010, tri roky po zmrazení základnej schémy ECMA-376, takže nemohli byť umiestnené priamo v bežnom XML kóde hárka bez toho, aby to narušilo staršie čítače. Riešením spoločnosti Microsoft je mechanizmus zoznamu rozšírení (extension list): hárok môže končiť elementom <extLst> obsahujúcim bloky <ext>, z ktorých každý má URI identifikujúce danú funkciu ([MS-XLSX] §2.3.6). Minigrafy používajú URI {05C60535-1F16-4fd2-B633-F4F36F0B64E0} and the x14 namespace. Čítač, ktorý rozpozná tento identifikátor GUID, blok spracuje; čítač, ktorý ho nepozná, ho musí preskočiť. To je celý príbeh o spätnej kompatibilite, a preto Excel 2007 otvorí zošit s minigrafmi bez chýb — jednoducho zobrazí zdrojové čísla bez vizuálnych minigrafov

Jeden detail tohto mechanizmu stojí za zmienku, pretože odporuje bežnému predpokladu: na koreňovom elemente hárka nie je potrebná žiadna deklarácia mc:Ignorable. Samotná brána ext GUID je plne dostačujúca a vlastný generátor Excelu deklaruje menný priestor x14 lokálne na elemente <ext>, namiesto toho, aby zasahoval do koreňa. HotXLS sa drží rovnakého vzoru, čo ponecháva zvyšok XML hárka nedotknutý. To je tiež štrukturálny rozdiel oproti skutočným grafom: graf je samostatná časť DrawingML s vlastným spracovaním vykresľovania, popísaným v sprievodnom článku o grafoch, obrázkoch a kresbách, zatiaľ čo minigraf predstavuje metadáta hárka, ktoré vykresľuje priamo samotná mriežka tabuľky

Ako programovo pridať minigrafy do súboru XLSX?

Metóda TXLSXWorksheet.AddSparklineGroup(AType, ASourceRange, ALocation) predstavuje priamu cestu: vytvorí skupinu minigrafov daného typu, naplní ju predvolenou farbou radov a pridá prvý minigraf mapujúci zdrojový rozsah s názvom hárka do cieľovej bunky. Vrátený objekt TXLSXSparklineGroup potom prijíma ďalšie minigrafy prostredníctvom svojej metódy Add, jeden pár F/Sqref na riadok, pričom všetky zdieľajú typ a formátovanie skupiny. Pre prípad prehľadového dashboardu je to presne požadovaný tvar: jedna skupina, jedna sada vizuálnych nastavení a stovky položiek

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Grp: TXLSXSparklineGroup;
  Row: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('dashboard.xlsx');
    Sheet := Book.Sheets[0];

    // One group: every product row shares type and formatting
    Grp := Sheet.AddSparklineGroup(xlsxSparklineLine,
      'Sheet1!B2:M2', 'N2');
    for Row := 3 to 201 do
      Grp.Add(Format('Sheet1!B%d:M%d', [Row, Row]),
        Format('N%d', [Row]));

    Book.SaveAs('dashboard-trends.xlsx');
  finally
    Book.Free;
  end;
end;

Typ TXLSXSparklineType pokrýva tri druhy, ktoré Excel ponúka: xlsxSparklineLine pre čiarové trendy, xlsxSparklineColumn pre stĺpcové minigrafy a xlsxSparklineStacked pre win/loss grafy, kde sa každá hodnota vykresľuje ako blok hore alebo dole. Každý jednotlivý minigraf pozostáva len z dvoch reťazcov — F, čo je zdrojový rozsah s názvom hárka, a Sqref, čo je bunka, v ktorej sa minigraf vykresľuje — takže pre jednotlivé riadky nie je potrebné nič iné konfigurovať. Skupiny je možné zostaviť aj ručne prostredníctvom kolekcie Worksheet.SparklineGroups, ak chcete začať s prázdnou skupinou namiesto predvolenej

Značky, farebné sloty a škálovanie osí v typovom modeli

Trieda TXLSXSparklineGroup sprístupňuje celú sadu možností z panela Nástroje pre minigrafy v Exceli ako bežné vlastnosti. Šesť logických (boolean) prepínačov zvýrazňuje dátové body: Markers pre každý bod na čiarovom minigrafe, plus HighPoint, LowPoint, NegativePoints, FirstPoint a LastPoint. S nimi sa spája osem farebných slotov ARGB — ColorSeries, ColorNegative, ColorAxis, ColorMarkers, ColorFirst, ColorLast, ColorHigh, ColorLow — s konvenciou, že slot ponechaný na hodnote 0 sa v súbore vynechá a Excel použije vlastné predvolené nastavenie. Rovnaký plne nepriehľadný formát ARGB sa používa naprieč celou knižnicou, takže $FFD00000 tu znamená rovnakú červenú farbu ako v štýloch podmieneného formátovania

Grp := Sheet.AddSparklineGroup(xlsxSparklineStacked,
  'Sheet1!B2:M2', 'N2');
Grp.NegativePoints := True;          // losing months stand out
Grp.ColorNegative := $FFD00000;
Grp.HighPoint := True;
Grp.ColorHigh := $FF00B050;
Grp.MinAxisType := xlsxSparklineAxisGroup;   // one scale for all rows
Grp.MaxAxisType := xlsxSparklineAxisGroup;
Grp.DisplayEmptyCellsAs := xlsxSparklineEmptyGap;

Vlastnosti osí si zaslúžia chvíľu premýšľania pred tým, ako akceptujete predvolené hodnoty. Parametre MinAxisType a MaxAxisType umožňujú individuálne, skupinové alebo vlastné škálovanie: individuálne roztiahne každý minigraf na jeho vlastné minimum a maximum, čo spôsobí, že riadok kolísajúci medzi 99 a 101 vyzerá rovnako dramaticky ako riadok s trojnásobným nárastom. Skupinové škálovanie umiestni všetkých členov na jednu zdieľanú vertikálnu os, takže výška grafu znamená rovnaké množstvo v každom riadku — čo je zvyčajne to, čo komparatívny dashboard vyžaduje. DisplayEmptyCellsAs určuje, ako prázdna zdrojová bunka ovplyvní čiaru: zanechá medzeru, počíta sa ako nula, alebo premostí dieru spojením susedných bodov

Čo HotXLS zapisuje do extLst hárka pri uložení

Pri uložení HotXLS serializuje každú skupinu ako element x14:sparklineGroup nesúci atribúty typu a prepínačov, farebné sloty ako dcérske elementy a zoznam x14:sparklines, ktorého členovia spájajú vzorec rozsahu xm:f s hostiteľskou bunkou xm:sqref. Celá štruktúra sa nachádza vo vnútri <extLst><ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"> na konci XML hárka, s menným priestorom x14 deklarovaným priamo na bloku, presne tak, ako to zapisuje Excel. Hárok bez skupín minigrafov nevygeneruje vôbec žiadny extLst, takže súbory, ktoré túto funkciu nepoužívajú, vychádzajú bajt po bajte identické s tým, čo produkovali predchádzajúce verzie HotXLS — ide o rovnakú disciplínu konzervatívneho zápisu, aká je popísaná v článku o infraštruktúre bezstratových prechodov (lossless round-trip)

Jeden detail špecifikácie je dôležitý, ak niekedy porovnávate výstup s Excelom alebo ručne kontrolujete XML: predvolená hodnota schémy pre lineWeight je 0.75 bodu, nie 1.25, ako uvádzajú niektoré sekundárne zdroje — [MS-XLSX] definuje CT_SparklineGroup@lineWeight s predvolenou hodnotou 0.75, čo zodpovedá hrúbke, ktorú rozhranie Excelu skutočne aplikuje. HotXLS rešpektuje túto predvolenú hodnotu vynechaním: ak nastavíte LineWeight na hodnotu odlišnú od 0.75, atribút sa zapíše, ak ho ponecháte na 0.75, nezapíše sa. Chyba v ktoromkoľvek smere produkuje súbory, ktoré sa vykresľujú o niečo hrubšie alebo tenšie ako rovnaký zošit uložený z Excelu

Prechody tam a späť, kopírovanie hárkov a rozšírenia, ktoré HotXLS nemodeluje

Otváranie je zrkadlovým obrazom ukladania. Keď HotXLS otvorí zošit, ktorý obsahuje minigrafy — či už ho zapísal HotXLS alebo Excel — parser zachytí GUID minigrafu a znovu zostaví každú skupinu, člena, farbu a nastavenie osí do typového modelu, takže cyklus otvoriť→upraviť→uložiť ich kompletne zachová. Skopírovanie hárka do iného zošita naklonuje aj jeho skupiny minigrafov spolu so zvyškom hárka, čo zjednodušuje generovanie reportov na základe šablón: ponecháte si naštýlovaný hárok šablóny, skopírujete ho pre každý report a zmeníte smerovanie rozsahov

Zoznam extLst môže obsahovať aj rozširujúce bloky, pre ktoré HotXLS nemá typový model — Excel zapisuje do rovnakého zoznamu bloky x14 pre funkcie ako prierezy (slicers) a rozšírené podmienené formátovanie. Od verzie v2.131.0 sú tieto cudzie bloky pri prechode tam a späť uchované doslovne a nezahadzujú sa: parser ich zachytí, sprístupní ich len na čítanie cez Worksheet.RawWorksheetExts a zapíše ich späť pri uložení, pričom cestujú s hárkom aj pri jeho skopírovaní do iného zošita. Zachované XML sa rekonštruuje z udalostí parsera, takže je sémanticky ekvivalentné s originálom, hoci nie bajtovo identické, avšak Excel ho akceptuje a príslušné funkcie prežijú. Praktický dôsledok je ten najdôležitejší pre produkciu: otvorenie zošita zákazníka a jeho opätovné uloženie už neodstráni rozšírenia, ktorým ste od HotXLS nežiadali rozumieť

Úprimné obmedzenie: minigrafy sa vykresľujú v Exceli 2010 a novšom, a v akomkoľvek inom prehliadači, ktorý implementuje rozšírenie x14; Excel 2007 zobrazí údaje bez minigrafov, čo je presne ten spôsob degradácie, na ktorý bol formát navrhnutý. Tri typy minigrafov, osem farebných slotov, prepínače bodov a tri režimy osí pokrývajú kompletné možnosti, ktoré ponúka dialógové okno samotného Excelu. Podpora pre sparkline minigrafy sa dodáva spolu so zvyškom tu zobrazeného XLSX enginu v komponente HotXLS Delphi Excel Component pre Delphi a C++Builder