Apa pola desain yang baik untuk menghasilkan file Excel (xlsx) dalam kode?


12

Lihat Pembaruan saya di bagian bawah untuk informasi lebih lanjut.


Saya kadang-kadang memiliki proyek di mana saya harus menampilkan beberapa data sebagai file Excel (format xlsx). Prosesnya biasanya:

  1. Pengguna mengklik beberapa tombol di aplikasi saya

  2. Kode saya menjalankan kueri DB dan memproses hasilnya, entah bagaimana

  3. Kode saya menghasilkan file * .xlsx menggunakan pustaka interop Excel com atau pustaka pihak ketiga (mis., Aspose.Cell)

Saya dapat dengan mudah menemukan contoh kode untuk melakukan hal ini secara online, tetapi saya mencari cara yang lebih kuat untuk melakukan ini. Saya ingin kode saya mengikuti beberapa prinsip desain untuk memastikan bahwa kode saya dapat dipelihara dan mudah dimengerti.


Berikut ini adalah upaya awal saya untuk menghasilkan file xlsx:

var wb = new Workbook();
var ws = wb.Worksheets[0];
ws.Cells[0, 0].Value = "Header";
ws.Cells[1, 0].Value = "Row 1";
ws.Cells[2, 0].Value = "Row 2";
ws.Cells[3, 0].Value = "Row 3";
wb.Save(path);

Pro: Tidak banyak. Itu bekerja, jadi itu bagus.

Cons:

  • Referensi sel di-hardcode, jadi saya memiliki angka ajaib yang berserakan di seluruh kode saya.
  • Sulit untuk menambah atau menghapus kolom dan baris tanpa memperbarui banyak referensi sel.
  • Saya perlu belajar beberapa perpustakaan pihak ketiga. Beberapa perpustakaan digunakan seperti perpustakaan lain, tetapi masih ada masalah. Saya punya masalah di mana perpustakaan interop com menggunakan referensi sel berbasis 1 sedangkan Aspose.Cells menggunakan referensi sel berbasis 0.

Berikut adalah salah satu solusi yang membahas beberapa kontra yang saya sebutkan di atas. Saya ingin memperlakukan tabel data sebagai objeknya sendiri yang dapat dipindahkan dan diubah tanpa menggali manipulasi sel dan mengganggu referensi sel lainnya. Inilah beberapa kodesemu:

var headers = new Block(new string[] { "Col 1", "Col 2", "Col 3" });
var body = new Block(new string[,]
    {
        { "Row 1", "Row 1", "Row 1" },
        { "Row 2", "Row 2", "Row 2" },
        { "Row 3", "Row 3", "Row 3" }
    });

body.PutBelow(headers);

Sebagai bagian dari solusi ini, saya akan memiliki beberapa objek BlockEngine yang mengambil wadah Blok dan melakukan manipulasi sel yang diperlukan untuk menampilkan data sebagai file * .xlsx. Objek Blok dapat memiliki pemformatan yang terlampir padanya.

Pro:

  • Ini menghapus sebagian besar angka ajaib yang dimiliki kode awal saya.
  • Ini menyembunyikan banyak kode manipulasi sel, meskipun manipulasi sel masih diperlukan dalam objek BlockEngine yang saya sebutkan.
  • Jauh lebih mudah untuk menambah dan menghapus baris tanpa mempengaruhi bagian lain dari spreadsheet.

