Kirjaimellisella RGB-arvolla täytetty chart-sarja ei seuraa työkirjan teemaa. Vaihda teemaa ja sarja säilyttää vanhan värin. HotXLS käsittelee tämän binääri-XLS:ssä teeman värisinä chart-sarjojen täyttöinä: GelFrame-tietue, 4198 tai $1066, kirjoitetaan heti sarjalohkon AreaFormat-tietueen jälkeen ja se sisältää OfficeArt-skeemaindeksin sekä tint-arvon. Excel renderöi sarjan samalla tavalla kuin itse kirjoittamansa teeman mukaisen täytön
Mistä GelFrame-tietuenumero tulee?
GelFrame-tietuenumero on 4198 ($1066), etkä löydä sitä tietueen omasta spesifikaatiokohdasta. [MS-XLS] 2.4.131 kuvaa mitä GelFrame sisältää mutta toisin kuin useimmat tietueosiot se ei ilmoita rt-arvoa. Chart-alistreamin ABNF ei myöskään auta: se antaa vain tuotannon GELFRAME = 1*2GelFrame *Continue, joka nimeää tietueen mutta ei numeroi sitä. Numero on tietuenumeroiden enumeraatiotaulukossa, useita sivuja payloadia dokumentoivasta osiosta kauempana. Tuotanto on syytä lukea toisen kerran jokaisen lukijaa kirjoittavan silmin: se sallii yhden tai kaksi GelFrame-tietuetta, joita kumpaakin voivat valinnaisesti seurata Continue-tietueet, joten parseri joka olettaa tuotannolle yhden tietueen käsittelee väärin tiedoston jota se ei itse kirjoittanut. HotXLS emittoi täsmälleen yhden GelFramen teeman mukaiselle sarjalle, kuten Excel tekee yksinkertaiselle kiinteälle teematäytölle, ja sen dekooderi käsittelee tietueen itsenäisenä payloadina eikä oleta kiinteää lukumäärää
GelFrame-payloadin sisällä: kaksi OfficeArt-ominaisuustaulukkoa
GelFrame-payload on kaksi peräkkäistä OfficeArt-ominaisuustaulukkoa: OfficeArtFOPT (nimeltään OPT1), jota seuraa OfficeArtTertiaryFOPT (OPT2). Kumpikin taulukko alkaa kaksitavuisella ominaisuuksien määrällä ja jatkuu niin monella kuusitavuisella FOPTE-alkiolla, jossa jokaisessa on kaksitavuinen opid ja nelitavuinen op. opid-arvon bitti 15 on fComplex: kun se on asetettu, op-arvo on tavupituus ja kiinteiden alkioiden jälkeen seuraa muuttuvan pituuden loppuosa. Dekooderi joka ohittaa nämä loput menettää kohdistuksen ja lukee roskana opid-arvoja kaikelle ensimmäisen complex-ominaisuuden jälkeen
Teematäyttö ilmaistaan kolmella ominaisuudella jotka on jaettu molempien taulukoiden yli sekä yhdellä joka ilmoittaa täytön lajin. HotXLS kirjoittaa 28 tavuun neljä ominaisuutta ilman complex-loppuosia:
fillType$0180 OPT1:ssä, arvoksi 1 (msofillSolid) asetettunafillColor$0181 OPT1:ssä, litistetty RGB jonka vanhempi tai teemaa ymmärtämätön kuluttaja piirtääfillColorExt$019E OPT2:ssa, alkuperäinen teeman värifillColorExtMod$01A0 OPT2:ssa, alkuperäiseen väriin kohdistettu tint tai shade
Jako on formaatin tarkoituksellinen ominaisuus eikä toteutuksen sattuma: [MS-ODRAW] 2.2.2 kuvaa teeman kolmikon litteänä värinä, perusvärinä ja muunnoksena, joten teemat ymmärtävä kuluttaja laskee täytön uudelleen ja muutoin vain järkevästi maalaava kuluttaja saa silti jotakin. Ympäröivät opidit noudattavat samaa mallia ja käyttävät identtistä numerointia vanhoissa ja nykyisissä [MS-ODRAW]-versioissa, mikä helpottaa kahden revision rinnakkaislukemista: fillOpacity $0182, fillBackColor $0183, fillShadeType $019C, fillBackColorExt $01A2 ja fillBackColorExtMod $01A4
Miksi skeemaindeksi on punaisessa tavussa?
Koska OfficeArtCOLORREF määritellään tavun offsetin eikä numeerisen arvon kautta: punainen tavussa 0, vihreä tavussa 1, sininen tavussa 2 ja liput tavussa 3. Lue tämä rakenne little-endian DWORDina, kuten jokainen FOPTE:n op-arvo luetaan, ja punaisesta tulee vähiten merkitsevä tavu. [MS-ODRAW]-dokumentin toimiva lineColor-esimerkki vahvistaa tämän. Siksi fSchemeIndex, joka on lippu E, saa numeerisen arvon $08000000 ja itse skeemaindeksi sijoitetaan punaiseen tavuun vihreän ja sinisen ollessa pakollisesti nollia. Accent1 on siis op-arvo $08000004 eikä $00000004 eikä varsinkaan $04000000
Teemaindeksien järjestys jonka spesifikaatio kieltäytyy määrittelemästä
Spesifikaatio kutsuu skeemaindeksin järjestystä hostin määrittelemäksi eikä anna taulukkoa, mikä tarkoittaa ettei pelkkä tavuasettelu riitä yhteentoimivuuteen Excelin kanssa. HotXLS käyttää spreadsheet-teeman järjestystä, joka tekee kierroksen oikeiden Excel-tiedostojen kanssa:
- 0 = lt1, 1 = dk1, 2 = lt2, 3 = dk2
- 4–9 = accent1–accent6
- 10 = hlink, 11 = folHlink
Tint ja shade: MSOTINTSHADE-payload
fillColorExtMod-op on MSOTINTSHADE-arvo, joka koodaa suunnan ja määrän yhteen DWORD-arvoon signed fractionin sijaan. Arvo $20000000 tarkoittaa muuttamatonta. Vaaleuttava tint on $02F4 shl 16 or amount shl 8 or $10 (MSOTINT); tummentava tint on samanmuotoinen mutta yläosassa on $01F4 (MSOSHADE). amount-tavu kulkee vastakkaiseen suuntaan kuin intuitio: $FF tarkoittaa muuttumatonta ja $00 täyttä muunnosta. HotXLS normalisoi sen yhdeksi DrawingML-tyyliseksi doubleksi jossa positiivinen vaalentaa ja negatiivinen tummentaa, käyttäen plus- tai miinusarvoa (255 - amount) / 255. Kuvaus on täsmällinen niille arvoille joita Excelin käyttöliittymä oikeasti tarjoaa, minkä vuoksi kierros on häviötön eikä likimäärin häviötön: tuttu "Lighter 40%" on amount 153 ja (255 - 153) / 255 on 0,4 ilman pyöristysvirhettä kumpaankaan suuntaan. Shade amount-arvolla 191 palaa arvona -64/255. Tässä encoder, rajattuna lailliseen alueeseen:
if Tint > 0 then // MSOTINT - vaaleampi
TintOp := LongWord($02F4) shl 16 or
(LongWord(Round(255 * (1 - Tint))) shl 8) or $10
else if Tint < 0 then // MSOSHADE - tummempi
TintOp := LongWord($01F4) shl 16 or
(LongWord(Round(255 * (1 + Tint))) shl 8) or $10
else
TintOp := $20000000; // MSOCOLORMODUNDEFINED
Teematäytön asettaminen ja lukeminen Delphillä
Kirjoituspuolella teematäyttö on kaksi uutta kenttää sarjakohtaisessa tyylitietueessa. TXLSChartSeriesStyleInfo sai kentät HasFillTheme, FillThemeColor ja FillThemeTint, ja builder emittoi GelFramen vain kun sekä HasStyle että HasFillTheme on asetettu. Jos asetat lisäksi eksplisiittisen FillRgb-arvon, se menee OPT1:n fillColor-kenttään sellaisenaan; jos et aseta sitä, HotXLS litistää värin itse sisäänrakennetun oletus-Office-teemataulukon kautta tint kohdistettuna, joten vain teeman sisältävä sarja saa silti järkevän litteän värin kuluttajille jotka jättävät OPT2:n huomiotta. Huomaa Default()-initialisaatio, koska TXLSChartSeriesInfo sisältää hallinnoituja kenttiä ja sen tavalliset Boolean-jäsenet ovat muuten pinoroskia:
var
Wb: TXLSWorkbook;
Series: array [0..1] of TXLSChartSeriesInfo;
begin
Wb := TXLSWorkbook.Create;
try
Wb.Sheets.Add.Name := 'Data';
Series[0] := Default(TXLSChartSeriesInfo); // älä koskaan kutsu FillCharia tälle tietueelle
Series[0].Name := 'Explicit';
Series[0].Categories := 'Data!$A$1:$A$2';
Series[0].Values := 'Data!$B$1:$B$2';
Series[0].HasStyle := True;
Series[0].Style.HasFill := True;
Series[0].Style.FillRgb := $C47244; // accent1, punainen matalassa tavussa
Series[0].Style.HasFillTheme := True;
Series[0].Style.FillThemeColor := 4; // accent1
Series[0].Style.FillThemeTint := 0.4; // Lighter 40%
Series[1] := Default(TXLSChartSeriesInfo);
Series[1].Name := 'ThemeOnly';
Series[1].Categories := 'Data!$A$1:$A$2';
Series[1].Values := 'Data!$C$1:$C$2';
Series[1].HasStyle := True;
Series[1].Style.HasFillTheme := True; // ei eksplisiittistä RGB:tä: litistetään
Series[1].Style.FillThemeColor := 8; // accent5
Wb.Sheets.AddChartSheet('Themed', xlsChartTypeColumn, '', '', '', Series);
Wb.SaveAs('themed.xls');
finally
Wb.Free;
end;
end;
Takaisin lukeminen kulkee saman chart-mallin kautta jota muu HotXLS-chartien tarkastus käyttää. GetChartModel palauttaa omistetun TXLSChartModel-olion joka vapautetaan, ja jokainen TXLSChartSeries tarjoaa HasFillTheme-, FillThemeColor- ja FillThemeTint-arvot rinnakkain OPT1:n fillColor-arvosta dekoodatun FillRgb-arvon kanssa, joka voittaa kyseisen sarjan AreaFormat-värin. Samat kolme arvoa päätyvät myös kanoniseen semanttiseen snapshot-malliin kenttinä SolidFillThemeSet, SolidFillThemeColor ja SolidFillThemeTint, joten työkirjavertailu näkee teemamuutoksen teemamuutoksena eikä selittämättömänä RGB-ajautumisena. Jos tulet XLSX-puolelta, tämä on binääriformaatin vastine tyylille joka kuvataan HotXLS:n Delphi-oppaassa Excel-charteista, kuvista ja piirroksista:
Wb := TXLSWorkbook.Create;
try
Wb.Open('themed.xls');
Model := Wb.Sheets[2]._Chart.GetChartModel;
try
Ser := Model.GetSeries(0);
if Ser.HasFillTheme then
begin
WriteLn(Ser.FillThemeColor); // 4 = accent1
WriteLn(Ser.FillThemeTint:0:3); // 0.400
WriteLn(IntToHex(Ser.FillRgb, 6)); // C47244, OPT1:n fillColor
end;
finally
Model.Free;
end;
finally
Wb.Free;
end;
Mitä teeman täyttö binääri-XLS:ssä ei lupaa?
Kolme rehellistä rajaa. Ensinnäkin ja tärkeimpänä jokaiselle joka auditoi tätä koodia: paikallisen aineiston yksikään näytetiedosto ei sisällä GelFrame-tietuetta. Ehdollisen formatoinnin näytteessä olevat tavuparin 66 10 yksitoista esiintymää ovat tietueiden rajojen ulkopuolella ja täyden stream-dumpin tulos on nolla osumaa. Tässä kuvattu bittiasettelu johdettiin spesifikaatiosta ja lukittiin sitten kolmella tavalla: dekoodauksen symmetrialla builderin tulosteessa, käsin rakennetuilla tavutesteillä jotka syöttävät synteettisen $1066-payloadin suoraan dekooderille ja tarkan litistetyn RGB-arvon assertionilla. Tämä on heikompaa näyttöä kuin kaapattu Excel-tiedosto, ja niin kannattaa sanoa sen sijaan että vihjaisi muuta. Toiseksi vain teeman sisältävän täytön litistys käyttää sisäänrakennettua oletus-Office-teemataulukkoa eikä työkirjasta luettua teemaosaa, koska binääri-XLS:ssä ei ole theme partia siinä mielessä kuin paketoidussa XLSX:ssä — jos tarvitset työkirjan oman teeman ohjaamaan litteää väriä, anna FillRgb itse. Kolmanneksi dekooderi hyväksyy GelFramen vain sarjalohkon sisällä; sama tietue voi esiintyä chart-alueella tai axis-framessa, ja sen hyväksyminen siellä kohdistaisi taustatäytön hiljaisesti sarjalle, joten nämä ohitetaan. fillColorExt ilman $08000000-lippua käsitellään samoin tavallisena extended-värinä eikä se koskaan aseta HasFillTheme-arvoa. Työkirjoille joissa chart on laadittu XLSX-maailmassa ja vain kulkee tämän kautta artikkelin Excel-chartien muokkaaminen ChartML:n säilyttäen preservation-polku on turvallisempi, ja näiden tietueiden säiliö käsitellään artikkelissa OLE2-compound-tiedostojen lukeminen Delphissä ilman COM IStoragea
Teeman väriset chart-täytöt, GelFrame-enkooderi ja -dekooderi sekä koko BIFF8-chart-alistreamin builder toimitetaan HotXLS Delphi spreadsheet component -komponentin osana Delphille ja C++Builderille, ja se lukee ja kirjoittaa XLS-, XLSX- ja ODS-tiedostoja ilman asennettua Exceliä