Tekninen artikkeli

Kaavio-objektien upottaminen laskentataulukoille HotXLS:llä

HotXLS voi sijoittaa kaavion suoraan laskentataulukolle ankkuroituna solualueeseen sen sijaan, että laittaisi sen erilliselle kaaviosivulle. BIFF8:n termeillä se tarkoittaa piirrosmuodon kirjoittamista OBJ-tietueella, jonka tyyppi on 5, ja kaavion alivirran pysäköintiä taulukon tietuevirran loppuun, mikä on täsmälleen se asettelu, jonka Excel tuottaa, ja täsmälleen se paikka, josta lukija odottaa sen löytyvän

Ero merkitsee jokaiselle, joka tuottaa toiminnallisia raportteja. Kaaviosivu on mainio koti yhdelle otsikkokuvalle. Kuukausittainen alueittainen erittely haluaa kaavion lukujensa viereen, samalle taulukolle, kokoon sovitettuna siihen solulohkoon, johon se kuuluu, jotta lukija vierittää kerran tabien vaihtamisen ja kontekstin menettämisen sijaan

Lukeminen oli jo olemassa, kirjoittaminen ei

Epäsymmetria kannattaa nimetä, koska se muotoilee työn. HotXLS osasi jo lukea upotettuja kaavioita: kun taulukon tietuevirta sisältää kaavion alivirraksi merkityn BOF:n, jäsennin vaihtaa kontekstia, kerää kaaviotietueet ja luovuttaa sulkeutuvan EOF:n kohdalla ne takaisin piirrosmuodolle, jonka OBJ-tietue esitteli. Tuo polku oli ollut käytössä jokaisessa Excelin laatimassa työkirjassa, jonka kirjasto koskaan avasi

Mitä puuttui oli laatimispuoli, ja hyödyllinen seuraus on, että uudella kirjoittajalla oli tarkka spesifikaatio osuttavana: tuota tavuasettelu, jonka olemassa oleva lukija jo kiinnittää takaisin. Ei ole parempaa hyväksymiskriteeriä binäärimuoto-ominaisuudelle kuin itsenäisesti kirjoitettu lukija, jota et saanut muuttaa

Mistä upotettu kaavio on tehty

Kolmen palan on sovittava yhteen. Piirroskerros myöntää isäntäkontrollimuodon, objektikerros OBJ-tietueen, jonka yhteinen objektidata julistaa objektityypin 5, ja tietuevirta itse kaavion alivirran. OBJ-tietueen optionliput ovat ne, jotka Excel kirjoittaa kaaviokehykselle: sijoitettu, lukittu, automaattinen viiva ja automaattinen täyttö, mikä saa upotetun kaavion käyttäytymään natiivin kaltaisesti, kun käyttäjä napsauttaa sitä

HotXLS ankkuroi BIFF8-kaavion alivirran Delphi-taulukkolaskentaan kolmen yhteen sopivan palan kautta: piirroskerroksen isäntäkontrollimuoto, OBJ-tietue, jonka yhteinen objektidata julistaa objektityypin 5, ja kaaviotietueketju, joka on pysäköitynä taulukon tietuevirran loppuun, jossa kaavion BOF vaihtaa jäsennyksen kontekstin ja sulkeutuva EOF kiinnittää tietueet takaisin
Kolme kerrosta kantaa yhtä upotettua kaaviota: piirrosmuoto ankkuroi sen, OBJ-tietue tyypittää sen kaavioisäännäksi, ja kaavion alivirta taulukon tietuevirran lopussa toimittaa tietueet, jotka lukija kiinnittää takaisin

Ankkuri ansaitsee huomion, koska se on yleinen off-by-one-vikojen lähde. HotXLS:n API ottaa ykköspohjaiset rivi- ja sarakenumerot vastaten kirjaston loppua, ja tiedostoon kirjoitettava asiakasankkuri on nollapohjainen. Muunnos tapahtuu AddChartObjectin sisällä, joten kutsujat pysyvät koordinaatistossa, jota he käyttävät kaikkialla muualla, mutta jokaisen, joka vertaa heksadumppia omaan kutsuunsa, on muistettava, kummalla puolen rajaa hän lukee

var
  Book: TXLSWorkbook;
  Sheet: TXLSWorksheet;
  Series: array[0..1] of TXLSChartSeriesInfo;
