Teknisk artikel

Excel-minidiagram i Delphi: HotXLS och x14-tillägget

HotXLS skapar Excel-minidiagram (sparklines) — de minidiagram Excel ritar inuti en enskild cell — från Delphi och C++Builder med ett enda anrop: TXLSXWorksheet.AddSparklineGroup bygger en minidiagramgrupp över ett dataintervall, och när arbetsboken sparas skrivs den som ett x14-tilläggsblock inuti kalkylbladets extLst, vilket renderas av Excel 2010 och senare medan äldre läsare hoppar över det utan problem. Inga diagramobjekt, inga ritningsdelar, inga ankare

Scenariot som gör minidiagram värda att ha är alltid detsamma. En instrumentpanels-arbetsbok innehåller några hundra rader, en per produkt, region eller konto, med tolv månadssiffror vardera, och någon vill ha en trendfigur i slutet av varje rad. Om du modellerar detta med riktiga diagram skapar du hundratals DrawingML-diagramdelar, var och en med sin egen XML-del, relation och ankargeometri, för att inte tala om vad det gör med filstorlek och öppningstid. En minidiagramgrupp är ett enda XML-block som säger "rita en liten linje från B2:M2 till N2, och från B3:M3 till N3", vilket kan upprepas billigt för så många rader du har

Varför är minidiagram ett x14-tillägg istället för ett diagram?

Minidiagram introducerades i Excel 2010, tre år efter att ECMA-376-basschemat frystes, så de kunde inte ligga direkt i kalkylbladets markup utan att förstöra för alla befintliga läsare. Microsofts lösning är tilläggslistmekanismen: ett kalkylblad kan sluta med ett <extLst>-element som innehåller <ext>-block, var och en taggad med en URI som identifierar funktionen ([MS-XLSX] §2.3.6). Minidiagram använder URI:n {05C60535-1F16-4fd2-B633-F4F36F0B64E0} and namnrymden x14. En läsare som känner igen denna GUID tolkar blocket; en läsare som inte gör det måste hoppa över det. Detta utgör hela historien om framåtkompatibilitet, och det är anledningen till att Excel 2007 öppnar en arbetsbok med minidiagram utan problem — den visar helt enkelt källsiffrorna utan figurerna

En detalj i mekanismen är värd att lyfta fram eftersom den motsäger ett vanligt antagande: ingen mc:Ignorable-deklaration krävs på kalkylbladets rot. Det tillräckliga filtret är själva ext GUID-porten, och Excels egen skrivare deklarerar namnrymden x14 lokalt på <ext>-elementet snarare än att röra roten. HotXLS följer samma mönster, vilket gör att resten av kalkylbladets XML förblir orörd. Detta är också den strukturella skillnaden mot riktiga diagram: ett diagram är en separat DrawingML-del med sin egen renderings-pipeline, vilket beskrivs i artikeln om diagram, bilder och ritningar, medan ett minidiagram är kalkylbladsmetadata som kalkylbladsrutnätet självt målar upp

Hur lägger du till minidiagram i en XLSX-fil programmatiskt?

TXLSXWorksheet.AddSparklineGroup(AType, ASourceRange, ALocation) är vägen med ett enda anrop: den skapar en grupp av den givna typen, förser den med Excels standardseriefärg och lägger till det första minidiagrammet som mappar ett bladkvalificerat källintervall till en värdcell. Den returnerade TXLSXSparklineGroup-instansen accepterar sedan fler minidiagram via sin Add-metod, ett F/Sqref-par per rad, som alla delar gruppens typ och formatering. För instrumentpanelscenariot är det precis den form du vill ha: en grupp, en uppsättning visuella alternativ, hundratals medlemmar

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Grp: TXLSXSparklineGroup;
  Row: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('dashboard.xlsx');
    Sheet := Book.Sheets[0];

    // One group: every product row shares type and formatting
    Grp := Sheet.AddSparklineGroup(xlsxSparklineLine,
      'Sheet1!B2:M2', 'N2');
    for Row := 3 to 201 do
      Grp.Add(Format('Sheet1!B%d:M%d', [Row, Row]),
        Format('N%d', [Row]));

    Book.SaveAs('dashboard-trends.xlsx');
  finally
    Book.Free;
  end;
end;

TXLSXSparklineType täcker de tre typer Excel erbjuder: xlsxSparklineLine för trendlinjer, xlsxSparklineColumn för små stapeldiagram och xlsxSparklineStacked för vinst/förlust-fält där varje värde renderas som ett upp- eller nedblock. Varje enskilt minidiagram är bara två strängar — F, det bladkvalificerade källintervallet, och Sqref, cellen där figuren ritas — så det finns inget annat att konfigurera per rad. Grupper kan också byggas helt för hand via samlingen Worksheet.SparklineGroups om du vill utgå från en tom grupp snarare än det fördefinierade standardvärdet

Markörer, färgplatser och axelskalning på den typade modellen

TXLSXSparklineGroup exponerar hela alternativuppsättningen från Excels menyflik för minidiagramverktyg som vanliga egenskaper. Sex booleska flaggor framhäver datapunkter: Markers för varje punkt på ett linjeminidiagram, plus HighPoint, LowPoint, NegativePoints, FirstPoint och LastPoint. Åtta ARGB-färgplatser paras ihop med dessa — ColorSeries, ColorNegative, ColorAxis, ColorMarkers, ColorFirst, ColorLast, ColorHigh, ColorLow — med konventionen dat en färgplats som lämnas på 0 utelämnas från filen och Excel tillämpar sitt eget standardvärde. Samma helt opaka ARGB-form visas över hela biblioteket, så $FFD00000 här betyder samma röda färg som i villkorsstyrda formateringsstilar

