Technikai cikk

Excel Sparkline-ok Delphiben: HotXLS és az x14 kiterjesztés

A HotXLS egyetlen hívással hozza létre az Excel Sparkline-okat — azokat a mini diagramokat, amelyeket az Excel egyetlen cellán belül rajzol ki — Delphiből és C++Builderből: a TXLSXWorksheet.AddSparklineGroup létrehoz egy sparkline csoportot egy adattartomány felett, a munkafüzet mentésekor pedig ezt egy x14 kiterjesztési blokkként írja be a munkalap extLst részébe, amelyet az Excel 2010 és az újabb verziók renderelnek, a régebbi olvasók pedig panasz nélkül átugranak. Nincsenek diagramobjektumok, rajzi részek és rögzítések.

Az a forgatókönyv, amely a sparkline-okat értékessé teszi, mindig ugyanaz. Egy irányítópult-munkafüzet néhány száz sort tartalmaz, egyet-egyet termékenként, régiónként vagy fiókonként, mindegyiknél tizenkét havi adattal, és valaki egy trendgrafikát szeretne minden sor végére. Ha ezt valódi diagramokkal modellezné, akkor DrawingML diagramrészek százait hozná létre, mindegyiket saját XML résszel, kapcsolattal és rögzítési geometriával, nem is beszélve arról, hogy ez mit tenne a fájlmérettel és a megnyitási idővel. Egy sparkline csoport egyetlen XML blokk, amely azt mondja: 'rajzolj egy apró vonalat a B2:M2-ből az N2-be, és a B3:M3-ból az N3-ba', és ezt olcsón megismétli annyi sorra, amennyivel csak rendelkezik.

Miért x14 kiterjesztés a sparkline diagram helyett?

A sparkline-ok az Excel 2010-zel érkeztek meg, három évvel azután, hogy az ECMA-376 alapséma befagyasztásra került, így nem élhettek magában a munkalap jelölésében anélkül, hogy ne rontanák el az összes meglévő olvasót. A Microsoft válasza a kiterjesztési lista mechanizmus: a munkalap végződhet egy <extLst> elemmel, amely <ext> blokkokat tartalmaz, mindegyiket a funkciót azonosító URI-val megjelölve ([MS-XLSX] §2.3.6). A sparkline-ok a {05C60535-1F16-4fd2-B633-F4F36F0B64E0} URI-t és az x14 névteret használják. Az a szoftver, amely felismeri a GUID-ot, értelmezi a blokkot; amelyik nem, annak kötelező átugrania. Ez a teljes előre kompatibilitási történet, és ezért nyitja meg az Excel 2007 tisztán a sparkline-t tartalmazó munkafüzetet — egyszerűen a forrásszámokat mutatja a grafika nélkül.

A mechanizmus egyetlen részletét érdemes kiemelni, mert ellentmond egy általános feltételezésnek: nincs szükség mc:Ignorable deklarációra a munkalap gyökerénél. A kiterjesztés GUID kapuja önmagában is elegendő, és az Excel saját írója az x14 névteret helyileg deklarálja az <ext> elemen, ahelyett hogy hozzányúlna a gyökérhez. A HotXLS ugyanezt a mintát követi, ami érintetlenül tartja a munkalap XML-jének többi részét. Ez a strukturális különbség a valódi diagramokhoz képest is: a diagram egy különálló DrawingML rész saját renderelési folyamattal, amint azt a diagramokról, képekről és rajzokról szóló kísérőcikk részletezi, míg a sparkline egy munkalap-metaadat, amelyet maga a táblázat rácsa rajzol ki.

Hogyan adhatunk sparkline-okat egy XLSX fájlhoz programozottan?

A TXLSXWorksheet.AddSparklineGroup(AType, ASourceRange, ALocation) az egyhívásos út: létrehoz egy megadott típusú csoportot, beállítja az Excel alapértelmezett sorozatszínével, és hozzáadja az első sparkline-t, amely leképezi a munkalap-minősített forrástartományt egy gazdacellára. A visszaadott TXLSXSparklineGroup ezután további sparkline-okat fogad el az Add metódusán keresztül, soronként egy-egy F/Sqref párt, amelyek mindegyike osztozik a csoport típusán és formázásán. Az irányítópult esetében pontosan erre a formára van szükség: egy csoport, egy vizuális opciókészlet, tagok százai.

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

    // Egy csoport: minden terméksor osztozik a típuson és a formázáson
    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;