begin
  Book := TXLSWorkbook.Create(nil);
  try
    Book.LoadFromFile('regional-sales.xls');
    Sheet := Book.Sheets[0];

    FillChar(Series, SizeOf(Series), 0);
    Series[0].Name := 'Actual';
    Series[0].Categories := 'Data!$A$2:$A$13';
    Series[0].Values := 'Data!$B$2:$B$13';
    Series[0].DataLabels.ShowValue := True;
    Series[0].HasDataLabels := True;

    Series[1].Name := 'Target';
    Series[1].Categories := 'Data!$A$2:$A$13';
    Series[1].Values := 'Data!$C$2:$C$13';
    Series[1].SecondaryAxis := True;

    // Ankkuroitu E2:M20 tällä taulukolla, ykköspohjaisesti
    Sheet.AddChartObject(xlsChartTypeColumn, 'Regional sales',
      'Month', 'Amount', Series, 2, 5, 20, 13);

    Book.SaveToFile('regional-sales-charted.xls');
  finally
    Book.Free;
  end;
end;

FillChar sarjataulussa ei ole koristetta. TXLSChartSeriesInfo kantaa useita valinnaisia alitietueita, datanimikkeitä, sarjakohtaisen tyylin, trendiviivoja ja virhewiskureita, kukin portitettuna booleanilla, ja osittain alustettu tietue pinossa luovuttaa emittoijalle lippuja, joita kukaan ei asettanut. Nollaa taulu ja aseta sitten kentät, joita tarkoitat

Mitä sarjaviittauksia upotettu polku hyväksyy?

Paljaat A1-tyyliset alueet saman työkirjan sisällä, ja tuo rajoitus on tahallinen eikä hairahdus. Jokainen viittaus ratkaistaan työkirjan taulukkolistan vasten ja muunnetaan ulkoiseksi viittausindeksiksi, jota kaaviotietueet tarvitsevat. Nimetty alue tai ulkoinen työkirjaviittaus palaa paikkamerkkiin, jolla on nollapituinen jäsennetty lauseke, joten kaavio kirjoittuu puhtaasti, mutta kyseisellä sarjalla ei ole datalähdettä, ennen kuin osoitat sen alueeseen

HotXLS:n sarjaviittausten hyväksyntä upotetulla BIFF8-kaaviopolkua: A1-tyyliset alueet, kuten Data!$B$2:$B$13, saman työkirjan sisällä ratkeavat taulukkolistan vasten ulkoiseksi viittausindeksiksi, jota kaaviotietueet tarvitsevat, kun taas nimetyt alueet ja ulkoiset työkirjaviittaukset palaavat paikkamerkkiin, jolla on nollapituinen jäsennetty lauseke, ja molemmat kuuluvat AddChartSheetille
Vain paljaat A1-tyyliset alueet saman työkirjan sisällä kääntyvät kaaviosarjaviittauksiksi; kaikki muu kirjoittuu puhtaasti paikkamerkkinä uudelleenosoittamiseen asti, ja täysi polku asuu AddChartSheetillä

Syy on suora insinöörivaihtokauppa. Täysi viittausten käännöspolku on olemassa kaaviosivureitillä, kiedottuna taulukkokokoelmakeksen sisään, ja sen kohottaminen ulos puhtaasti tarkoittaisi sadan rivin ratkaisulogiikan monistamista tapaukselle, joka on käytännössä harvinainen. Upotettu kaavio piirtää lähes aina soluja omalta taulukoltaan tai sisardatalta. Nimetyt ja ulkoiset viittaukset kuuluvat kaaviosivupolkuun AddChartSheetin kautta, joten mikään ei ole saatavilla olematta, vain saavutetaan eri sisääntulopisteestä

Kaikki muu sarjamallissa toimii identtisesti molemmilla reiteillä. Toissijaisen akselin sidonta, sarjakohtainen viiva, täyttö ja merkkityylit, trendiviivat, virhewiskurit ja datanimikkeet ovat kaikki osa TXLSChartSeriesInfoa ja kaikki emittoituna samalla tavalla, joten kaaviomäärittely voi liikkua upotetun objektin ja kaaviosivun välillä vain kutsun muuttuessa. Toissijaisen akselin lipun takana olevat akseliryhmäkoneistot on käsitelty artikkelissa toissijaiset akseliryhmät BIFF-kirjoituksessa

