Technický článek

Úpravy grafů Excel bez ztráty ChartML v HotXLS

HotXLS si ponechává původní ChartML importovaného grafu Excel a při nezměněném typovém modelu ho přehrává bajt po bajtu, takže otevření a znovuuložení sešitu potichu neodstraní části grafu, které objektový model nereprezentuje. Upravte titulek, řadu nebo osu a HotXLS strukturálně sloučí nové typové uzly do původního stromu místo aby graf regeneroval od nuly

Právě tento rozdíl — replay při nedotknutí, merge při úpravě — dělá aplikaci v Delphi bezpečnou nasměrovat na grafy, které analytik postavil v Excelu. Regenerace grafu z typového modelu vždy ztratí cokoliv, co model nezná, a grafy Excel jsou plné věcí, které knihovna nezná: vlastní styly, extension listy, větve alternate content, formátování kvalifikované jmenným prostorem z doplňků

Proč znovuuložení sešitu zplošťuje jeho grafy?

Protože obvyklá implementace přečte, co rozumí, a zapíše, co rozumí. Vše, co je mezi — extLst z novější buildu Excelu, větev mc:AlternateContent, efekt tvaru, na který model nemá vlastnost — existuje v souboru, nemá domov v objektovém modelu a v čase uložení mizí. Uživatel vidí graf, který ztratil svůj gradient, vlastní data labels nebo 3D efekt, a sešit nedokáže vysvětlit proč

S PreserveUnsupportedParts zapnutým na sešitu ukládá HotXLS při importu původní UTF-8 bajty grafu spolu s délkou a 64bitovým otiskem modelovaného obsahu. Pokud se typový model do času uložení nezměnil, zapíše původní bajty zpět. Žádné přeuspořádání XML, žádný drift whitespace, žádná rezidentní UTF-16 kopie grafu visící v paměti pro graf, který nikdo neupravoval

var
  Workbook: TXLSXWorkbook;
  Chart: TXLSXChart;
begin
  Workbook := TXLSXWorkbook.Create(nil);
  try
    Workbook.PreserveUnsupportedParts := True;   // set before Open
    Workbook.Open('quarterly-review.xlsx');
    Chart := Workbook.Sheets[1].Charts[0];   // Sheets[] is 1-based
    if Chart.HasPreservedXml then
      Log('original ChartML retained; untouched charts replay exactly');
    Chart.Title := 'Revenue by region, Q3 2026';  // now the merge path runs
    Workbook.SaveAs('quarterly-review-out.xlsx');
  finally
    Workbook.Free;
  end;
end;

Co merge zachovává a co vlastní model

Pravidlem je vlastnictví. Veřejné uzly modelu — titulek, řady, caches, plot groups, osy — se rozhodují nově generovaným stromem. Nemodelované podstromy se přenášejí z původního. Tato asymetrie je záměrná a je to část, kterou chvíli trvá si osvojit: smazání řady nesmí vzkřísit starou řadu ze zachovaného XML, takže cokoliv, co model vlastní, se bere z modelu i když model říká „pryč"

Bez vlastnictví se obsah reinzeruje vedle odpovídajících uzlů, u kterých seděl, a extLst zůstává poslední uvnitř svého rodiče, protože tam ho vyžaduje schéma. Vyčištění známé vlastnosti — odstranění příznaku bold, shození barvy — se zachází jako s clear, nikoli jako s mezerou k vyplnění z původního stromu. Neznámé atributy ve stejném okolí si ponechají své místo

Markup-compatibility obsah dostává specifické zacházení. Při parsování HotXLS přeskakuje mc:Choice a čte mc:Fallback; pokud tato fallback větev obaluje plot group, kterou model zná, merge zapisuje nový typový obsah zpět do fallback podstromu. Bez tohoto kroku by uložení emitovalo novou plot group a nechalo starou uvnitř fallbacku, a graf by nesl dvě

Vyřazení jednoho grafu

ClearPreservedXml zahazuje původní XML a otisk pro jeden graf, takže další uložení přestaví tento graf čistě z typového modelu. Je to rozhodnutí per-chart; PreserveUnsupportedParts na úrovni sešitu stále řídí, zda se preservation stav buduje při importu