Cons:

  • Masih sulit untuk menambah atau menghapus kolom. Jika saya ingin menukar posisi kolom dua dan tiga, saya harus langsung menukar konten sel. Dalam hal ini, itu akan menjadi delapan suntingan, dan dengan demikian delapan peluang untuk membuat kesalahan.
    • Jika saya memiliki pemformatan di tempat untuk dua kolom itu, saya harus memperbarui itu juga.
  • Solusi ini tidak mendukung penempatan blok horisontal; Saya hanya bisa menempatkan satu blok di bawah yang lain. Tentu saya bisa tableRight.PutToRightOf(tableLeft), tetapi itu akan menyebabkan masalah jika tableRight dan tableLeft memiliki jumlah baris yang berbeda. Untuk menempatkan tabel, mesin harus menyadari setiap meja lainnya. Ini sepertinya tidak perlu rumit bagi saya.
  • Saya masih perlu belajar kode pihak ketiga, meskipun melalui lapisan abstraksi melalui objek Block dan BlockEngine kode akan kurang erat-digabungkan ke perpustakaan pihak ketiga daripada upaya awal saya. Jika saya ingin mendukung banyak opsi pemformatan berbeda dengan cara yang digabungkan secara longgar, saya mungkin harus menulis banyak kode; BlockEngine saya akan sangat berantakan.

Inilah solusi yang mengambil rute berbeda. Inilah prosesnya:

  1. Saya mengambil data laporan saya dan menghasilkan file xml dalam beberapa format yang saya pilih.

  2. Saya kemudian menggunakan transformasi xsl untuk mengkonversi file xml ke file Excel Spreadsheet XML 2003.

  3. Dari sana saya cukup mengkonversi Spreadsheet xml ke file xlsx menggunakan perpustakaan pihak ketiga.

Saya menemukan halaman ini yang menjelaskan proses serupa dan menyertakan contoh kode.

Pro:

  • Solusi ini hampir tidak memerlukan manipulasi sel. Anda malah menggunakan xsl / xpath untuk melakukan manipulasi Anda. Untuk menukar dua kolom dalam sebuah tabel, Anda memindahkan seluruh kolom dalam file xsl tidak seperti solusi saya yang lain yang membutuhkan swapping sel.
  • Meskipun Anda masih memerlukan pustaka pihak ketiga yang dapat mengonversi Excel 2003 XML Spreadsheet ke file xlsx, itu saja yang Anda perlukan untuk pustaka. Jumlah kode yang perlu Anda tulis yang akan memanggil ke perpustakaan pihak ketiga sangat kecil.
  • Saya pikir solusi ini adalah yang termudah untuk dipahami dan membutuhkan jumlah kode paling sedikit.
    • Kode yang membuat data dalam format xml saya sendiri akan sederhana.
    • File xsl akan menjadi rumit hanya karena Excel 2003 XML Spreadsheet rumit. Namun mudah untuk memeriksa output dari file xsl: cukup buka output di Excel dan periksa pesan kesalahan.
    • Sangat mudah untuk menghasilkan sampel file Excel 2003 XML Spreadsheet: cukup buat spreadsheet yang terlihat seperti file xlsx yang Anda inginkan, dan kemudian simpan sebagai Excel 2003 XML Spreadsheet.

Cons:

  • Excel 2003 XML Spreadsheets tidak mendukung fitur tertentu. Misalnya, Anda tidak dapat membuat lebar kolom secara otomatis. Anda tidak dapat memasukkan gambar dalam header atau footer. Jika Anda akan mengekspor file xlsx yang dihasilkan ke pdf, Anda tidak dapat mengatur bookmark pdf. (Saya meretas bersama perbaikan untuk ini menggunakan komentar sel.). Anda harus melakukan ini menggunakan perpustakaan pihak ketiga Anda.
  • Membutuhkan perpustakaan yang mendukung Excel 2003 XML Spreadsheets.
  • Menggunakan format file MS Office berusia 11 tahun.

Catatan: Saya menyadari bahwa file xlsx sebenarnya adalah file zip yang berisi file xml, tetapi format xml sepertinya terlalu rumit untuk tujuan saya.


Akhirnya, saya telah mencari solusi yang melibatkan SSR, tetapi tampaknya terlalu membengkak untuk tujuan saya.


Kembali ke pertanyaan awal saya, apa pola desain yang baik untuk menghasilkan file Excel dalam kode ?. Saya dapat memikirkan beberapa solusi, tetapi tidak ada yang tampak ideal. Masing-masing memiliki kekurangan.


