Du har laget ett ark helt riktig. Toppbanneret er slått sammen, kolonnebreddene passer dataene, de to øverste radene er låst, utskriftsområdet og margene er satt for en ren A4-eksport, og fanen er farget slik at økonomiavdelingen finner den. Nå trenger rapporten tolv slike, én per region, alle med samme oppsett. Å bygge arket på nytt i kode tolv ganger er slik små avvik sniker seg inn: region 7 får en kolonne som er ett punkt smalere, region 11 mister låsen, og ingen merker det før PDF-en lander på pulten til en leder. Det du egentlig vil ha, er den programatiske varianten av Excels høyreklikk, Flytt eller kopier, Opprett en kopi: ta det ferdige arket og stamp ut uavhengige kopier
XLSX-motoren i HotXLS, et innfødt Delphi- og C++Builder-bibliotek som leser og skriver Excel-filer uten å automatisere Excel selv, kunne allerede flytte ark, slette ark og kopiere celleområder mellom ark. Det den ikke kunne før v2.91.0, var å klone et helt regneark i ett kall. Den utgivelsen legger til to innganger: TXLSXWorksheet.CopyFrom, som kopierer arktilstand fra ett regneark til et annet, og TXLSXSheets.Duplicate, som legger til et nytt ark og kjører CopyFrom for deg. Det interessante er ikke at den kopierer ting. Det er den bevisste grensen mellom det som får en dyp kopi og det som ikke gjør det, og hvorfor grensen ligger akkurat der
Én kommando for å klone et ferdig ark
Høynivåoperasjonen er Duplicate. Gi den den 1-baserte indeksen til kildearket, og den returnerer et helt nytt regneark som speiler oppsettet og dataene i originalen. Indeksreglene matcher Items[] på XLSX-siden, så ark én er indeks 1, ikke 0; sender du en indeks utenfor området, får du nil i stedet for et unntak, samme feilkontrakt som resten av samlingen for XLSX-ark bruker
var
Book: TXLSXWorkbook;
Template, Copy: TXLSXWorksheet;
begin
Book := TXLSXWorkbook.Create;
try
Template := Book.Sheets.Add('Template');
Template.Cells[1, 1].Value := 'Quarterly Statement';
Template.Range['A1:C1'].Merge;
Template.ColWidth[1] := 18;
Template.FreezePanes(2, 1); // freeze top row + first column
Template.TabColorIsAuto := False;
Template.TabColor := $FF1F4E79;
// Clone with an explicit name...
Copy := Book.Sheets.Duplicate(1, 'Region-North');
// ...or let it pick the Excel-style default name.
Copy := Book.Sheets.Duplicate(1); // -> "Template (2)"
Book.SaveAs('regions.xlsx');
finally
Book.Free;
end;
end;
To ting i det eksempelet er verdt å dvele ved. For det første tar FreezePanes argumentene rad først, FreezePanes(ARow, ACol), så det følger indekseringen Cells[Row, Col]; kopien arver akkurat samme fastfrysing. For det andre heter metoden Duplicate og ikke det mer opplagte Copy, og det er ikke bare et stilvalg. Copy er en standardrutine i System-enheten, brukt hele tiden for strenger og dynamiske arrays. En metode som heter Copy på en klasse ville skygge for den inne i metoder og skape akkurat den typen navneoppløsning som slår deg seks måneder senere. Duplicate unngår hele problemet og leses riktig på kallstedet
Standardnavnet følger Excels egen regel
Når du kaller én-argumentvarianten, eller sender inn en tom navnestreng, får det nye arket samme navn som kilden med suffikset (2), og suffikset øker til navnet er unikt. Duplicer Template én gang og du får Template (2); duplicer det igjen og du får Template (3), fordi Template (2) allerede er opptatt. Dette speiler navnene Excel lager fra sin egen kommando Opprett en kopi, så arbeidsboken koden din produserer ser ut slik en bruker forventer at en manuelt duplisert arbeidsbok skal se ut. Unikhetskontrollen kjøres mot den aktive arklisten, som betyr at den også hopper over navn du har laget manuelt, ikke bare de som kommer fra tidligere dupliseringer
Hvis du genererer ett ark per region eller per måned, bør du heller bruke versjonen med eksplisitt navn. Et forutsigbart Region-North, Region-South-mønster er lettere å slå opp senere enn en rekke suffikser som (2), (3), og det holder de definerte navnene og formlene mellom arkene lesbare
Hva CopyFrom dypkopierer
Under panseret legger Duplicate til arket og kaller så CopyFrom(ASource), som du også kan kalle direkte når du vil klone over på et ark du allerede har opprettet. CopyFrom beskytter mot de to ugyldige tilfellene med en gang: kopiering fra nil, eller kopiering av et ark over seg selv, returnerer begge umiddelbart uten å gjøre noe. Alt etter det er selve kopieringen, og den er bevisst bred
Celledata kommer først. CopyFrom ber kilden om UsedRange, den tette avgrensningen rundt fylte celler og sammenslåtte områder, og gjenbruker den eksisterende CopyRangeTo-mekanikken for å føre hver verdi, formel og stilindeks per celle inn i målet med start i A1. Oppå cellene spiller den av hele laget med arknivåtilstand som får en mal til å se ferdig ut:
- Sammenslåtte områder, gjenskapt etter koordinater slik at banneret dekker samme rektangel
- Kolonnebredder og radhøyder, pluss listene for skjulte, sammenfoldede og disposisjonsnivåer, kopiert ordrett slik at rader og kolonner som ikke er standard, flukter nøyaktig
- Fastfrosne ruter og visningstilstand: zoomnivå, visning av rutenett og nullverdier, høyre-til-venstre-retning og visningstype
- Beskyttelsestilstand med tillatelsesvalg for hver handling, slik at en låst mal forblir låst på samme måte
- Hele sideoppsettet: marger, orientering, papirstørrelse, skalering og tilpass-til-side, utskriftsområde, utskriftstitler, topp- og bunntekster, samt flaggene for utskriftsrutenett og utskrift av kolonne- og radoverskrifter
- AutoFilter-området, fanefargen og arkets synlighet
Resultatet er et ark som skriver ut, filtrerer og presenterer seg identisk med kilden. Og fordi cellene, sammenslåingene og dimensjonslistene blir fysisk gjenskapt på det nye arket i stedet for å peke på samme data, er kopien helt uavhengig. Skriv 999 inn i en celle på kopien, og kilden beholder verdien sin; den uavhengigheten er den viktigste egenskapen for en klone som skal brukes til parallelle regionrapporter, og den medfølgende SheetCopy-demoen bekrefter det eksplisitt
Hva den lar være grunt, og hvorfor
Nå til den ærlige delen. Diagrammer, innebygde bilder, XLSX-tabeller, datavalideringer og regler for betinget formatering kopieres ikke. Dette er en dokumentert, bevisst grense, ikke en forglemmelse, og det er verdt å forstå hvorfor den finnes, slik at du kan planlegge rundt den i stedet for å bli overrasket av den
Hver av disse samlingene bærer med seg identitet og referanser som ikke overlever en naiv feltkopi. Et diagram peker på et kildedataområde og eier en tegningsrelasjon i OOXML-pakken; å klone objektet uten å remappe relasjonen og seriereferansene gir et diagram som tegner mot feil data, eller en pakke som Excel markerer som skadet og trenger reparasjon. En tabell har et navn som må være unikt i arbeidsboken, en overskriftsrad knyttet til bestemte kolonner, og sin egen automatisk genererte relasjon. Betinget formatering og datavalideringer er knyttet til koordinatområder og kan i valideringstilfellet referere til andre områder via formel. Å dypkopiere noe av dette korrekt betyr å skrive om referanser og lage nye identiteter, og det er reelt arbeid med reelle feilmodi. Å gjøre det halvveis, ved å kopiere objektet men ikke referansene, er verre enn å ikke kopiere i det hele tatt: du får en fil som åpnes med en reparasjonsprompt og mister innhold uten varsel. Derfor kopierer motoren det den kan kopiere rent, og lar de referansebærende samlingene ligge til den som kaller, og som vet hva målet skal peke på
I praksis betyr det at arbeidsflyten for en rikere mal er: dupliser arket for å få cellene, oppsettet og utskriftsinnstillingene, og bygg deretter opp diagrammet, tabellen, valideringene eller den betingede formateringen på kopien med samme API som du brukte første gang. Fordi du gjenskaper dem mot kopiens egne områder, blir referansene riktige av konstruksjon. For et diagram som leser A1:C10, legg til et nytt diagram på kopien som peker på kopiens A1:C10; for et AutoFilter du vil ha levende, legg merke til at filterområdet faktisk følger med, så du trenger bare å bruke kolonnevilkårene på nytt. Reglene for betinget formatering og datavalidering legger du tilbake gjennom de samme kallene som er beskrevet i artikkelen om sammenslåtte celler og oppsett for rapportmaler, som går gjennom sammenslåingstabellen og områdemodellen kopien arver
Hvor duplisering passer inn i en rapporteringsflyt
Duplisering av regneark er den naturlige partneren til generering styrt av plassholdere. Den tokenforankrede tilnærmingen i guiden til malstyrt rapportgenerering i Delphi løser problemet med å skrive data inn i et oppsett andre kan redigere; duplisering løser problemet med å trenge det samme oppsettet mange ganger i én arbeidsbok. Kombiner dem, og mønsteret blir ryddig: behold ett rent Template-ark med tokenene, sammenslåingene og utskriftsoppsettet, og kall så Duplicate for hver region eller periode, fyll tokenene i kopien med det datasnittet, og gå videre. Den rene malen blir aldri endret, så den forblir en pålitelig kilde for neste kopi, og hvert utdataark starter fra et layout som er identisk ned til minste byte
Et lite tips om rekkefølge sparer deg for en egen type forvirring. Dupliser arket før du heller data inn i det, ikke etterpå. En mal bør holde på struktur og formatering, ikke fjorårets tall, og en tom, stilisert kopi betyr at hver duplikat starter rent. Hvis du dupliserer et ark som allerede inneholder data, følger de dataene med, fordi CopyFrom kopierer UsedRange trofast; det er av og til det du vil ha, men for en distribusjonsrapport er det som regel ikke det
En rask verifiseringsvane
Fordi skillet mellom dyp og overfladisk kopi er usynlig til du ser etter det, bør du legge inn en femlinjesjekk i jobben i stedet for å stole på at alt kom med. Etter duplisering leser du tilbake de strukturelle signalene klonen skal arve, og verifiserer at de matcher kilden
Copy := Book.Sheets.Duplicate(1, 'Region-North');
WriteLn(Format('merged=%d colA=%.1f freezeRow=%d tabAuto=%d',
[Copy.MergedCells.Count, Copy.ColWidth[1],
Copy.FreezeRow, Integer(Copy.TabColorIsAuto)]));
// Prove independence: mutate the copy, confirm the source is untouched.
Copy.Cells[2, 2].Value := 999;
// Template.Cells[2, 2].Value is still whatever it was.
Antall sammenslåinger, en kolonnebredde, den fastfrosne raden og fanefargeflagget forteller deg at laget som faktisk skal kopieres, kom med. Separat, i alle ark som hadde diagram, tabell, valideringer eller betinget formatering, bør du behandle dem som en liste som må bygges opp på nytt i kopien: at de mangler er med vilje, og løsningen er noen få kall, ikke en feilrapport. Den mentale modellen, dyp der det er trygt og overfladisk der referanser ville brutt sammen, er hele historien om hvordan denne funksjonen brukes godt
Duplisering av regneark og kopiering av arktilstanden med CopyFrom slik det er beskrevet her, leveres i v2.91.0 av den innfødte HotXLS Delphi-regnearkkomponenten, sammen med et kjørbart SheetCopy-eksempel som viser hele klone- og endringssyklusen fra ende til ende