Sáhněte po něm, když chcete čistý graf spíše než věrný — například když graf v šabloně nese formátování ze starého firemního motivu a smyslem operace je ho zahodit. Nesahajte po něm jako po debug reflexu: graf, který se po úpravě renderuje špatně, je častěji otázkou modelování než preservation, a vyčištění preserved XML ničí důkaz

Kombinované grafy a druhá osa

AddPlotGroup staví uspořádané kombinované grafy, kde každá plot group si drží svou vlastní chart family a své vlastní přiřazení primární nebo sekundární osy. To je to, co potřebuje všudypřítomný obchodní graf: tržby jako sloupce na levé ose, marže v procentech jako čára na pravé

Grafy vystavují primární a sekundární kategorie a hodnotové osy plus series axis, přičemž typové nastavení kategorie, hodnoty, data a series axis pokrývá pozice, identifikátory, křižování, jednotky data, intervaly popisků a viditelnost. Starší ploché API — ChartType, AddSeries, plochá kolekce Series — stále adresuje primární plot group, takže existující kód funguje dál, zatímco model pod ním drží každou uspořádanou skupinu

var
  Chart: TXLSXChart;
  Line: TXLSXChartPlotGroup;
begin
  // Column chart anchored over rows 1..15, columns 5..12
  Chart := Sheet.Charts.Add(xlsxChartColumn, 'Revenue and margin',
    1, 5, 15, 12);
  Chart.AddSeries('Revenue', 'Data!$A$2:$A$13', 'Data!$B$2:$B$13');
  // Second plot group: a line, read against the secondary value axis
  Line := Chart.AddPlotGroup(xlsxChartLine, xlsxAxisSecondary);
  Line.AddSeries('Margin %', 'Data!$A$2:$A$13', 'Data!$C$2:$C$13');
end;

Dříve, než tento model existoval, otevření a znovuuložení kombinovaného grafu ho zploštilo do jedné chart family a ztratilo sekundární, datové a series osy. Odkazy na vzorce grafu a cached hodnoty řad nyní přežijí kopírování sešitů i open/save cykly a ukotvení grafů jsou matchována k jejich chart parts podle identifikátoru relationship — takže aplikace, která přeuspořádává relationship položky, už nehádže obsahy grafů mezi pozice listu

Past manual layout

Pokud pozicujete plot area, titulek, titulek osy nebo legendu ručně, zapište všechny čtyři souřadnice. Office vyžaduje x, y, w a h jako úplnou skupinu, kdykoli je přítomný kterýkoli z nich, a v opačném případě ignoruje celé manualLayout. HotXLS z toho důvodu vždy emituje plný obdélník a SetPositionAndSize ho nastaví a povolí jedním voláním

Další dva detaily následují Excel spíše než plnou volnost specifikace. Pozice se zapisuje s xMode a yMode nastavenými na edge, zatímco velikost používá factor pro wMode a hMode, protože to je to, co Excel zapisuje a co z ostatních kombinací převádí. A layoutTarget se emituje jen pro plot area, nikdy pro titulky nebo legendy, kde to implementační poznámky Microsoftu zakazují

Zapracování do round tripu sešitu

Preservation grafů je jednou instancí obecné politiky: knihovna, která upravuje dokumenty autorované jinde, by měla změnit to, o co byla požádána, a nic jiného. Stejné zdůvodnění řídí HotXLS u motivů, calc chainů a rozšíření listů, popsané v poznámkách k lossless round tripům pro motiv, extLst a calcChain a u VBA projektů a externích odkazů v preservaci VBA a externích odkazů. Pro samotnou authoring plochu grafů — vytváření grafů, umisťování obrázků a kreseb z Delphi — viz průvodce grafy, obrázky a kresby v HotXLS

HotXLS čte, upravuje a zapisuje grafy XLSX z nativního kódu Delphi a C++Builder bez instalace Excelu v počítači, což dělá z fidelity problém knihovny spíše než problém automatizace — stránka spreadsheet komponenty HotXLS má seznam funkcí grafů a zkušební stažení