HotXLS kan omskrive ét regneark inde i en eksisterende XLSX-pakke uden at parse eller genkomprimere resten af filen. TXLSDirectWriter.BeginPatch åbner en kildepakke, kopierer hver post undtagen målarket over med dens komprimerede bytes ordret, og lader dig genforfatte det enkelte ark via de almindelige AddSheet-, AddRow- og Write*-kald. Diagrammer, pivot-caches, temaer, stilarter og delte strenge bliver aldrig dekomprimeret overhovedet
Den arbejdsgang, dette løser, dukker op i rapportering og dataopdatering. En arbejdsbog ankommer fra et forretningsteam og bærer pivottabeller, slicere, betingede formater og et årti med akkumuleret formatering. Hver nat skal ét dataark udskiftes med friske tal. At indlæse og gemme hele arbejdsbogen igen koster minutter pr. fil og, mere vigtigt, risikerer troskab på funktioner, som indlæsningsmotoren skal genopbygge. Patching omgår begge problemer ved ikke at røre, hvad den ikke behøver at røre
Hvorfor er det den interessante del at kopiere komprimerede bytes?
En zip-post, der kopieres på komprimeret niveau, koster en streamkopi. Den samme post, ført gennem en normal skrivevej, koster en inflate på vej ind og en deflate på vej ud, og deflate er den dyre halvdel. På en arbejdsbog med en stor pivot-cache og et par dusin indlejrede billeder er den forskel forskellen mellem en patch, der bliver færdig på den tid, det tager at skrive det nye ark, og en, der bruger det meste af sin tid på at genkomprimere bytes, den aldrig undersøgte
HotXLS bruger CopyCompressedFrom til dette, som skriver kildepostens komprimerede bytes direkte ind i målarkivet. Når en post ikke kan kopieres på den måde, fordi den bruger en anden komprimeringsmetode eller svag kryptering, falder skriveren tilbage til en dekomprimeret streamkopi frem for at fejle. Mappe-markørposter springes over, da skriveren producerer sine egne
Erstat på plads, eller skriv til en ny fil
To overloads dækker de to former, denne opgave antager. In-place-formen forbereder resultatet i en midlertidig fil ved siden af originalen, lukker kildehåndtaget, sletter og omdøber derefter, så et nedbrud midt i skrivningen efterlader originalen intakt. Den eksplicitte mål-form efterlader kilden urørt og kan enten erstatte et ark eller tilføje et nyt:
var
W: TXLSDirectWriter;
begin
W := TXLSDirectWriter.Create;
try
W.BeginPatch('monthly-dashboard.xlsx', 'Data'); // på plads
W.AddSheet('Data');
W.AddRow(1);
W.WriteString(1, 'Region');
W.WriteString(2, 'Revenue');
W.AddRow(2);
W.WriteString(1, 'North');
W.WriteNumber(2, 184320.55);
W.AddRow(3);
W.WriteFormula(1, '=SUM(B2:B2)');
W.Close;
finally
W.Free;
end;
end;
Insert-varianten tager en kilde og en målsti plus InsertSheet:
// Kilden forbliver urørt; målet får et ekstra regneark ved navn Extra
W.BeginPatch('template.xlsx', 'output.xlsx', 'Extra', True);
W.AddSheet('Extra');
W.AddRow(1);
W.WriteString(1, 'appended by the nightly job');
W.Close;
Indsættelse er den del, der kræver reel bogholderikirurgi. Skriveren parser arkregistret i xl/workbook.xml og relationskortet, der binder hvert ark til dets del, og vælger derefter det næste ledige delnummer, arkidentifikator og relationsidentifikator. Relationstyper følger konventionerne i kildepakken, så patching af en streng ISO 29500-arbejdsbog udsender strenge relationstyper, og patching af en transitionel en udsender transitionelle typer
Hvad patchen bevidst dropper og begrænser
Beregningskæden kasseres i begge tilstande. I erstat-tilstand beskriver dens poster celler i et ark, der ikke længere findes i den form; i indsæt-tilstand ugyldiggør arkindeksforskydningen den fuldstændigt. Excel genopbygger kæden ved den næste genberegning, så at droppe den er korrekt frem for tabsgivende. Delen udelades fra kopien, og dens relationspost og indholdstype-override fjernes kirurgisk
To forfattersemantikker ændrer sig inde i en patch, og begge følger af samme princip: patchen må ikke forstyrre dele, den ikke omskrev. Strenge skrives inline ind i arket i stedet for at blive tilføjet til tabellen med delte strenge, fordi kildetabellen krydser over urørt. Og StyleIndex refererer til poster i kildepakkens cellXfs, ikke til en stiltabel, skriveren bygger. Det betyder, at man kan referere til formater, den oprindelige arbejdsbog allerede definerer, hvilket som regel er præcis, hvad en dataopdatering vil have, men det betyder også, at man skal vide, hvilket indeks der bærer hvilket format
// Inde i en patch indekserer StyleIndex KILDE-pakkens cellXfs.
// En dato kræver et eksplicit indeks, der mapper til et datoformat der:
W.WriteDateTime(3, EncodeDate(2026, 8, 22), DateStyleIndexFromTemplate);
// Den stil-frie WriteDateTime-overload afvises i patch-tilstand,
// fordi den forudsætter skriverens egen stiltabel, som en patch
// aldrig opretter
Seks forfatterindgangspunkter er spærret: at tilføje tabeller, diagrammer, billeder, kommentarer, definerede navne og cellestile udløser alle en undtagelse i patch-tilstand, med et andet sikkerhedsnet ved lukning, der fejler, hvis nogen af deres tællere er forskellige fra nul. Hver af disse funktioner ville kræve redigering af dele, som patchen kopierer ordret, og en halvt redigeret pakke er værre end en afvist handling. Præcis ét ark må patches pr. handling
Hvornår man skal patche, og hvornår man skal indlæse
Patching er det rigtige værktøj, når arbejdsbogen er stor, ændringen er begrænset til ét ark, og resten af filen skal overleve bit for bit. Det er det forkerte værktøj, når ændringen spænder over flere ark, når ny formatering eller nye objekter er nødvendige, eller når filen er lille nok til, at en normal indlæsning og gemning ikke koster noget. Til masseoprettelse fra bunden er streamingstien beskrevet i den streamende direkte skriver stadig det bedre valg, og den deler det samme AddRow- og Write*-API, så at bevæge sig mellem de to er mekanisk
Manipulation på arkniveau inde i en indlæst arbejdsbog, når man rent faktisk ønsker den fulde objektmodel, er beskrevet i duplikering af regneark i XLSX-pakker. Og hvis grunden til, at du overvejer en patch, er, at hele-arbejdsbog-behandling er blevet langsom, er målingerne og hukommelsesadfærden i ydeevne for store arbejdsbøger værd at læse, før du vælger en tilgang
Verificering af, at en patch faktisk gjorde, hvad du tror
Tre tjek fanger næsten hver fejl. Bekræft, at de dele, du forventede skulle overleve, stadig er i arkivet, at xl/calcChain.xml er væk, og at genåbning af filen via TXLSXWorkbook rapporterer det arkantal, du forventer, uændret for en erstatning og forøget med én for en indsættelse. At læse det patchede ark tilbage og sammenligne nogle værdier og formler lukker løkken
Én implementeringsdetalje fra udviklingen af denne funktion fortjener at blive gentaget, fordi den kan bide enhver, der skriver lignende kode på zip-niveau. Regnearksdelnavne matches efter præfiks, og en off-by-one-fejl i præfikslængden betyder, at prædikatet aldrig matcher, så en nyskrevet del kolliderer med et eksisterende navn, og læsere, der tager den sidste post med et givet navn, vælger stiltiende det forkerte ark. Hvis en patch tilsyneladende bytter indholdet af to ark, så se på navnematching, før du ser på XML'en
In-place-patching, streamende skrivninger og den fulde arbejdsbog-objektmodel leveres i det samme bibliotek til Delphi og C++Builder; funktionslisten findes på HotXLS Delphi regnearkskomponentsiden