Menggabungkan DOCX, XLSX, dan PDF menjadi satu binder — demo run

The thing that kept eating my Fridays

Setiap Jumat sore, 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 mengirim binder dengan lampiran di halaman satu karena nama file diurutkan secara alfabetis di aplikasi penggabung.

Jika ini terdengar familiar, sisa posting 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 salah.

What I actually wanted

Bukan “pipeline dokumen yang mewah.” Hanya tiga hal:

  1. Beri sebuah metode daftar file (campuran DOCX, XLSX, PDF) dan dapatkan satu PDF kembali.
  2. Arahkan logika yang sama ke sebuah folder dan biarkan ia menentukan daftar file secara otomatis.
  3. 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 tahu.

Setup

  • .NET 6.0 atau lebih baru
  • GroupDocs.Merger for .NET 24.10+ (grab a temporary license sehingga Anda 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.

Step 1 — Let a folder be the input

Saya selalu memulai di sini karena ini adalah titik masuk yang realistis. Pada praktiknya, sesuatu yang lain (handler upload, job 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 output dari file pertama yang Anda buka — jika saya memberi DOCX sebagai dokumen utama, saya akan mendapatkan DOCX sebagai output. Karena pipeline saya selalu menginginkan PDF sebagai output, saya memastikan setiap PDF yang ada di folder mendapat posisi 0.

Dua hal yang patut disebutkan:

  • ToLowerInvariant() karena suatu hari nanti mitra akan mengirimkan REPORT.PDF dan filter yang hanya memeriksa huruf kecil akan secara diam‑diam menyingkirkannya.
  • ThenBy(f) hanya ada untuk membuat output menjadi deterministik. Tanpa itu, dua kali jalankan pada folder yang sama dapat menghasilkan urutan yang berbeda tergantung mood sistem file.

Step 2 — The merge itself

Setelah saya memiliki daftar path yang terurut, proses penggabungan lebih singkat daripada deskripsi penggabungannya.

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 secara intensif:

  • using penting. Merger memegang handle file pada sumber; jika Anda lupa membuangnya, pekerja folder‑drop Anda pada akhirnya tidak akan dapat menghapus inputnya sendiri.
  • JoinOptions kosong 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 ditentukan 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 sanity 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 secara diam‑diam” daripada tes apa pun yang pernah saya tulis.

Step 3 — Extract a slice later

Permintaan lanjutan yang saya dapatkan setiap kali: “Bisakah Anda kirimkan halaman sampul saja?” atau “Klien hanya menginginkan tanda tangan.” Membangun kembali seluruh binder hanya untuk menyerahkan dua halaman adalah hal yang bodoh — Extract 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 akan dibuang. Ini cepat karena hasilnya sudah berupa PDF — tidak ada konversi bolak‑balik.

Before vs. after, honestly

Apa yang dulu saya lakukan Dengan Merger.Join
Waktu per kontrak 5–10 menit klik‑klik kurang dari 30 detik end‑to‑end
Kegagalan umum Halaman dalam urutan salah, tidak ada yang menyadari Urutan apa pun yang ada di daftar file, konsisten
Skalabilitas 100/hari Tidak ada — 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 suara keras.

A real story from a tiny legal-tech team

Sebuah startup dua orang yang saya bantu memiliki paralegal yang pagi harinya dimulai dengan perakitan kontrak. Perjanjian Word, harga Excel, addendum PDF, dijahit dalam sebuah aplikasi, lalu di‑upload ke DocuSign. Sekitar delapan menit per paket, yang pada 30 paket per hari pada dasarnya menghabiskan seluruh paginya.

Mereka menaruh metode pemindaian folder ke dalam layanan backend yang sudah memantau email masuk mereka. Dua puluh detik per paket, ditambah satu baris log dengan jumlah halaman. Paralegal beralih ke peninjauan kontrak alih‑alih merakitnya. Tidak ada lagi binder yang dikirim dengan urutan salah — bukan karena pustaka itu ajaib, melainkan karena daftar file eksplisit di 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.

Stuff I didn’t need today but will tomorrow

Pustaka yang sama melakukan banyak hal yang tidak saya bahas karena artikel ini akan menjadi terlalu panjang. Secara urutan kira‑kira saya gunakan:

  • Watermarks on the output untuk stempel “DRAFT” pada salinan pra‑tanda tangan.
  • Page rotation untuk pemindaian yang masuk miring.
  • Custom page ordering ketika urutan sumber bukan urutan pengiriman.
  • PDF encryption untuk apa pun yang dikirim ke pihak eksternal.

Semua itu berada di balik API Merger yang sama. docs memiliki daftar lengkap — saya hanya ingin menekankan bahwa “merge” adalah starter yang murah dan sisanya tersedia ketika Anda membutuhkannya.

What I’d tell past-me

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 ter‑embed, dan sebagainya. Biarkan sesuatu yang lain mengurus permukaan itu, dan habiskan Jumat sore Anda pada sesuatu yang bukan sekadar penyortiran nama file.

Ke mana harus melangkah selanjutnya: