Tekninen artikkeli

Excel-pikakaaviot Delphissä: HotXLS ja x14-laajennus

HotXLS luo Excel-pikakaavioita (sparklines) — eli pieniä kaavioita, jotka Excel piirtää yksittäisen solun sisälle — Delphistä ja C++Builderistä yhdellä kutsulla: TXLSXWorksheet.AddSparklineGroup rakentaa pikakaavioryhmän tietoalueelle, ja työkirjan tallentaminen kirjoittaa sen x14-laajennuslohkona taulukon extLst-rakenteen sisään. Tämän lohkon Excel 2010 ja uudemmat piirtävät, ja vanhemmat lukijat ohittavat sen valittamatta. Ei kaavio-olioita, ei piirto-osia eikä ankkureita

Skenaario, joka tekee pikakaavioista hyödyllisiä, on aina sama. Yhteenvetotyökirja sisältää muutamia satoja rivejä (yksi per tuote, alue tai tili), kussakin kaksitoista kuukausittaista lukua, ja joku haluaa suuntaviivan kunkin rivin loppuun. Jos tämä toteutettaisiin oikeilla kaavioilla, luotaisiin satoja DrawingML-kaavio-osia omine XML-osineen, suhteineen ja ankkurigeometrioineen, puhumattakaan siitä, mitä se tekisi tiedostokoolle ja avautumisajalle. Pikakaavioryhmä on yksi XML-lohko, joka ilmoittaa "piirrä pieni viiva alueelta B2:M2 soluun N2, ja alueelta B3:M3 soluun N3", ja tämä toistetaan tehokkaasti niin monelle riville kuin tarpeen

Miksi pikakaaviot ovat x14-laajennus eivätkä kaavio?

Pikakaaviot tulivat Excel 2010:n myötä, kolme vuotta ECMA-376-perusskeeman lukitsemisen jälkeen. Siksi ne eivät voineet sijaita varsinaisessa taulukkomerkinnässä rikkomatta kaikkia olemassa olevia lukijoita. Microsoftin ratkaisu on laajennusluettelomekanismi (extension list mechanism): laskentataulukko voi päättyä elementtiin <extLst>, joka sisältää <ext>-lohkoja, joista kukin on merkitty toiminnon tunnistavalla URI-tunnisteella ([MS-XLSX] §2.3.6). Pikakaaviot käyttävät URI-tunnistetta {05C60535-1F16-4fd2-B633-F4F36F0B64E0} ja nimiavaruutta x14. Lukija, joka tunnistaa tämän GUID-tunnisteen, jäsentää lohkon. Lukija, joka ei sitä tunnista, ohittaa sen vaatimusten mukaisesti. Tämä on koko eteenpäin suuntautuvan yhteensopivuuden tarina, ja siksi Excel 2007 avaa pikakaavioita sisältävän työkirjan puhtaasti — se vain näyttää lähdenumerot ilman symboleita

Eräs mekanismin yksityiskohta on syytä nostaa esiin, sillä se on vastoin yleistä oletusta: laskentataulukon juuressa ei tarvita mc:Ignorable-ilmoitusta. Laajennuksen GUID-portti riittää itsessään, ja Excelin oma kirjoitin ilmoittaa x14-nimiavaruuden paikallisesti elementissä <ext> sen sijaan, että koskettaisiin juureen. HotXLS noudattaa samaa mallia, mikä pitää taulukon muun XML:n koskemattomana. Tämä on myös rakenteellinen ero oikeisiin kaavioihin: kaavio on erillinen DrawingML-osa omalla piirtoputkellaan, jota käsitellään kumppaniartikkelissa kaavioista, kuvista ja piirroksista, kun taas pikakaavio on taulukon metatietoa, jonka taulukkoruudukko itse piirtää

Miten lisäät pikakaavioita XLSX-tiedostoon ohjelmallisesti?

TXLSXWorksheet.AddSparklineGroup(AType, ASourceRange, ALocation) on yhden kutsun polku: se luo annetun tyyppisen ryhmän, alustaa sen Excelin oletusväreillä ja lisää ensimmäisen pikakaavion, joka kartoittaa taulukkomääritetyn lähdealueen isäntäsoluun. Palautettu TXLSXSparklineGroup ottaa sitten vastaan lisää pikakaavioita Add-metodillaan (yksi F/Sqref-pari riviä kohti), ja ne kaikki jakavat ryhmän tyypin ja muotoilut. Yhteenvetoskenaariossa tämä on juuri haluttu rakenne: yksi ryhmä, yhdet visuaaliset asetukset ja satoja jäseniä

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

    // Yksi ryhmä: jokainen tuoterivi jakaa tyypin ja muotoilun
    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;

TXLSXSparklineType kattaa kolme Excelin tarjoamaa tyyppiä: xlsxSparklineLine suuntaviivoille, xlsxSparklineColumn pienille pylväskaavioille ja xlsxSparklineStacked voitto/tappio-kuvioille, joissa jokainen arvo piirtyy ylös- tai alaspäin osoittavana lohkona. Kukin ryhmän pikakaavio koostuu vain kahdesta merkkijonosta — F (taulukon lähdealue) ja Sqref (solu, johon kuvio piirretään) — joten rivikohtaisesti ei tarvite määrittää muuta. Ryhmiä voidaan rakentaa myös kokonaan käsin kokoelman Worksheet.SparklineGroups kautta, jos haluat aloittaa tyhjästä ryhmästä alustetun oletuksen sijaan

Merkit, väripaikat ja akselin skaalaus tyypitetyssä mallissa

TXLSXSparklineGroup tuo Excelin Pikakaaviotyökalut-välilehden kaikki asetukset käytettäviksi tavallisina ominaisuuksina. Kuusi boolean-valintaa korostaa tietopisteitä: Markers jokaiselle pisteelle viivapikakaaviossa, sekä HighPoint, LowPoint, NegativePoints, FirstPoint ja LastPoint. Kahdeksan ARGB-väripaikkaa muodostavat parin näiden kanssa — ColorSeries, ColorNegative, ColorAxis, ColorMarkers, ColorFirst, ColorLast, ColorHigh, ColorLow — käytännöllä, että arvoon 0 jätetty paikka jätetään pois tiedostosta ja Excel soveltaa omaa oletustaan. Sama täysin peittävä ARGB-muoto esiintyy läpi kirjaston, joten $FFD00000 tarkoittaa täällä samaa punaista kuin ehdollisen muotoilun tyyleissä

Grp := Sheet.AddSparklineGroup(xlsxSparklineStacked,
  'Sheet1!B2:M2', 'N2');
Grp.NegativePoints := True;          // tappiolliset kuukaudet erottuvat
Grp.ColorNegative := $FFD00000;
Grp.HighPoint := True;
Grp.ColorHigh := $FF00B050;
Grp.MinAxisType := xlsxSparklineAxisGroup;   // yksi asteikko kaikille riveille
Grp.MaxAxisType := xlsxSparklineAxisGroup;
Grp.DisplayEmptyCellsAs := xlsxSparklineEmptyGap;

Akselin ominaisuuksia kannattaa harkita hetki ennen oletusten hyväksymistä. MinAxisType ja MaxAxisType ottavat kumpikin vastaan yksilöllisen, ryhmäkohtaisen tai mukautetun skaalauksen: yksilöllinen (individual) venyttää jokaisen pikakaavion sen omaan minimiin ja maksimiin, mikä tekee arvojen 99 ja 101 välillä vaihtelevasta rivistä yhtä dramaattisen näköisen kuin kolminkertaistuvasta rivistä. Ryhmäskaalaus asettaa kaikki jäsenet yhdelle yhteiselle pystysuuntaiselle asteikolle, jolloin kuvion korkeus tarkoittaa samaa määrää jokaisella rivillä — mikä on yleensä vertailevassa yhteenvedossa haluttu tapa. DisplayEmptyCellsAs määrittää, mitä tyhjä lähdesolu tekee viivalle: jättää välin (gap), laskee nollaksi tai ylittää aukon yhdistämällä sen naapuripisteet

Mitä HotXLS kirjoittaa taulukon extLst-luetteloon tallennettaessa

