Articolo tecnico

Modificare grafici Excel senza perdere ChartML in HotXLS

HotXLS conserva il ChartML originale di un grafico Excel importato e lo riproduce byte per byte quando nulla nel modello tipizzato è cambiato, così aprire e risalvare una cartella di lavoro non smantella silenziosamente le parti di un grafico che il modello a oggetti non rappresenta. Modifica un titolo, una serie o un asse e HotXLS fonde strutturalmente i nuovi nodi tipizzati nell'albero originale anziché rigenerare il grafico da zero

Quella distinzione — riproduci quando non toccato, fondi quando modificato — è ciò che rende sicuro puntare un'applicazione Delphi su grafici che un analista ha costruito in Excel. Rigenerare un grafico da un modello tipizzato perde sempre ciò che il modello non conosce, e i grafici Excel sono pieni di cose che una libreria non conosce: stili personalizzati, liste di estensioni, branch di alternate content, formattazione qualificata da namespace che proviene da componenti aggiuntivi

Perché risalvare una cartella di lavoro appiattisce i suoi grafici?

Perché l'implementazione consueta legge ciò che capisce e scrive ciò che capisce. Tutto ciò che sta in mezzo — una extLst da una build Excel più recente, un branch mc:AlternateContent, un effetto di forma per cui il modello non ha una proprietà — esiste nel file, non ha casa nel modello a oggetti, e scompare al salvataggio. L'utente vede un grafico che ha perso il proprio gradiente, le proprie etichette dati personalizzate o il proprio effetto 3D, e la cartella di lavoro non sa spiegare perché

Con PreserveUnsupportedParts attivato sulla cartella di lavoro, HotXLS archivia i byte UTF-8 originali del grafico all'importazione insieme a una lunghezza e a una fingerprint a 64 bit del contenuto modellato. Se il modello tipizzato non è cambiato entro il salvataggio, riscrive i byte originali. Nessun riordino XML, nessuna deriva di whitespace, nessuna copia UTF-16 residente del grafico in memoria per un grafico che nessuno ha modificato

Diagramma della conservazione ChartML HotXLS in Delphi dove i grafici invariati riproducono i byte originali e i grafici modificati fondono nodi del modello tipizzato nell'XML conservato, mentre una ricostruzione dal solo modello perde i rami extLst e AlternateContent
HotXLS memorizza i byte ChartML originali all'import e li riproietta intatti, oppure fonde modifiche tipizzate nell'albero preservato quando il modello è cambiato
var
  Workbook: TXLSXWorkbook;
  Chart: TXLSXChart;
begin
  Workbook := TXLSXWorkbook.Create;
  try
    Workbook.PreserveUnsupportedParts := True;   // imposta prima di Open
    Workbook.Open('quarterly-review.xlsx');
    Chart := Workbook.Sheets[1].Charts[0];   // Sheets[] è con base 1
    if Chart.HasPreservedXml then
      Log('original ChartML retained; untouched charts replay exactly');
    Chart.Title := 'Revenue by region, Q3 2026';  // ora viene eseguito il percorso di merge
    Workbook.SaveAs('quarterly-review-out.xlsx');
  finally
    Workbook.Free;
  end;
end;

Cosa conserva il merge e cosa possiede il modello

La regola è la proprietà. I nodi pubblici del modello — titolo, serie, cache, plot group, assi — sono decisi dall'albero appena generato. I sottoalberi non modellati sono riportati dall'originale. Quella asimmetria è deliberata, ed è la parte che richiede un momento per essere interiorizzata: cancellare una serie non deve resuscitare la vecchia serie dal XML preservato, così qualsiasi cosa il modello possiede è presa dal modello anche quando il modello dice «sparita»

Il contenuto non posseduto è reinserito accanto ai nodi con cui combaciava a fianco, e extLst resta ultimo dentro il proprio genitore perché è lì che lo schema lo richiede. Cancellare una proprietà nota — togliere un flag di grassetto, rimuovere un colore — è trattato come cancellazione, non come un vuoto da riempire dall'albero originale. Gli attributi sconosciuti nello stesso intorno conservano il proprio posto

Il contenuto markup-compatibility riceve gestione specifica. In fase di parse, HotXLS salta mc:Choice e legge mc:Fallback; se quel branch di fallback avvolge un plot group che il modello conosce, il merge riscrive il nuovo contenuto tipizzato nel sottoalbero di fallback. Senza quel passo, un salvataggio emetterebbe il nuovo plot group e lascerebbe quello vecchio dentro il fallback, e il grafico ne porterebbe due

Escludere un grafico

ClearPreservedXml droppa il XML originale e la fingerprint per un solo grafico, così il prossimo salvataggio ricostruisce quel grafico puramente dal modello tipizzato. È una decisione per-grafico; il flag a livello di cartella di lavoro PreserveUnsupportedParts continua a governare se lo stato di preservazione viene costruito all'importazione

