Hal yang Memakan Jumat Saya
Setiap sore Jumat, selama kira‑kira setahun, saya memiliki ritual kecil yang sama. Sebuah kontrak datang dalam tiga file — perjanjian utama dalam Word, lampiran harga dalam Excel, dan lembar syarat mitra sebagai PDF — dan saya harus menggabungkannya menjadi satu PDF yang bersih. Tidak sulit. Buka Word, ekspor ke PDF. Buka Excel, ekspor ke PDF. Buka aplikasi penggabung PDF gratis, seret tiga file, periksa urutan, simpan.
Butuh sekitar delapan menit. Kalikan dengan lima belas kontrak per minggu dan Anda kehilangan dua jam hanya karena menggerakkan mouse. Lebih parah, setiap beberapa minggu seseorang mengirimkan binder dengan lampiran di halaman satu karena nama file diurutkan secara alfabet di aplikasi penggabungan.
Jika ini terdengar familiar, sisa postingan ini adalah sore ketika saya akhirnya mengganti ritual tersebut dengan kode.
Biaya sebenarnya bukan waktunya — melainkan satu kontrak dari lima puluh di mana halaman berada dalam urutan yang salah dan tidak ada yang menyadarinya sampai klien menandatangani versi yang keliru.
Apa yang Sebenarnya Saya Inginkan
Bukan “pipeline dokumen yang mewah.” Hanya tiga hal:
- Beri sebuah metode daftar file (campuran apa saja dari DOCX, XLSX, PDF) dan dapatkan satu PDF kembali.
- Arahkan logika yang sama ke sebuah folder dan biarkan ia menentukan daftar file secara otomatis.
- Ambil rentang halaman dari binder yang sudah selesai tanpa harus mengulang seluruh proses penggabungan.
Itulah seluruh pekerjaan. Jika pustaka tidak dapat melakukan ketiga hal itu dengan bersih, saya tidak mau mendengarnya.
Persiapan
- .NET 6.0 atau lebih baru
- GroupDocs.Merger untuk .NET 24.10+ (dapatkan lisensi sementara agar tidak mengirimkan watermark evaluasi)
- Sebuah folder dengan campuran dokumen apa pun yang biasanya Anda gabungkan secara manual
dotnet add package GroupDocs.Merger
Itu saja untuk dependensi. Tidak ada konverter eksternal, tidak ada instalasi Office headless, tidak ada pustaka manipulasi PDF di atasnya.
Langkah 1 — Biarkan Sebuah Folder Menjadi Input
Saya selalu memulai di sini karena itu adalah titik masuk yang realistis. Pada praktiknya, sesuatu yang lain (handler unggahan, pekerjaan ingest email, dump malam dari keuangan) menaruh sekumpulan file ke dalam sebuah direktori, dan kode saya harus menangani apa pun yang ditemukan.
// Pick up every supported file in the drop folder; the PDF wins
// the tie-break for position 0 so the merger keeps the output
// as a PDF regardless of how files are named.
string[] extensions = { ".pdf", ".docx", ".xlsx" };
var files = Directory.EnumerateFiles(folderPath)
.Where(f => extensions.Contains(Path.GetExtension(f).ToLowerInvariant()))
.OrderBy(f => Path.GetExtension(f).ToLowerInvariant() == ".pdf" ? 0 : 1)
.ThenBy(f => f)
.ToArray();
if (files.Length == 0)
throw new InvalidOperationException(
$"No supported documents found in '{folderPath}'.");
Trik OrderBy adalah bagian yang menarik. GroupDocs.Merger memilih format outputnya dari file pertama yang Anda buka — jika saya memberinya DOCX sebagai dokumen utama, saya akan mendapatkan DOCX keluar. Karena pipeline saya selalu menginginkan PDF keluar, saya memastikan setiap PDF yang ada di folder mendapat posisi 0.
Dua hal yang patut disebutkan:
ToLowerInvariant()karena suatu hari nanti mitra akan mengirimkanREPORT.PDFdan filter yang hanya huruf kecil Anda akan secara diam‑diam menyingkirkannya.ThenBy(f)hanya ada untuk membuat output menjadi deterministik. Tanpanya, dua kali jalankan pada folder yang sama dapat menghasilkan urutan yang berbeda tergantung mood sistem berkas.
Langkah 2 — Penggabungan Itu Sendiri
Setelah saya memiliki daftar jalur yang terurut, proses penggabungan lebih singkat daripada deskripsi penggabungan.
Console.WriteLine($"Primary source: {sourcePaths[0]}");
using var merger = new Merger(sourcePaths[0]);
var joinOptions = new JoinOptions();
for (int i = 1; i < sourcePaths.Length; i++)
{
Console.WriteLine($"Joining: {sourcePaths[i]}");
merger.Join(sourcePaths[i], joinOptions);
}
merger.Save(outputPath);
Console.WriteLine($"Unified PDF binder saved to: {Path.GetFullPath(outputPath)}");
Beberapa catatan dari penggunaan ini dalam kondisi nyata:
usingpenting.Mergermemegang handle file pada sumber; lupa membuangnya akan membuat pekerja folder‑drop Anda akhirnya gagal menghapus inputnya sendiri.JoinOptionskosong di sini karena nilai default adalah apa yang saya inginkan 95 % waktu. Ketika Anda memang membutuhkannya, di situlah rentang halaman, rotasi, dan posisi sisipan berada.- Ketika Excel masuk ke binder, tata letak lembar‑ke‑halaman diputuskan oleh area cetak workbook sumber. Jika XLSX Anda berakhir menjadi 38 halaman dan Anda menginginkan tiga, perbaikannya ada di spreadsheet, bukan di
JoinOptions.
Satu pemeriksaan kewarasan yang selalu saya tambahkan tepat setelah penyimpanan:
using var verify = new Merger(outputPath);
Console.WriteLine($"Result pages: {verify.GetDocumentInfo().PageCount}");
Dua detik kode yang telah menangkap lebih banyak bug “lampiran yang disingkirkan diam‑diam” daripada tes apa pun yang pernah saya tulis.
Langkah 3 — Ekstrak Irisan Nanti
Permintaan lanjutan yang saya dapatkan setiap kali: “Bisakah Anda kirimkan halaman sampul saja?” atau “Klien hanya mau tanda tangan.” Membangun kembali seluruh binder hanya untuk menyerahkan dua halaman adalah hal yang bodoh — ekstraksi melakukannya secara langsung.
using var merger = new Merger(binderPath);
merger.ExtractPages(new ExtractOptions(pages));
merger.Save(outputPath);
Console.WriteLine($"Extracted pages [{string.Join(",", pages)}] to " +
Path.GetFullPath(outputPath));
pages adalah int[] berisi nomor halaman berbasis 1 yang ingin Anda pertahankan. Semua yang lain dibuang. Ini cepat karena hasilnya sudah PDF — tidak ada konversi bolak‑balik.
Sebelum vs. Sesudah, Jujur
| Apa yang dulu saya lakukan | Dengan Merger.Join |
|
|---|---|---|
| Waktu per kontrak | 5–10 menit mengklik | kurang dari 30 detik end‑to‑end |
| Kegagalan umum | Halaman dalam urutan salah, tidak ada yang menyadari | Urutan apa pun yang tercantum dalam daftar file, konsisten |
| Skalabilitas 100/hari | Tidak — Anda mempekerjakan orang | Satu pekerja, biasanya bosan |
| Kode yang dipelihara | Halaman Confluence berjudul “Binder Process v4” | Satu kelas, ~70 baris |
| Output | Tiga PDF dan doa | Satu binder, dengan jumlah halaman yang dapat dicatat |
Baris yang paling saya pedulikan adalah “kegagalan”. Penggabungan manual gagal secara diam‑diam; kode yang mencatat jumlah halaman gagal dengan keras.
Cerita Nyata dari Tim Legal‑Tech Kecil
Sebuah startup dua orang yang saya bantu memiliki paralegal yang pagi harinya dimulai dengan perakitan kontrak. Perjanjian Word, harga Excel, lampiran PDF, dijahit dalam sebuah aplikasi, diunggah ke DocuSign. Sekitar delapan menit per paket, yang pada 30 paket sehari pada dasarnya adalah seluruh pagiannya.
Mereka menaruh metode pemindaian folder ke dalam layanan backend yang sudah memantau email masuk mereka. Dua puluh detik per paket, plus satu baris log dengan jumlah halaman. Paralegal beralih ke meninjau kontrak alih‑alih merakitnya. Tidak ada lagi binder yang dikirimkan dalam urutan yang salah — bukan karena pustaka itu ajaib, melainkan karena daftar file eksplisit dalam kode dan Anda dapat membandingkannya.
string folder = @"C:\IncomingContracts";
string output = @"C:\Processed\ContractPackage.pdf";
var files = CreatePdfBinderFromFolder(folder, output);
Console.WriteLine($"Package created: {files}");
Itulah seluruh integrasi. Semua yang berada di hulu (listener email, jalur penyimpanan) sudah ada.
Hal yang Tidak Saya Butuhkan Hari Ini tapi Akan Saya Pakai Besok
Pustaka yang sama melakukan banyak hal yang tidak saya bahas karena artikel ini akan menjadi terlalu panjang. Secara kasar urutan hal‑hal yang pernah saya gunakan:
- Watermarks pada output untuk stempel “DRAFT” pada salinan pra‑tanda tangan.
- Rotasi halaman untuk pemindaian yang datang miring.
- Urutan halaman khusus ketika urutan sumber bukan urutan pengiriman.
- Enkripsi PDF untuk apa pun yang dikirim ke pihak eksternal.
Semua itu berada di balik API Merger yang sama. Dokumen memiliki daftar lengkap — saya hanya ingin menekankan bahwa “merge” adalah starter yang murah dan sisanya tersedia ketika Anda membutuhkannya.
Apa yang Akan Saya Katakan pada Diri Saya di Masa Lalu
Jika Anda akan menulis langkah DOCX‑to‑PDF sendiri karena “hanya satu metode,” berhentilah. Konversi adalah bagian yang diam‑diam membusuk — fitur Office baru, penanganan gambar hasil scan, font tertanam, dan sebagainya. Biarkan sesuatu yang lain mengurus permukaan itu, dan habiskan sore Jumat Anda pada sesuatu yang bukan sekadar penyortiran nama file.
Ke mana harus melangkah selanjutnya:
- Temporary license — diperlukan untuk output tanpa watermark
- Advanced merging options — JoinOptions, opsi penyimpanan, kompresi
- Supported formats — jauh melampaui tiga yang saya tunjukkan di sini
- Sample projects on GitHub — termasuk yang satu ini