A TXLSXSparklineType az Excel által kínált három típust fedi le: xlsxSparklineLine a trendvonalakhoz, xlsxSparklineColumn az apró oszlopdiagramokhoz és xlsxSparklineStacked a nyert/vesztett sávokhoz, ahol minden érték fel vagy le blokkként jelenik meg. Minden tag sparkline csupán két karakterláncból áll — F, a munkalap-minősített forrástartomány, és Sqref, a cella, amelybe a grafikát rajzolják —, így soronként semmi mást nem kell konfigurálni. A csoportok teljesen kézzel is felépíthetők a Worksheet.SparklineGroups gyűjteményen keresztül, ha egy üres csoportból szeretne kiindulni a beállított alapértelmezett helyett.

Jelölők, színhelyek és tengelyméretezés a típusos modellen

A TXLSXSparklineGroup az Excel Sparkline-eszközök szalagjának teljes opciókészletét egyszerű tulajdonságokként teszi elérhetővé. Hat logikai kapcsoló emeli ki az adatpontokat: Markers a vonal sparkline minden pontjára, valamint HighPoint (legmagasabb pont), LowPoint (legalacsonyabb pont), NegativePoints (negatív pontok), FirstPoint (első pont) és LastPoint (utolsó pont). Nyolc ARGB színhely párosul hozzájuk — ColorSeries, ColorNegative, ColorAxis, ColorMarkers, ColorFirst, ColorLast, ColorHigh, ColorLow —, azzal a szabállyal, hogy a 0-n hagyott színhely kimarad a fájlból, és az Excel a saját alapértelmezését alkalmazza. Ugyanez a teljesen átlátszatlan ARGB formátum jelenik meg a könyvtár egészében, így a $FFD00000 itt ugyanazt a pirosat jelenti, mint a feltételes formázási stílusokban.

Grp := Sheet.AddSparklineGroup(xlsxSparklineStacked,
  'Sheet1!B2:M2', 'N2');
Grp.NegativePoints := True;          // a veszteséges hónapok kiemelkednek
Grp.ColorNegative := $FFD00000;
Grp.HighPoint := True;
Grp.ColorHigh := $FF00B050;
Grp.MinAxisType := xlsxSparklineAxisGroup;   // egyetlen skála minden sorhoz
Grp.MaxAxisType := xlsxSparklineAxisGroup;
Grp.DisplayEmptyCellsAs := xlsxSparklineEmptyGap;

A tengelytulajdonságok megérdemelnek egy pillanatnyi átgondolást, mielőtt elfogadná az alapértelmezett értékeket. A MinAxisType és a MaxAxisType mindegyike egyéni, csoportos vagy egyéni skálázást vesz igénybe: az egyéni minden sparkline-t a saját minimumára és maximumára nyújt, ami miatt egy 99 és 101 között ingadozó sor ugyanolyan drámainak tűnik, mint egy megháromszorozódó sor. A csoportos skálázás minden tagot egy közös függőleges skálára helyez, így a grafika magassága ugyanazt a mennyiséget jelenti minden sorban — általában ezt igényli egy összehasonlító irányítópult. A DisplayEmptyCellsAs dönti el, hogy egy üres forráscella mit tesz a vonallal: üresen hagy egy hézagot, nullának számít, vagy áthidalja a lyukat a szomszédok összekapcsolásával.

Mit ír a HotXLS a munkalap extLst részébe mentéskor?

