Teknisk artikel

Redigera Excel-diagram utan att förlora ChartML i HotXLS

HotXLS behåller den ursprungliga ChartML för ett importerat Excel-diagram och spelar tillbaka den byte för byte när ingenting i den typade modellen ändrats, så att öppna och spara om en arbetsbok inte tyst tar bort de delar av ett diagram som objektmodellen inte representerar. Redigera en titel, en serie eller en axel så sammanfogar HotXLS strukturellt de nya typade noderna in i det ursprungliga trädet i stället för att regenerera diagrammet från grunden

Den skillnaden — återplaya när orörd, sammanfoga när redigerad — är vad som gör en Delphi-applikation säker att rikta mot diagram en analytiker byggde i Excel. Att regenerera ett diagram från en typad modell förlorar alltid vad modellen inte vet om, och Excel-diagram är fulla av saker ett bibliotek inte vet om: anpassade stilar, tilläggslistor, alternativa innehållsgrenar, namnrymdskvalificerad formatering från tillägg

Varför plattar omsparande av en arbetsbok ut dess diagram?

Eftersom den vanliga implementeringen läser vad den förstår och skriver vad den förstår. Allt däremellan — en extLst från en nyare Excel-bygge, en mc:AlternateContent-gren, en formeekt modellen inte har någon egenskap för — existerar i filen, har inget hem i objektmodellen och försvinner vid sparande. Användaren ser ett diagram som förlorat sin toning, sina anpassade dataetiketter eller sin 3D-effekt, och arbetsboken kan inte förklara varför

Med PreserveUnsupportedParts aktiverat på arbetsboken lagrar HotXLS de ursprungliga UTF-8-diagrambytena vid import tillsammans med en längd och ett 64-bitars fingeravtryck av det modellerade innehållet. Om den typade modellen inte har ändrats vid sparandet skriver den tillbaka de ursprungliga byten. Ingen XML-omordning, inget blankstegsdift, ingen kvarboende UTF-16-kopia av diagrammet runt i minnet för ett diagram ingen redigerade

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;

Vad sammanfogningen behåller och vad modellen äger

Regeln är ägandeskap. Publika modellnoder — titel, serier, cachar, plottgrupper, axlar — beslutas av det nygenererade trädet. Omodellerade underträd bärs över från originalet. Den asymmetrin är avsiktlig, och det är den del som tar en stund att internalisera: att ta bort en serie får inte återuppliva den gamla serien från den bevarade XML:en, så allting modellen äger tas från modellen även när modellen säger "borta"

Ej ägt innehåll återinfogas bredvid de matchade noder det satt bredvid, och extLst förblir sist inom sin förälder eftersom det är där schemat kräver det. Att rensa en känd egenskap — ta bort en fet flagga, släppa en färg — behandlas som en rensning, inte som ett mellanrum att fylla från det ursprungliga trädet. Okända attribut i samma omgivning behåller sin plats

Markup-compatibility-innehåll får specifik hantering. Vid tolkning hoppar HotXLS över mc:Choice och läser mc:Fallback; om den grenen sveper in en plottgrupp modellen känner skriver sammanfogningen det nya typade innehållet tillbaka in i reservunderträdet. Utan det steget skulle ett sparande emittera den nya plottgruppen och lämna den gamla inuti reserven, och diagrammet skulle bära två

Att lämna ett diagram utanför

ClearPreservedXml släpper den ursprungliga XML:en och fingeravtrycket för ett diagram, så nästa sparande bygger om det diagrammet rent från den typade modellen. Det är ett per-diagram-beslut; arbetsboksnivåns PreserveUnsupportedParts styr fortfarande huruvida bevarandetillstånd byggs vid import

Sträck dig efter det när du vill ha ett rent diagram i stället för ett troget — till exempel när ett malldiagram bär formatering från ett gammalt företagstema och poängen med operationen är att kasta det. Sträck dig inte efter det som en felsökningsreflex: ett diagram som renderar fel efter en redigering är oftare en modelleringsfråga än en bevarandefråga, och att rensa den bevarade XML:en förstör bevisningen

Kombinationsdiagram och den andra axeln

AddPlotGroup bygger ordnade kombinationsdiagram, där varje plottgrupp behåller sin egen diagramfamilj och sin egen primära eller sekundära axeltilldelning. Det är vad det allestädes närvarande affärsdiagrammet behöver: intäkter som kolumner på vänsteraxeln, marginalprocent som en linje på höger

Diagram exponerar primära och sekundära kategori- och värdeaxlar plus en serieaxel, med typade kategori-, värde-, datum- och serieaxelegenskaper som täcker positioner, identifierare, korsningar, datumenheter, etikettintervall och synlighet. Det äldre platta API:et — ChartType, AddSeries, den platta Series-samlingen — adresserar fortfarande den primära plottgruppen, så befintlig kod fungerar fortfarande medan modellen under håller varje ordnad grupp

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;

Innan denna modell existerade kollapsade öppnande och omsparande av ett kombinationsdiagram det till en diagramfamilj och tappade de sekundära, datum- och serieaxlarna. Diagramformelreferenser och cachade serievärden överlever numera arbetsbokskopior och öppna/stäng-cykler likaså, och diagramankare matchas till sina diagrampar via relationsidentifierare — så en applikation som ordnar om relationsposter byter inte längre diagraminnehåll mellan kalkylbladspositioner

Fällan med manuell layout

Om du positionerar ett plotområde, en titel, en axeltiteln eller en förklaring för hand, skriv alla fyra koordinater. Office kräver x, y, w och h som en komplett grupp närhelst någon av dem finns närvarande, och ignorerar hela manualLayout annars. HotXLS emitterar alltid den fullständiga rektangeln av den anledningen, och SetPositionAndSize sätter och aktiverar den i ett anrop

Två ytterligare detaljer följer Excel i stället för specifikationens fulla latitud. Position skrivs med xMode och yMode satta till edge medan storlek använder factor för wMode och hMode, eftersom det är vad Excel skriver och vad det konverterar andra kombinationer till. Och layoutTarget emitteras endast för plotområdet, aldrig för titlar eller förklaringar, där Microsofts implementeringsnoter förbjuder det

Att passa in detta i en arbetsboksrundtur

Diagrambevarande är en instans av en allmän policy: ett bibliotek som redigerar dokument författade annorstädes bör ändra vad det blev bett att ändra och ingenting annat. Samma resonemang driver HotXLS på teman, beräkningskedjor och kalkylbladstillägg, beskrivet i noterna om förlustfria rundturer för tema, extLst och calcChain, och om VBA-projekt och externa länkar i bevara VBA och externa länkar. För själva diagramförfattarytan — skapa diagram, placera bilder och ritningar från Delphi — se genomgången av diagram, bilder och ritningar i HotXLS

HotXLS läser, redigerar och skriver XLSX-diagram från inbyggd Delphi- och C++Builder-kod utan Excel-installation på maskinen, vilket är vad som gör fidelity till ett biblioteksproblem i stället för ett automatiseringsproblem — HotXLS kalkylbladskomponentsida har diagramfunktionslistan och en testnedladdning