Ați construit o foaie exact cum trebuie. Banda de antet este îmbinată, lățimile coloanelor se potrivesc datelor, primele două rânduri sunt înghețate, zona de tipărire și marginile sunt setate pentru un export A4 curat, iar fila este colorată astfel încât echipa financiară să o poată găsi rapid. Acum raportul are nevoie de douăsprezece astfel de foi, câte una pentru fiecare regiune, toate pornind de la aceeași structură. Să reconstruiești acea foaie în cod de douăsprezece ori este modul sigur de a introduce mici abateri: regiunea 7 ajunge cu o coloană cu un punct mai îngustă, regiunea 11 pierde înghețarea, iar nimeni nu observă până când PDF-ul ajunge pe biroul unui manager. Ce vă doriți de fapt este versiunea programatică a opțiunii Excel clic dreapta, Move or Copy, Create a copy: luați foaia terminată și scoateți duplicate independente
Motorul XLSX din HotXLS, o bibliotecă nativă pentru Delphi și C++Builder care citește și scrie fișiere Excel fără a automatiza chiar Excel-ul, putea deja să mute foi, să șteargă foi și să copieze intervale de celule între foi. Însă până la v2.91.0 nu putea clona o foaie de lucru întreagă dintr-un singur apel. Acea versiune adaugă două puncte de intrare: TXLSXWorksheet.CopyFrom, care copiază starea la nivel de foaie de la o foaie de lucru la alta, și TXLSXSheets.Duplicate, care adaugă o foaie nouă și rulează CopyFrom pentru dvs. Partea interesantă nu este că poate copia lucruri. Este linia trasată intenționat între ceea ce se copiază în profunzime și ceea ce nu se copiază, precum și motivul pentru care linia este exact acolo
Un singur apel pentru a clona o foaie terminată
Operația de nivel înalt este Duplicate. Oferiți-i indexul de bază 1 al foii sursă și vă returnează o foaie de lucru complet nouă, care oglindește aspectul și datele originale. Convenția de indexare se aliniază cu Items[] în partea XLSX, astfel încât foaia unu are indexul 1, nu 0; dacă transmiteți un index în afara intervalului, obțineți nil în loc de o excepție, același contract de eșec pe care îl folosește restul colecției de foi XLSX
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;
Două lucruri din acest fragment merită lămurite. În primul rând, FreezePanes primește argumentele de la rândul întâi, FreezePanes(ARow, ACol), astfel încât se aliniază cu indexarea Cells[Row, Col]; duplicatul moștenește exact împărțirea freeze-ului. În al doilea rând, metoda se numește Duplicate și nu mai evidentul Copy, iar acesta nu este un capriciu de stil. Copy este o rutină standard în unitatea System, folosită constant pentru șiruri și tablouri dinamice. O metodă numită Copy pe o clasă i-ar face umbră în corpurile metodelor și ar crea exact genul de ambiguitate de rezolvare care te mușcă peste șase luni. Duplicate ocolește complet problema și se citește corect la locul apelului
Numele implicit urmează propria regulă a Excel
Când apelați suprasarcina cu un singur argument sau transmiteți un șir de nume gol, foaia nouă primește numele foii sursă cu sufixul (2), iar sufixul crește până când numele devine unic. Duplicați foaia Template o dată și obțineți Template (2); duplicați-o din nou și obțineți Template (3), pentru că Template (2) este deja folosit. Aceasta reflectă numele generate de Excel din propria comandă Create a copy, astfel încât un registru de lucru produs de codul dvs. arată așa cum s-ar aștepta un utilizator să arate unul duplicat manual. Verificarea unicității se face pe colecția de foi activă, ceea ce înseamnă că sare peste numele create manual de dvs., nu doar peste cele rezultate din duplicări anterioare
Dacă generați o foaie per regiune sau per lună, folosiți mai degrabă suprasarcina cu nume explicit. O schemă previzibilă de tip Region-North, Region-South este mai ușor de adresat ulterior decât un șir de sufixe de tip (2), (3), și păstrează lizibile numele definite și formulele între foi
Ce copiază CopyFrom în profunzime
Sub capotă, Duplicate adaugă foaia și apoi apelează CopyFrom(ASource), pe care o poți apela și direct când vrei să clonezi pe o foaie creată deja de tine. CopyFrom se apără din start de cele două cazuri degenerate: copierea de la nil, sau copierea unei foi peste ea însăși, returnează imediat și nu face nimic. Tot ce urmează este chiar copia, iar aceasta este intenționat amplă
Datele celulelor vin primele. CopyFrom cere sursei UsedRange, caseta de delimitare strânsă a celulelor completate și a regiunilor îmbinate, și reutilizează mecanismul existent CopyRangeTo pentru a duce fiecare valoare, formulă și index de stil per celulă în țintă, începând de la A1. Peste celule, reface întreaga stratură de stare la nivel de foaie care face ca un șablon să aibă aspectul finalizat:
- Regiunile îmbinate, recreate după coordonate, astfel încât bannerul să ocupe același dreptunghi
- Lățimile coloanelor și înălțimile rândurilor, plus listele de rânduri și coloane ascunse, restrânse și pe niveluri de contur, copiate întocmai pentru ca rândurile și coloanele nestandard să se alinieze exact
- Panourile înghețate și starea de afișare: nivelul de zoom, afișarea liniilor de grilă și a valorilor zero, direcția de la dreapta la stânga și tipul de vizualizare
- Starea de protecție cu opțiunile de permisiune pentru fiecare acțiune, astfel încât un șablon blocat să rămână blocat la fel
- Întregul bloc de configurare a paginii: margini, orientare, formatul hârtiei, scalare și încadrare pe pagină, zona de imprimare, titluri de imprimare, anteturi și subsoluri, precum și indicatoarele pentru liniile de grilă și titlurile de imprimare
- Intervalul AutoFilter, culoarea filei și vizibilitatea foii
Rezultatul este o foaie care tipărește, filtrează și se prezintă identic cu sursa ei. Și, fiindcă celulele, îmbinările și listele de dimensiuni sunt recreate fizic pe foaia nouă, nu doar aliasate, copia este complet independentă. Scrie 999 într-o celulă de pe copie, iar sursa își păstrează valoarea originală; această independență este cea mai importantă proprietate a unei clone gândite pentru rapoarte regionale paralele, iar SheetCopy demo-ul livrat o afirmă explicit
Ce lasă la suprafață și de ce
Acum partea sinceră. Diagramele, imaginile încorporate, tabelele XLSX, validările de date și regulile de formatare condiționată sunt nu copiate. Aceasta este o limită documentată și intenționată, nu o scăpare, și merită înțeles raționamentul ca să poți planifica în jurul ei, nu să fii surprins de ea
Fiecare dintre aceste colecții poartă o identitate și referințe care nu supraviețuiesc unei copieri naive de câmpuri. O diagramă indică un interval sursă de date și deține o relație de desen în pachetul OOXML; clonarea obiectului fără remaparea relației și a referințelor seriilor produce o diagramă care se desenează pe datele greșite sau un pachet pe care Excel îl semnalează ca având nevoie de reparare. Un tabel are un nume care trebuie să fie unic în registrul de lucru, un rând de antet legat de coloane specifice și propria sa relație generată automat. Formatele condiționate și validările de date se atașează la intervale de coordonate și, în cazul validării, pot face referire la alte intervale prin formulă. Copierea profundă corectă a oricăreia dintre acestea înseamnă rescrierea referințelor și emiterea unor identități noi, ceea ce este muncă reală cu moduri reale de eșec. A le face pe jumătate, copiind obiectul dar nu și referințele, este mai rău decât a nu le copia deloc: rezultă un fișier care se deschide cu o solicitare de reparare și pierde conținut în liniște. Așa că motorul copiază lucrurile pe care le poate copia curat și lasă colecțiile care poartă referințe în grija apelantului, care știe spre ce ar trebui să indice ținta
În practică, asta înseamnă că fluxul pentru un șablon mai bogat este: duplici foaia ca să obții celulele, aspectul și configurarea de imprimare, apoi reconstruiești diagrama, tabelul, validările sau formatele condiționate pe copie cu aceeași API pe care ai folosit-o prima dată. Pentru că le recreezi pe propriile intervale ale copiei, referințele ies corecte prin construcție. Pentru o diagramă care citește A1:C10, adaugi o diagramă nouă pe copie care indică spre A1:C10; pentru un AutoFilter pe care îl vrei activ, observă că intervalul filtrului chiar se păstrează, așa că reaplici doar criteriile pe coloană. Regulile de formatare condiționată și validare de date pe care le-ai adăuga din nou prin aceleași apeluri descrise în articolul despre celulele îmbinate și aspectul șabloanelor de raport, care parcurge tabela de îmbinări și modelul de intervale pe care le moștenește copia
Unde se potrivește duplicarea într-un flux de raportare
Duplicarea foii de lucru este însoțitorul firesc al generării bazate pe substituenți. Abordarea ancorată în token-uri din ghidul pentru generarea rapoartelor bazate pe șabloane în Delphi rezolvă problema scrierii datelor într-un aspect pe care îl editează alții; duplicarea rezolvă problema de a avea nevoie de acel aspect de multe ori într-un singur registru de lucru. Combină-le și modelul devine curat: păstrează o singură foaie Template impecabilă, cu token-urile, îmbinările și configurarea de imprimare, apoi pentru fiecare regiune sau perioadă apelează Duplicate, completează token-urile clonei cu acel fragment de date și mergi mai departe. Șablonul impecabil nu este niciodată modificat, așa că rămâne o sursă de încredere pentru următoarea clonă, iar fiecare foaie de ieșire pornește de la un aspect identic până la ultimul byte
O notă despre ordonare evită o clasă de confuzii. Duplică foaia înainte să torni date în ea, nu după. Un șablon ar trebui să păstreze structura și formatarea, nu numerele de trimestrul trecut, iar clonarea unei foi stilizate goale înseamnă că fiecare copie pornește curat. Dacă duplici o foaie care are deja date, acele date vin odată cu ea, pentruCopyFromcopiază fidel intervalul folosit; uneori asta este exact ce vrei, dar pentru un raport de distribuire, de obicei, nu este
Un obicei de verificare rapidă
Deoarece diferența dintre copierea profundă și copierea superficială rămâne invizibilă până când o cauți, introdu în flux o verificare de cinci linii, în loc să presupui că totul a fost preluat corect. După duplicare, citește din nou semnalele structurale pe care clona ar trebui să le moștenească și verifică dacă se potrivesc cu sursa
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.
Numărul de îmbinări, lățimea unei coloane, rândul fixat și indicatorul de culoare al filei îți arată că stratul care estecopiat a ajuns într-adevăr la destinație. Separat, în orice foaie care conținea un grafic, un tabel, validări sau formatare condiționată, tratează-le în copie ca pe o listă de elemente de reconstruit: absența lor este intenționată, iar corectarea înseamnă câteva apeluri, nu un raport de eroare. Acest model mental, profund acolo unde este sigur și superficial acolo unde referințele s-ar rupe, este întreaga poveste despre cum să folosești bine această funcție
Duplicarea foilor de lucru și CopyFromcopierea stării foii descrise aici sunt livrate în v2.91.0 a componentei native HotXLS Delphi spreadsheet component, împreună cu un SheetCopyexemplu rulabil care parcurge cap-coadă ciclul de clonare și modificare