Mentéskor a HotXLS minden csoportot x14:sparklineGroup elemként szerializál, amely tartalmazza a típus- és kapcsolóattribútumokat, a színhelyeket gyermekelemekként, valamint egy x14:sparklines listát, amelynek tagjai egy xm:f tartományképletet párosítanak egy xm:sqref gazdacellával. A teljes szerkezet a munkalap rész végén található <extLst><ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"> elemen belül helyezkedik el, a blokkon közvetlenül deklarált x14 névtérrel, pontosan úgy, ahogyan az Excel írja. A sparkline csoportok nélküli munkalap egyáltalán nem bocsát ki extLst-et, így a funkciót soha nem használó fájlok bájtjaira megegyeznek azzal, amit a korábbi HotXLS verziók produkáltak — ugyanaz a konzervatív írói fegyelem, amelyet a veszteségmentes oda-vissza út infrastruktúrájáról szóló cikk ír le.

Egy specifikációs részlet számít, ha valaha is összehasonlítja a kimenetet az Excelével, vagy kézzel ellenőrzi az XML-t: a lineWeight séma-alapértelmezése 0,75 pont, nem pedig az 1,25, amelyet egyes másodlagos források idéznek — az [MS-XLSX] a CT_SparklineGroup@lineWeight-et 0,75-ös alapértelmezéssel definiálja, ami megegyezik azzal a vastagsággal, amelyet az Excel felhasználói felülete ténylegesen alkalmaz. A HotXLS elhagyással tiszteli meg az alapértelmezettet: állítsa a LineWeight értéket a 0,75-től eltérő értékre, és az attribútum beírásra kerül, hagyja 0,75-ön, és nem kerül beírásra. Ennek elhibázása bármelyik irányban olyan fájlokat eredményez, amelyek finoman nehezebben vagy könnyebben renderelődnek, mint az Excelből mentett ugyanezen munkafüzet.

Oda-vissza utak, lapmásolatok és kiterjesztések, amelyeket a HotXLS nem modellez

A megnyitás a mentés tükörképe. Amikor a HotXLS megnyit egy sparkline-okat tartalmazó munkafüzetet — akár a HotXLS írta, akár az Excel —, az elemző a sparkline kiterjesztés GUID-jára kapuzik, és újjáépít minden csoportot, tagot, színt és tengelyopciót a típusos modellbe, így a megnyitás→szerkesztés→mentés ciklus teljesen megőrzi azokat. Egy munkalap átmásolása egy another munkafüzetbe klónozza a sparkline csoportjait a lap többi részével együtt, ami egyszerűvé teszi a sablonvezérelt jelentéskészítést: tartson meg egy formázott sablonlapot, másolja le jelentésenként, és irányítsa át a tartományokat.

Az extLst olyan kiterjesztési blokkokat is tartalmazhat, amelyekhez a HotXLS-nek nincs típusos modellje — az Excel x14 blokkokat ír az olyan funkciókhoz, mint a szeletelők (slicers) és a kiterjesztett feltételes formázás ugyanebbe a listába. A v2.131.0 verzió óta ezek az idegen blokkok szó szerint megőrződnek az oda-vissza út során ahelyett, hogy elvesznének: az elemző rögzíti őket, írásvédettként elérhetővé teszi őket a Worksheet.RawWorksheetExts gyűjteményen keresztül, és visszahárítja őket mentéskor, és a lappal együtt utaznak, amikor azt egy másik munkafüzetbe másolják. A megőrzött XML az elemző eseményeiből épül fel újra, így szemantikailag egyenértékű az eredetivel, nem pedig bájt-azonos, de az Excel elfogadja, és a funkciók túlélnek. A gyakorlati következmény az, ami számít éles környezetben: egy ügyfél munkafüzetének megnyitása és újramentése már nem fosztja meg azokat a kiterjesztéseket, amelyek megértését nem kérte a HotXLS-től.

A becsületes határvonal: a sparkline-ok az Excel 2010 és újabb verzióiban renderelődnek, valamint minden más olyan olvasóben, amely implementálja az x14 kiterjesztést; az Excel 2007 a grafika nélkül mutatja az adatokat, ami pontosan az a fokozatos leépülés (degradation), amelyre a formátumot tervezték. A három sparkline típus, a nyolc színhely, a pontkapcsolók és a három tengelymód lefedi a teljes opciós felületet, amelyet az Excel saját párbeszédpanele kínál. A sparkline támogatás az itt bemutatott XLSX motor többi részével együtt a Delphire és C++Builderre készült HotXLS Delphi Excel komponensben érhető el.