Article technique

Éditer des Graphiques Excel Sans Perdre le ChartML avec HotXLS

HotXLS conserve le ChartML original d'un graphique Excel importé et le rejoue octet pour octet quand rien dans le modèle typé n'a changé, donc ouvrir et réenregistrer un classeur ne supprime pas silencieusement les parties d'un graphique que le modèle objet ne représente pas. Éditez un titre, une série ou un axe et HotXLS fusionne structurellement les nouveaux nœuds typés dans l'arbre original plutôt que de régénérer le graphique à partir de zéro

Cette distinction — rejouer quand inchangé, fusionner quand édité — est ce qui rend une application Delphi sûve à pointer sur des graphiques qu'un analyste a construits dans Excel. Régénérer un graphique depuis un modèle typé perd toujours ce que le modèle ne connaît pas, et les graphiques Excel sont pleins de choses qu'une bibliothèque ne connaît pas : styles personnalisés, listes d'extensions, branches de contenu alternatif, mise en forme qualifiée par espace de noms provenant de modules complémentaires

Pourquoi réenregistrer un classeur aplatit-il ses graphiques ?

Parce que l'implémentation habituelle lit ce qu'elle comprend et écrit ce qu'elle comprend. Tout ce qui se trouve entre — un extLst d'une version Excel plus récente, une branche mc:AlternateContent, un effet de forme pour lequel le modèle n'a aucune propriété — existe dans le fichier, n'a pas de foyer dans le modèle objet, et disparaît à la sauvegarde. L utilisateur voit un graphique qui a perdu son dégradé, ses étiquettes de données personnalisées ou son effet 3D, et le classeur ne peut pas expliquer pourquoi

Avec PreserveUnsupportedParts activé sur le classeur, HotXLS stocke les octets UTF-8 originaux du graphique à l'importation avec une longueur et une empreinte 64 bits du contenu modélisé. Si le modèle typé n'a pas changé à la sauvegarde, il réécrit les octets originaux. Pas de réordonnancement XML, pas de dérive d'espacement, pas de copie UTF-16 résidente du graphique qui traîne en mémoire pour un graphique que personne n'a édité

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;

Ce que la fusion conserve et ce que le modèle possède

La règle est la propriété. Les nœuds publics du modèle — titre, séries, caches, groupes de traçage, axes — sont décidés par le nouvel arbre généré. Les sous-arbres non modélisés sont reportés depuis l'original. Cette asymétrie est délibérée, et c'est la partie qui prend un moment à intérioriser : supprimer une série ne doit pas ressusciter l'ancienne série depuis le XML préservé, donc tout ce que le modèle possède est pris depuis le modèle même quand le modèle dit « disparu »

Le contenu non possédé est réinséré à côté des nœuds correspondants auprès desquels il se trouvait, et extLst reste en dernier à l'intérieur de son parent car c'est là que le schéma l'exige. Effacer une propriété connue — retirer un indicateur de gras, abandonner une couleur — est traité comme un effacement, pas comme un manque à remplir depuis l'arbre original. Les attributs inconnus dans le même voisinage gardent leur place

Le contenu de compatibilité de balisage reçoit un traitement spécifique. À l'analyse, HotXLS saute mc:Choice et lit mc:Fallback ; si cette branche de repli enveloppe un groupe de traçage que le modèle connaît, la fusion réécrit le nouveau contenu typé dans le sous-arbre de repli. Sans cette étape une sauvegarge émettrait le nouveau groupe de traçage et laisserait l'ancien à l'intérieur du repli, et le graphique porterait les deux

Retirer un graphique du dispositif

ClearPreservedXml abandonne le XML original et l'empreinte pour un graphique, donc la prochaine sauvegarde reconstruit ce graphique purement depuis le modèle typé. C'est une décision par graphique ; le PreserveUnsupportedParts au niveau classeur gouverne encore si l'état de préservation est construit à l'importation

Atteignez-le quand vous voulez un graphique propre plutôt que fidèle — par exemple quand un graphique de modèle porte la mise en forme d'un ancien thème d'entreprise et que le propos de l'opération est de la rejeter. Ne l'atteignez pas comme réflexe de débogage : un graphique qui se rend mal après une édition est plus souvent une question de modélisation qu'une question de préservation, et effacer le XML préservé détruit la preuve

Graphiques combinés et le second axe

AddPlotGroup construit des graphiques combinés ordonnés, où chaque groupe de traçage garde sa propre famille de graphique et sa propre assignation d'axe primaire ou secondaire. C'est ce dont le graphique commercial omniprésent a besoin : le chiffre d'affaires en colonnes sur l'axe gauche, la marge en pourcentage en ligne sur la droite

Les graphiques exposent les axes de catégorie et de valeur primaires et secondaires plus un axe de séries, avec des réglages typés de catégorie, valeur, date et axe de séries couvrant positions, identifiants, croisements, unités de date, intervalles d'étiquette et visibilité. L ancienne API plate — ChartType, AddSeries, la collection Series plate — adresse toujours le groupe de traçage primaire, donc le code existant continue de fonctionner tandis que le modèle en dessous détient chaque groupe ordonné

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;

Avant que ce modèle n'existe, ouvrir et réenregistrer un graphique combiné le réduisait à une seule famille de graphique et perdait les axes secondaire, de date et de séries. Les références de formule de graphique et les valeurs de séries en cache survivent maintenant aux copies de classeur et aux cycles ouvrir/enregistrer également, et les ancres de graphique sont mises en correspondance avec leurs parties de graphique par identifiant de relation — donc une application qui réordonne les entrées de relation ne permute plus les contenus de graphique entre les positions de feuille de calcul

Le piège de la disposition manuelle

Si vous positionnez une zone de traçage, un titre, un titre d'axe ou une légende à la main, écrivez les quatre coordonnées. Office exige x, y, w et h comme un groupe complet toutes les fois que l'un d'entre eux est présent, et ignore le manualLayout entier autrement. HotXLS émet toujours le rectangle complet pour cette raison, et SetPositionAndSize le règle et l'active en un seul appel

Deux détails supplémentaires suivent Excel plutôt que la pleine latitude de la spécification. La position est écrite avec xMode et yMode réglés à edge tandis que la taille utilise factor pour wMode et hMode, car c'est ce qu'Excel écrit et ce en quoi il convertit les autres combinaisons. Et layoutTarget n'est émis que pour la zone de traçage, jamais pour les titres ou légendes, où les notes d'implémentation Microsoft l'interdisent

Intégrer cela dans un aller-retour de classeur

La préservation des graphiques est une instance d'une politique générale : une bibliothèque qui édite des documents créés ailleurs devrait changer ce qu'on lui a demandé de changer et rien d'autre. Le même raisonnement dirige HotXLS sur les thèmes, les chaînes de calcul et les extensions de feuille de calcul, décrit dans les notes sur les allers-retours sans perte pour thème, extLst et calcChain, et sur les projets VBA et liaisons externes dans la préservation des VBA et liaisons externes. Pour la surface de création de graphiques elle-même — créer des graphiques, placer images et dessins depuis Delphi — voir la visite guidée des graphiques, images et dessins dans HotXLS

HotXLS lit, édite et écrit les graphiques XLSX depuis du code Delphi et C++Builder natif sans aucune installation Excel sur la machine, ce qui est ce qui fait de la fidélité un problème de bibliothèque plutôt qu'un problème d'automation — la page composant tableur HotXLS a la liste des fonctionnalités graphiques et un essai téléchargeable