Raggiungilo quando vuoi un grafico pulito anziché uno fedele — per esempio quando un grafico template porta formattazione da un vecchio tema aziendale e il punto dell'operazione è disfarsene. Non raggiungerlo come riflesso di debug: un grafico che si renderizza male dopo una modifica è più spesso una questione di modellazione che di preservazione, e cancellare il XML preservato distrugge le prove

Grafici combinati e il secondo asse

AddPlotGroup costruisce grafici combinati ordinati, dove ciascun plot group conserva la propria famiglia di grafico e la propria assegnazione di asse primario o secondario. È ciò di cui ha bisogno l'onnipresente grafico aziendale: ricavi come colonne sull'asse sinistro, percentuale di margine come linea sull'asse destro

I grafici espongono assi categoria e valore primari e secondari più un asse serie, con impostazioni tipizzate per categoria, valore, data e asse serie che coprono posizioni, identificatori, intersezioni, unità di data, intervalli di etichetta e visibilità. La vecchia API piatta — ChartType, AddSeries, la collezione piatta Series — continua a indirizzare il plot group primario, così il codice esistente continua a funzionare mentre il modello sotto tiene ogni gruppo ordinato

Diagramma di un grafico combinato HotXLS in Delphi con colonne di ricavi da AddSeries sull'asse dei valori primario e una linea di margine da AddPlotGroup sull'asse dei valori secondario, mentre la vecchia API piatta raggiunge solo il gruppo uno
Ogni chiamata AddPlotGroup aggiunge in append un gruppo ordinato con la propria famiglia di grafici e assegnazione dell'asse primario o secondario mentre l'API piatta continua a indirizzare il gruppo uno
var
  Chart: TXLSXChart;
  Line: TXLSXChartPlotGroup;
begin
  // Grafico a colonne ancorato sulle righe 1..15, colonne 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');
  // Secondo plot group: una linea, letta contro l'asse valori secondario
  Line := Chart.AddPlotGroup(xlsxChartLine, xlsxAxisSecondary);
  Line.AddSeries('Margin %', 'Data!$A$2:$A$13', 'Data!$C$2:$C$13');
end;

Prima che questo modello esistesse, aprire e risalvare un grafico combinato lo collassava in un'unica famiglia di grafico e perdeva gli assi secondari, di data e di serie. I riferimenti alle formule di grafico e i valori cached delle serie ora sopravvivono alle copie della cartella di lavoro e ai cicli di apertura/salvataggio, e gli ancoraggi dei grafici sono abbinati alle proprie parti grafico per identificatore di relazione — così un'applicazione che riordina le voci di relazione non scambia più i contenuti dei grafici tra le posizioni dei fogli di lavoro

La trappola del manual layout

Se posizioni a mano l'area del tracciato, il titolo, il titolo dell'asse o la legenda, scrivi tutte e quattro le coordinate. Office richiede x, y, w e h come gruppo completo ogni volta che uno qualsiasi di essi è presente, e ignora l'intero manualLayout in caso contrario. HotXLS emette sempre il rettangolo completo per quel motivo, e SetPositionAndSize lo imposta e lo abilita in una sola chiamata

Diagramma della regola di layout manuale HotXLS in Delphi dove x, y, w e h devono arrivare come gruppo completo o Office ignora l'intero elemento manualLayout, con modalità edge e factor e layoutTarget limitato all'area del tracciato
Office applica un layout manuale solo quando x, y, w e h arrivano come gruppo completo, ed è per questo che HotXLS emette l'intero rettangolo

Altri due dettagli seguono Excel anziché la piena latitudine della specifica. La posizione è scritta con xMode e yMode impostati a edge mentre la dimensione usa factor per wMode e hMode, perché è ciò che Excel scrive e in cui converte le altre combinazioni. E layoutTarget è emesso solo per l'area del tracciato, mai per titoli o leggende, dove le note di implementazione Microsoft lo vietano

Inserire questo in un round trip della cartella di lavoro

La preservazione dei grafici è un'istanza di una policy generale: una libreria che modifica documenti scritti altrove dovrebbe cambiare ciò che le è stato chiesto di cambiare e null'altro. Lo stesso ragionamento guida HotXLS su tema, catene di calcolo ed estensioni dei fogli di lavoro, descritto nelle note sui round trip lossless per tema, extLst e calcChain, e sui progetti VBA e sui collegamenti esterni in preservare VBA e collegamenti esterni. Per la superficie di authoring dei grafici stessa — creare grafici, collocare immagini e disegni da Delphi — vedi la guida sui grafici, immagini e disegni in HotXLS

HotXLS legge, modifica e scrive grafici XLSX da codice Delphi e C++Builder nativo senza alcuna installazione di Excel sulla macchina, il che è ciò che rende la fedeltà un problema di libreria anziché di automazione — la pagina del componente spreadsheet HotXLS ha la lista delle funzionalità dei grafici e un download di prova