Pembaruan: Jadi saya mencoba solusi BlockEngine saya dan solusi XML Spreadsheet saya untuk menghasilkan file XLSX serupa. Inilah pendapat saya tentang mereka:

  • Solusi BlockEngine:

    • Ini hanya membutuhkan terlalu banyak kode mempertimbangkan alternatif.
    • Saya merasa terlalu mudah untuk menimpa satu blok dengan yang lain jika saya memiliki offset yang salah.
    • Saya awalnya menyatakan bahwa pemformatan dapat dilampirkan pada level blok. Saya menemukan ini tidak jauh lebih baik daripada melakukan format secara terpisah dari konten blokir. Saya tidak bisa memikirkan cara yang baik untuk menggabungkan konten dan format. Saya juga tidak dapat menemukan cara yang baik untuk memisahkan mereka. Itu hanya berantakan.
  • Solusi XML Spreadsheet:

    • Saya akan menggunakan solusi ini untuk saat ini.
    • Perlu diulang bahwa solusi ini membutuhkan kode jauh lebih sedikit. Saya secara efektif mengganti BlockEngine dengan Excel itu sendiri. Saya masih membutuhkan peretasan untuk fitur-fitur seperti bookmark dan page break.
    • Format XML Spreadsheet cukup bagus, tetapi mudah untuk membuat perubahan kecil dan membandingkan hasilnya dengan file yang ada di program Diff favorit Anda. Dan setelah Anda menemukan beberapa keanehan, Anda dapat meletakkannya di tempat dan melupakannya dari sana.
    • Saya masih khawatir bahwa solusi ini bergantung pada format file Excel yang lebih lama.
    • File XSLT yang saya buat mudah digunakan. Berurusan dengan pemformatan jauh lebih sederhana di sini daripada dengan solusi BlockEngine.

Jawaban:


7

Jika Anda benar-benar menginginkan sesuatu yang bekerja dengan baik untuk Anda, maka saya sarankan Anda terbiasa dengan ide "tidak perlu rumit" ... itulah sifat berurusan dengan format file Microsoft Office.

Saya (semacam) menyukai ide Anda tentang "blok" ... Saya akan membuat objek blok sub-kelas, seperti Tabel, dengan Kolom dan Baris tidak tergantung pada gagasan sel. Kemudian gunakan mesin blok Anda untuk mengonversikannya ke file XSLS.

Saya telah menggunakan OpenXML SDK berhasil di masa lalu, tetapi jangan mencoba membaca dokumentasi dan mulai dari awal. Alih-alih, buat salinan persis di Excel tentang apa yang Anda inginkan, simpan, dan periksa menggunakan alat Reflektor Dokumen yang disediakan. Ini akan memberi Anda kode C # yang Anda butuhkan untuk membuat dokumen, yang kemudian dapat Anda pelajari dan modifikasi.


Dokumen kantor BUKAN "kompleks yang tidak perlu" - mereka sedang melakukan atau memungkinkan sejumlah besar operasi, pemformatan, fungsi, dll.
warren

5
Saya tidak berpendapat bahwa format file itu sendiri tidak perlu rumit seperti halnya saya berpendapat bahwa bekerja dengannya. Misalnya, menggunakan OpenXML SDK mengharuskan Anda mengetahui urutan ajaib untuk menambahkan elemen ... menambahkan tata letak slide ke presentasi, misalnya, tidak berfungsi. Anda harus menambahkannya ke slide terlebih dahulu, dan kemudian ke presentasi. Mengapa? Karena Microsoft memberi kode perpustakaan seperti itu. Ada banyak referensi melingkar yang aneh untuk dikelola juga. Saya mengerti format membutuhkan kompleksitas, tetapi bekerja dengan itu seharusnya tidak begitu menyakitkan.
mgw854

3