Tallennettaessa HotXLS sarjoittaa kunkin ryhmän x14:sparklineGroup-elementiksi, joka kantaa tyyppi- ja valinta-attribuutit, värit lapsielementteinä ja x14:sparklines-luettelon, jonka jäsenet yhdistävät xm:f-aluekaavan ja xm:sqref-isäntäsolun. Koko rakenne sijaitsee polussa <extLst><ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"> laskentataulukko-osan lopussa, x14-nimiavaruuden ollessa ilmoitettuna suoraan lohkossa, täsmälleen kuten Excel sen kirjoittaa. Laskentataulukko ilman pikakaavioryhmiä ei tuota extLst-elementtiä lainkaan, joten tiedostot, jotka eivät ole koskaan käyttäneet toimintoa, ovat bitti bitiltä identtisiä aiemmilla HotXLS-versioilla tuotettujen kanssa — noudattaen samaa konservatiivisen kirjoittimen kurinalaisuutta, jota kuvaillaan artikkelissa häviöttömän edestakaisen kierroksen infrastruktuurista

Eräs spesifikaation yksityiskohta on tärkeä, jos koskaan vertaat tulostetta Excelin tuottamaan tai tarkistat XML:n käsin: skeeman oletusarvo määritteelle lineWeight on 0.75 pistettä, not the 1.25 some secondary sources quote — [MS-XLSX] määrittelee CT_SparklineGroup@lineWeight oletukseksi 0.75, mikä vastaa Excelin käyttöliittymän todellisuudessa soveltamaa painoa. HotXLS kunnioittaa oletusta jättämällä sen pois: jos asetat LineWeight-arvoksi muun kuin 0.75, attribuutti kirjoitetaan, jos jätät sen arvoon 0.75, sitä ei kirjoiteta. Tämän meneminen väärin kumpaan tahansa suuntaan tuottaa tiedostoja, jotka piirtyvät hieman raskaampina tai kevyempinä kuin vastaava Excelistä tallennettu työkirja

Edestakaiset kierrokset, taulukon kopiot ja laajennukset, joita HotXLS ei mallinna

Avaaminen on tallentamisen peilikuva. Kun HotXLS avaa pikakaavioita sisältävän työkirjan — oli se sitten HotXLS:n tai Excelin kirjoittama — jäsennin tunnistaa pikakaavion ext GUID -tunnisteen ja rakentaa kunkin ryhmän, jäsenen, värin ja akselin asetukset tyypittyyn malliin. Siten avaa-muokkaa-tallenna-sykli säilyttää ne kokonaan. Laskentataulukon kopioiminen toiseen työkirjaan monistaa sen pikakaavioryhmät taulukon muun sisällön ohella, mikä tekee mallipohjaisesta raporttien luonnista suoraviivaista: säilytä muotoiltu mallipohja, kopioi se raporttia kohden ja kohdista alueet uudelleen

extLst voi sisältää myös laajennuslohkoja, joille HotXLS-komponentilla ei ole tyypitettyä mallia — Excel kirjoittaa x14-lohkoja esimerkiksi osittajille (slicers) ja laajennetuille ehdollisille muotoiluille samaan luetteloon. Versiosta v2.131.0 lähtien nämä ulkopuoliset lohkot säilytetään sellaisenaan edestakaisessa kierrossa sen sijaan, että ne pudotettaisiin pois: jäsennin poimii ne, tuo ne esiin vain luku -muodossa Worksheet.RawWorksheetExts-ominaisuuden kautta ja kirjoittaa ne takaisin tallennettaessa, ja ne kulkevat taulukon mukana, kun se kopioimassa toiseen työkirjaan. Säilytetty XML rakennetaan uudelleen jäsentimen tapahtumista, joten se on semanttisesti vastaava alkuperäisen kanssa vaikkei ole bitti bitiltä identtinen, mutta Excel hyväksyy sen ja toiminnot säilyvät. Käytännön seuraus on tuotannossa merkittävä: asiakkaan työkirjan avaaminen ja uudelleentallentaminen ei enää poista laajennuksia, joita et pyytänyt HotXLS-komponenttia ymmärtämään

Rehellinen rajalinja: pikakaaviot piirtyvät Excel 2010:ssä ja uudemmissä sekä kaikissa muissa lukijoissa, jotka toteuttavat x14-laajennuksen; Excel 2007 näyttää tiedot ilman kuvioita, mikä on se hallittu heikennys (degradation), joksi formaatti on suunniteltu. Kolme pikakaaviotyyppiä, kahdeksan väripaikkaa, pisteiden valinnat ja kolme akselitilaa kattavat koko Excelin oman valintaikkunan tarjoaman asetuskentän. Pikakaaviotuki, yhdessä muun tässä esitetyn XLSX-moottorin kanssa, toimitetaan HotXLS Delphi Excel Component -tuotteessa Delphille ja C++Builderille