Grp := Sheet.AddSparklineGroup(xlsxSparklineStacked,
  'Sheet1!B2:M2', 'N2');
Grp.NegativePoints := True;          // losing months stand out
Grp.ColorNegative := $FFD00000;
Grp.HighPoint := True;
Grp.ColorHigh := $FF00B050;
Grp.MinAxisType := xlsxSparklineAxisGroup;   // one scale for all rows
Grp.MaxAxisType := xlsxSparklineAxisGroup;
Grp.DisplayEmptyCellsAs := xlsxSparklineEmptyGap;

Axelegenskaperna förtjänar en stunds eftertanke innan du accepterar standardvärdena. MinAxisType och MaxAxisType tar var och en emot individuell skalning, gruppskalning eller anpassad skalning: individuell skalning sträcker ut varje minidiagram till dess eget minimum och maximum, vilket gör att en rad som svänger mellan 99 och 101 ser lika dramatisk ut som en rad som tredubblas. Gruppskalning placerar alla medlemmar på en gemensam vertikal skala, så att höjden på figurerna betyder samma kvantitet på varje rad — vilket vanligtvis är vad en jämförande instrumentpanel vill ha. DisplayEmptyCellsAs avgör vad en tom källcell gör med en linje: lämna ett tomrum, räkna som noll eller spänna över hålet genom att ansluta dess grannar

Vad HotXLS skriver till kalkylbladets extLst när det sparas

När HotXLS sparar serialiseras varje grupp som ett x14:sparklineGroup-element som bär på typ- och flaggattribut, färgplatserna som underordnade element samt en x14:sparklines-lista vars medlemmar parar ihop en xm:f-intervallsformel med en xm:sqref-värdcell. Hela strukturen ligger inuti <extLst><ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"> i slutet av kalkylbladsdelen, med namnrymden x14 deklarerad direkt på blocket, exakt som Excel skriver det. Ett kalkylblad utan minidiagramgrupper genererar ingen extLst alls, så filer som aldrig använt funktionen blir byte-för-byte identiska med vad tidigare HotXLS-versioner producerade — samma konservativa skrivardisciplin som beskrivs i artikeln om förlustfri round-trip-infrastruktur

En detalj i specifikationen är viktig om du någonsin jämför utdata med Excels eller kontrollerar XML-koden manuellt: schemats standardvärde för lineWeight är 0,75 punkter, inte de 1,25 som vissa sekundära källor anger — [MS-XLSX] definierar CT_SparklineGroup@lineWeight med ett standardvärde på 0,75, vilket matchar den vikt Excels gränssnitt faktiskt tillämpar. HotXLS respekterar standardvärdet genom utelämnande: ställ in LineWeight till något annat än 0,75 så skrivs attributet ut, lämna det på 0,75 så görs det inte. Om detta blir fel åt något håll produceras filer som renderas subtilt tyngre eller lättare än samma arbetsbok sparad från Excel

Round-trips, bladkopior och tillägg som HotXLS inte modellerar

Öppning är spegelbilden av sparande. När HotXLS öppnar en arbetsbok som innehåller minidiagram — oavsett om HotXLS eller Excel har skrivit den — filtrerar tolkaren på minidiagrammets ext GUID och bygger upp varje grupp, medlem, färg och axelalternativ i den typade modellen, så att en öppna→redigera→spara-cykel bevarar dem helt. Att kopiera ett kalkylblad till en annan arbetsbok klonar dess minidiagramgrupper tillsammans med resten av bladet, vilket gör mallstyrd rapportgenerering enkel: behåll ett formaterat mallblad, kopiera det per rapport och rikta om intervallen

extLst kan också innehålla tilläggsblock som HotXLS inte har någon typad modell för — Excel skriver x14-block för funktioner som utsnitt (slicers) och utökad villkorsstyrd formatering i samma lista. Sedan version v2.131.0 bevaras dessa främmande block ordagrant under en round-trip istället för att tappas bort: tolkaren fångar upp dem, exponerar dem som skrivskyddade via Worksheet.RawWorksheetExts och skriver tillbaka dem när dokumentet sparas. De följer också med ett blad när det kopieras till en annan arbetsbok. Den bevarade XML-koden återskapas från tolkarhändelser, så den är semantiskt ekvivalent med originalet snarare än byte-identisk, men Excel accepterar den och funktionerna överlever. Den praktiska konsekvensen är den som betyder något i produktion: öppna en kunds arbetsbok och spara om den tar inte längre bort tillägg som du inte har bett HotXLS att förstå

Den ärliga gränsdragningen: minidiagram renderas i Excel 2010 och senare, samt i alla andra läsare som implementerar x14-tillägget; Excel 2007 visar datan utan figurerna, vilket är den degradering som formatet var utformat för att ha. De tre typerna av minidiagram, de åtta färgplatserna, datapunktsflaggorna och de tre axellägena täcker hela den alternativyta som Excels egen dialogruta erbjuder. Stöd för minidiagram, tillsammans med resten av XLSX-motorn som visas här, ingår i HotXLS Delphi Excel Component för Delphi och C++Builder