Inilah solusi yang sering saya gunakan di masa lalu:

  • buat dokumen Excel biasa (biasanya dalam format xlsx) sebagai templat, berisi semua tajuk kolom, termasuk judul dan pemformatan default untuk kolom dan mungkin pemformatan untuk sel judul.

  • tempel templat itu ke sumber daya program Anda. Saat runtime, langkah pertama adalah mengekstraksi template sebagai file baru dan menempatkannya ke folder tujuan

  • gunakan Interop atau perpustakaan pihak ketiga untuk mengisi data ke xlsx yang baru dibuat. Jangan merujuk ke nomor kolom hardcode, melainkan gunakan beberapa metadata (misalnya header kolom) untuk mengidentifikasi kolom yang benar.

Pro:

  • sesuatu seperti pendekatan Blok Anda sekarang berfungsi lebih baik. Misalnya, bertukar kolom: tidak perlu mengubah apa pun dalam kode blok Anda, karena kolom yang benar diidentifikasi oleh tajuknya

  • selama kolom Anda memiliki pemformatan unik, sebagian besar pemformatan dapat dilakukan secara langsung di Excel, dengan memanipulasi templat Anda. Itu memberi Anda perasaan WYSIWYG, bersama dengan kebebasan untuk menggunakan opsi pemformatan apa pun yang tersedia di Excel tanpa perlu menulis kode untuk itu

Cons:

  • Anda masih perlu menggunakan lib pihak ketiga atau Interop. Apakah saya menyebutkan bahwa Interop lambat?

  • ketika tajuk kolom berubah dalam templat Anda, Anda perlu menyesuaikan juga kode Anda (tapi itu dapat dengan mudah dideteksi dengan memiliki rutin validasi yang memberi sinyal jika ada kolom yang diharapkan hilang)

  • ketika Anda membutuhkan pemformatan dinamis sel yang berbeda di kolom yang sama, Anda masih harus berurusan dengan itu dalam kode

Sebagai petunjuk umum, pendekatan apa pun yang Anda pilih: memiliki keunggulan untuk memisahkan tata letak dari konten dan memanfaatkan solusi deklaratif.


0

Ada dua hal yang perlu dipertimbangkan:

  • Kompleksitas membuat file dalam format yang diberikan
  • Kerentanan kode terhadap kerusakan ketika struktur konten file perlu diubah.

Mengenai yang pertama:

Jika spreadsheet yang Anda perlukan tidak mengandung format atau formula apa pun , maka Anda cukup mudah untuk membuat file CSV atau Tab-Delimited alih-alih XLSX yang sebenarnya. Excel membuka file-file ini, sering secara default pada banyak PC. Ini tidak akan membantu Anda dengan pengkodean yang sulit di sekitar kolom dan baris tetapi itu akan menghemat kerja ekstra Anda memanipulasi model objek Excel.

Jika Anda perlu memformat atau rumus, maka bekerja dengan model objek Excel adalah cara yang masuk akal, terutama jika Anda membuat spreadsheet yang tidak terlalu "dikodekan". Dengan kata lain, jika spreadsheet Anda menggunakan rumus relatif dan rentang nama secara tepat, maka ia dapat digunakan bersamaan dengan pengkodean angka ajaib yang kurang sulit.

Mengenai yang kedua:

Anda dapat bekerja melalui sel dengan sel dengan referensi baris dan kolom yang tersandi kode, atau Anda dapat bekerja dengan array / koleksi koleksi dan forloop untuk menggeneralisasi populasi sel.


Saya tidak jelas dalam pertanyaan awal saya bahwa saya ingin mengontrol opsi pemformatan dan pencetakan dan semacamnya dalam solusi saya. Mengenai poin kedua, saya pikir apa yang Anda maksudkan adalah apa yang saya jelaskan dalam BlockEnginesolusi saya . Saya bisa mengambil IList<IBusinessObject>dan mengeluarkan Blockbenda. Pro dan kontra akan tetap sama.
user2023861
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.