Miksi kaavion otsikko lukesi kahtena merkkinä?

Koska merkkimäärä passitettiin paikkaan, jossa tavumäärää odotettiin, ja BIFF Unicode -merkkijonot tekevät tuosta virheestä helpon kirjoittaa ja vaikean nähdä. Lyhyt BIFF Unicode -merkkijono alkaa merkkimäärällä ja lipputavulla, ja lipputavu kantaa high-byte-bittiä, joka sanoo, onko payload yksi tavu per merkki vai kaksi. Lue 16-bittinen payload merkkimäärällä, ikään kuin se olisi tavupituus, ja saat täsmälleen puolet merkkijonosta: sarja, jonka nimi on Sales, palaa muodossa Sa, ja kaavion otsikko katkeaa samalla tavalla, koska otsikot ja sarjanimikkeet jakavat dekoodauspolun

Se, mikä tekee tästä defektistä merkittävän, on, että se toistui kolme kertaa samassa tietueperheessä, kerran trendiviivojen nimissä, kerran pivot-kaavioiden nimissä ja kerran kaavioiden otsikoissa. Jokainen ilmentymä näytti tuoreelta bugilta uudessa ominaisuudessa. Kaikki kolme olivat sama puuttuva kertolasku. Sääntö, joka lopulta sulki asian, on mekaaninen, ja se pitäisi soveltaa ilman harkintaa: aina kun luet yhden näistä merkkijonoista, tarkista high-byte-lippu ensin ja kerro merkkimäärä payloadin leveydellä ennen puskuriin koskemista. Tietuetason yksityiskohdat ovat artikkelissa XLUnicodeStringin merkkimäärien ja high-byte-lipun dekoodaus

// Upotettu kaavio jakaa piirroskerroksen kuvien ja muotojen kanssa,
// joten taulukolla jo oleva piirros säilyy. AddChartObject palauttaa
// luodun objektin indeksin
var
  ObjIndex: Integer;
begin
  ObjIndex := Sheet.AddChartObject(xlsChartTypeLine, 'Trend',
    'Week', 'Units', Series, 2, 8, 18, 16);
  if ObjIndex < 0 then
    raise Exception.Create('chart object was not created');
end;

Missä upotetut kaaviot istuvat vaihtoehtojen rinnalla

Kolme reittiä on olemassa, ja ne vastaavat eri kysymyksiin. Upotettu kaavio-objekti kuuluu datansa viereen laskentataulukolle ja on se, mitä useimmat raportit haluavat. Kaaviosivu sopii yhteen esityskuvaan ja antaa täyden viittausten käännöspolun. Olemassa olevan kaavion säilyttäminen ladatusta tiedostosta koskemattomana on oikea vastaus silloin, kun työkirja tuli Excelistä muotoilulla, jota kukaan ei halua kirjaston tulkitsevan uudelleen; tuo läpiviennin käytös on kuvattu artikkelissa säilytetyt ChartML- ja yhdistelmäkaaviot

Koska upotettu kaavio ajaa piirroskerrosta, se elää rinnakkain kuvien ja muotojen kanssa samalla taulukolla korvaamatta niitä, ja kyseisen kerroksen yleinen malli on käsitelty artikkelissa kaaviot, kuvat ja piirrokset HotXLS:ssä. Kaikki kolme reittiä toimituvat HotXLS Delphi -taulukkolaskentakomponentin mukana, joten valinta koskee sitä, miltä raportin pitäisi näyttää, eikä sitä, mitä kirjasto pystyy ilmaisemaan

Metodologinen pointti on se, joka kannattaa pitää. Kun binäärimuoto-ominaisuudella on olemassa oleva lukija, rakenna kirjoittaja lukijaa vasten, ei omaa spesifikaation lukemaasi vasten. Lukija koodaa vuosien kosketuksen tiedostoihin, joita oikeat sovellukset oikeasti tuottivat, mukaan lukien ne osat, jotka spesifikaatio ilmaisee löyhästi, ja kirjoittaja, joka tyydyttää sen, on paljon todennäköisemmin tyydyttävä myös Excelin