Anda sudah membuat satu sheet dengan tepat. Bagian header sudah merge, lebar kolom sesuai data, dua baris atas di-freeze, area print dan margin siap untuk ekspor A4 bersih, dan tab sudah diwarnai agar tim finance mudah menemukannya. Sekarang laporan membutuhkan dua belas sheet serupa, satu per region, masing-masing mulai dari tata letak yang sama. Menyalin ulang sheet lewat kode dua belas kali dapat membuat "drift" halus: region 7 kehilangan satu point lebar kolom, region 11 kehilangan freeze, dan masalahnya baru ketahuan saat hasilnya ada di meja manajer. Yang Anda butuhkan sebenarnya adalah versi programatik dari operasi Excel "Move or Copy, Create a copy": ambil sheet jadi dan buat duplikat independen
Engine XLSX di HotXLS, library native Delphi dan C++Builder yang membaca menulis Excel tanpa meng-otomasi Excel, sebelumnya sudah bisa memindah sheet, menghapus sheet, dan menyalin rentang antar sheet. Tapi sampai v2.91.0 ia belum bisa men-duplicate seluruh worksheet dalam satu method. Rilis ini menambah dua titik masuk: TXLSXWorksheet.CopyFrom untuk menyalin state tingkat sheet dari worksheet sumber ke worksheet target, dan TXLSXSheets.Duplicate untuk membuat sheet baru lalu memanggil CopyFrom. Menariknya bukan karena kemampuan salin semata, tapi karena batas yang jelas antara mana yang deep-copied dan mana yang tidak
Satuh pemanggilan untuk menyalin sheet jadi
Operasi tingkat tinggi adalah Duplicate. Berikan index 1-based dari sheet sumber dan ia mengembalikan worksheet baru yang meniru layout dan data aslinya. Konvensi index ini mengikuti Items[] di sisi XLSX, jadi sheet pertama adalah 1, bukan 0. Index di luar rentang mengembalikan nil, bukan exception, sesuai kontrak error dari koleksi sheet yang lain
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;
Ada dua hal penting di contoh ini. Pertama, FreezePanes menerima argumen baris dulu, yaitu FreezePanes(ARow, ACol), sehingga sesuai urutan Cells[Row, Col]. Salinan otomatis mewarisi pemisah freeze yang persis sama. Kedua, method bernama Duplicate dan bukan Copy sengaja dipilih. Copy adalah routine standar di unit System untuk string dan dynamic array. Kalau ada method bernama Copy di class, pemanggilan di method body dapat menimbulkan ambiguitas. Duplicate menghindari masalah itu dan membuat nama pemanggilan lebih jelas
Nama default mengikuti aturan Excel
Ketika Anda memanggil overload satu argumen, atau memberikan string nama kosong, sheet baru diberi nama dari sumber dengan akhiran (2), lalu angka dinaikkan sampai unique. Duplikasi pertama Template menjadi Template (2). Jika duplikasi lagi menjadi Template (3) karena Template (2) sudah ada. Ini sejalan dengan nama yang dihasilkan Excel saat memakai command "Create a copy", jadi workbook yang dibuat kode Anda terlihat seperti hasil duplicate manual dari user. Pemeriksaan keunikan berjalan pada koleksi sheet aktif, jadi nama yang dibuat manual juga diperhitungkan, bukan hanya hasil duplikasi sebelumnya
Jika Anda membuat sheet per region atau per bulan, lebih baik pakai overload nama explicit. Skema Region-North, Region-South lebih mudah dilacak dibanding deretan (2), (3) dan menjaga nama range terdefinisi serta formula lintas sheet tetap terbaca
Yang dibawa oleh CopyFrom
Di dalam, Duplicate membuat sheet lalu memanggil CopyFrom(ASource), dan Anda juga bisa memanggilnya langsung saat ingin menyalin ke sheet yang sudah Anda buat. CopyFrom memeriksa dua kondisi rusak sejak awal: copy dari nil atau copy dari sheet diri sendiri, keduanya langsung return tanpa perubahan. Sisanya menjalankan proses salin yang sengaja luas
Data cell diproses pertama. CopyFrom meminta sumber untuk UsedRange, yaitu kotak batas sel terisi dan merge region, lalu memakai mesin CopyRangeTo yang sudah ada untuk memindahkan semua value, formula, dan index style per-cell ke target mulai dari A1. Setelah sel, ia menyalin lapisan state level sheet yang membuat template terlihat selesai:
- Range yang merged, dibuat ulang berdasarkan koordinat agar banner menutup area yang sama
- Lebar kolom dan tinggi baris, termasuk daftar hidden, collapsed, dan outline-level, disalin apa adanya agar baris dan kolom non-default tetap tepat
- Freeze panes dan state tampilan: zoom, gridline, tampilan nilai nol, arah kanan ke kiri, dan tipe view
- State proteksi dengan opsi per-aksi, jadi template terkunci tetap terkunci dalam cara yang sama
- Seluruh blok page setup: margin, orientasi, ukuran kertas, scaling dan fit-to-page, print area, print titles, header, footer, print-gridlines, dan print-headings flags
- Rentang AutoFilter, tab colour, dan visibilitas sheet
Hasilnya adalah sheet yang bisa di-print, difilter, dan tampil identik dengan sumbernya. Karena sel, merge, dan list dimensi dibuat ulang secara fisik pada sheet baru bukan di-alias, duplikat benar-benar independen. Saat Anda menulis 999 ke sel pada copy, sumber tetap mempertahankan nilai aslinya; inilah properti paling penting dari clone untuk laporan regional paralel, dan demo SheetCopy yang dikirim memang memverifikasi hal ini
Apa yang dibiarkan shallow, dan kenapa
Sekarang bagian jujur. Chart, gambar tertanam, tabel XLSX, validasi data, dan aturan conditional formatting tidak disalin. Ini batas desain yang didokumentasikan, bukan kelalaian. Karena koleksi-koleksi tersebut membawa identity dan relasi yang tidak tahan kalau hanya copy field biasa. Chart merujuk ke source data range dan memiliki drawing relationship di paket OOXML; duplikasi objek tanpa remap relasi dan referensi series menghasilkan chart yang mengacu data salah, atau file Excel yang menandai need repair. Tabel memiliki nama unik dalam workbook, baris header yang tergantung kolom tertentu, dan relationship internalnya sendiri. Conditional format dan data validation melekat ke rentang, dan di kasus validation bisa merujuk ke rentang lain lewat formula. Deep-copy yang benar menuntut rewrite referensi dan buat identity baru, yang rentan salah. Menyambung setengah-setara, hanya menyalin objek tanpa referensinya, lebih buruk dari tidak menyalin sama sekali karena menghasilkan file yang dibuka dengan prompt repair dan kehilangan konten. Jadi mesin hanya menyalin hal yang aman dan menaruh koleksi berbasis referensi kembali ke caller agar caller bisa menentukan arah
Secara praktik, alur untuk template lengkap adalah: duplikat sheet agar dapat cell, layout, dan print setup, lalu bangun ulang chart, table, validation, atau conditional format pada copy dengan API yang sama dengan saat pertama kali membuatnya. Karena Anda membuatnya di atas rentang milik duplicate, referensi akan benar. Untuk chart yang membaca A1:C10, buat chart baru pada copy yang mengacu A1:C10 milik copy; untuk AutoFilter agar aktif, rentang range-nya tetap terduplikasi jadi Anda hanya tinggal ulangi kriteria kolom. Aturan conditional-formatting dan data validation bisa ditambahkan ulang lewat call yang sama di the article on merged cells and report-template layout, yang menjelaskan model merge table dan range yang diwariskan
Di mana duplikasi masuk alur pelaporan
Duplikasi worksheet memang pasangan alami pendekatan token-based generation. Pendekatan ber-penanda di the guide to template-driven report generation in Delphi menyelesaikan masalah menulis data ke layout yang diubah orang lain, sedangkan duplikasi menyelesaikan kebutuhan memakai layout itu banyak kali dalam satu workbook. Padukan keduanya: simpan satu sheet Template yang tetap bersih dengan token, merges, dan print setup, lalu untuk tiap region atau periode panggil Duplicate, isi token pada copy dengan slice data, lalu lanjut. Template bersih tidak pernah termodifikasi sehingga tetap menjadi sumber yang konsisten untuk clone berikutnya, dan setiap output sheet selalu berawal dari layout identik byte per byte
Satu urutan mencegah kebingungan. Duplikasi sheet harus dilakukan sebelum menaruh data, bukan setelahnya. Template seharusnya memegang struktur dan formatting, bukan angka kuartal sebelumnya; meng-copy sheet yang sudah berisi data akan membawa data itu juga karena CopyFrom menyalin used range utuh. Itu kadang berguna, tapi untuk laporan fan-out biasanya bukan yang Anda mau
Kebiasaan verifikasi cepat
Karena perbedaan deep-copy dan shallow-copy tidak terlihat, bangun pengecekan lima langkah dalam proses alih-alih hanya mengandalkan hasil. Setelah duplikasi, baca sinyal struktural yang harus diwarisi clone lalu pastikan sesuai sumber
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.
Jumlah merged, lebar kolom, freeze row, dan flag tab-colour memberi sinyal bahwa lapisan yang ditiru memang terbawa. Di setiap sheet yang awalnya memuat chart, table, validation, atau conditional format, daftar ini harus dianggap list yang perlu dibangun ulang di copy: ketidakhadirannya adalah desain, jadi perbaikannya hanya beberapa method pemanggilan, bukan tiket bug. Model ini, dalam kondisi aman pada bagian yang deep-copy dan tidak memaksa shallow-copy saat akan mematahkan relasi, adalah intisari penggunaan fitur ini
Worksheet duplication dan salinan state sheet via CopyFrom dibawa di v2.91.0 dari native HotXLS Delphi spreadsheet component, bersama contoh runnable SheetCopy yang menjalankan siklus clone-and-mutate secara end to end