Daha fazla bilgi için aşağıdaki Güncellememe bakın.
Bazen bazı verileri bir Excel dosyası (xlsx formatı) olarak çıktılamak zorunda olduğum projelerim var. İşlem genellikle:
Kullanıcı uygulamamdaki bazı düğmeleri tıklıyor
Kodum bir DB sorgusu çalıştırır ve sonuçları bir şekilde işler
Kodum, Excel com birlikte çalışma kitaplıkları veya bazı üçüncü taraf kitaplıkları (ör. Aspose.Cells) kullanarak bir * .xlsx dosyası oluşturur
Bunu nasıl çevrimiçi yapmak için kolayca kod örnekleri bulabilirsiniz, ancak bunu yapmak için daha sağlam bir yol arıyorum. Kodumun korunabilir ve kolay anlaşılır olmasını sağlamak için kodumun bazı tasarım ilkelerini izlemesini istiyorum.
İşte benim xlsx dosyası oluşturmak için ilk denemem şöyle görünüyordu:
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);
Artıları: Fazla değil. Çalışıyor, bu yüzden iyi.
Eksileri:
- Hücre başvuruları sabit kodlu, bu yüzden kodum boyunca sihirli numaralar var.
- Çok sayıda hücre referansını güncellemeden sütun ve satır eklemek veya kaldırmak zordur.
- Bazı üçüncü taraf kütüphanelerini öğrenmem gerekiyor. Bazı kütüphaneler diğer kütüphaneler gibi kullanılır, ancak yine de sorunlar olabilir. Aspose.Cells 0 tabanlı hücre başvurusu kullanırken com birlikte çalışma kitaplıkları 1 tabanlı hücre başvurusu kullanan bir sorun vardı.
Yukarıda listelediğim bazı eksilerini ele alan bir çözüm. Bir veri tablosunu, hücre manipülasyonuna kazmadan ve diğer hücre referanslarını bozmadan hareket ettirilebilen ve değiştirilebilen kendi nesnesi olarak ele almak istedim. İşte bazı sözde kod:
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);
Bu çözümün bir parçası olarak, bir Blocks kapsayıcısı alan ve verileri bir .xlsx dosyası olarak çıktılamak için gereken hücre manipülasyonlarını gerçekleştiren bazı BlockEngine nesnesine sahip olacağım. Bir Block nesnesinin üzerine biçimlendirilmiş olabilir.
Artıları:
- Bu, ilk kodumdaki sihirli sayıların çoğunu kaldırır.
- Bahsettiğim BlockEngine nesnesinde hücre manipülasyonu hala gerekli olmasına rağmen, bu birçok hücre manipülasyon kodunu gizler.
- E-tablonun diğer bölümlerini etkilemeden satır eklemek ve kaldırmak çok daha kolaydır.
Eksileri:
- Sütun eklemek veya kaldırmak hala zor. İki ve üç sütunun konumunu değiştirmek istersem, doğrudan hücre içeriğini değiştirmem gerekirdi. Bu durumda, bu sekiz düzenleme ve dolayısıyla bir hata yapmak için sekiz fırsat olurdu.
- Bu iki sütun için herhangi bir biçimlendirmem varsa, bunu da güncellemeliyim.
- Bu çözüm yatay blok yerleşimini desteklemez; Sadece bir bloğu diğerinin altına yerleştirebilirim. Tabii ki olabilirdi
tableRight.PutToRightOf(tableLeft)
, ancak tableRight ve tableLeft'in farklı sayıda satırı varsa sorunlara neden olabilir. Tablo yerleştirmek için motorun diğer tüm tablolardan haberdar olması gerekir. Bu benim için gereksiz yere karmaşık görünüyor. - Yine de üçüncü taraf kodu öğrenmem gerekiyor, ancak Block nesneleri ve bir BlockEngine üzerinden soyutlama katmanı aracılığıyla kod, ilk denememden daha az üçüncü taraf kütüphanesine daha az bağlı olacak. Gevşek bir şekilde çok sayıda farklı biçimlendirme seçeneğini desteklemek istersem, muhtemelen çok fazla kod yazmak zorunda kalırdım; BlockEngine'm büyük bir karmaşa olurdu.
İşte farklı bir rota izleyen bir çözüm. İşlem şu şekildedir:
Rapor verilerimi alıp, seçtiğim formatta bir xml dosyası oluşturuyorum.
Daha sonra xml dosyasını bir Excel 2003 XML Elektronik Tablosu dosyasına dönüştürmek için bir xsl dönüşümü kullanıyorum.
Oradan sadece bir üçüncü taraf kitaplığı kullanarak xml Elektronik Tablosu bir xlsx dosyasına dönüştürmek.
Benzer bir işlemi açıklayan ve kod örnekleri içeren bu sayfayı buldum .
Artıları:
- Bu çözüm neredeyse hiç hücre manipülasyonu gerektirmez. Bunun yerine manipülasyonlarınızı yapmak için xsl / xpath kullanırsınız. Tablodaki iki sütunu takas etmek için xsl dosyasındaki tüm sütunları, hücre değiştirmeyi gerektiren diğer çözümlerimin aksine taşırsınız.
- Hala bir Excel 2003 XML Elektronik Tablosunu xlsx dosyasına dönüştürebilen üçüncü taraf bir kütüphaneye ihtiyacınız olsa da, kütüphaneye ihtiyacınız olan tek şey budur. Üçüncü taraf kitaplığını çağıracak, yazmanız gereken kod miktarı azdır.
- Bence bu çözüm anlaşılması en kolay ve en az miktarda kod gerektirir.
- Verileri kendi xml biçimimde oluşturan kod basit olacaktır.
- Xsl dosyası yalnızca Excel 2003 XML Elektronik Tablosu karmaşık olduğundan karmaşık olacaktır. Ancak xsl dosyasının çıktısını kontrol etmek kolaydır: çıktıyı Excel'de açın ve hata mesajlarını kontrol edin.
- Örnek Excel 2003 XML Elektronik Tablosu dosyaları oluşturmak kolaydır: istediğiniz xlsx dosyasına benzeyen bir elektronik tablo oluşturun ve Excel Excel XML Elektronik Tablosu olarak kaydedin.
Eksileri:
- Excel 2003 XML Elektronik Tabloları belirli özellikleri desteklemez. Örneğin sütun genişliklerine otomatik sığdıramazsınız. Üstbilgi veya altbilgiye resim ekleyemezsiniz. Ortaya çıkan xlsx dosyasını pdf'ye dışa aktaracaksanız, pdf yer imlerini ayarlayamazsınız. (Hücre yorumlarını kullanarak bunun için bir düzeltme hackledim.). Bunu üçüncü taraf kitaplığınızı kullanarak yapmanız gerekir.
- Excel 2003 XML Elektronik Tablolarını destekleyen bir kitaplık gerektirir.
- 11 yaşında bir MS Office dosya biçimi kullanır.
Not: xlsx dosyalarının aslında xml dosyaları içeren zip dosyaları olduğunu anlıyorum, ancak xml biçimlendirmesi benim amacım için çok karmaşık görünüyor.
Son olarak, SSRS'yi içeren çözümleri araştırdım, ancak bu benim amacım için çok şişkin görünüyor.
İlk soruma geri dönelim, kodda Excel dosyaları oluşturmak için iyi bir tasarım deseni nedir ?. Birkaç çözüm düşünebilirim, ama hiçbiri ideal gibi görünmüyor. Her birinin dezavantajları vardır.
Güncelleme: Bu yüzden hem XLEX dosyalarını hem de BlockEngine çözümümü ve XML Elektronik Tablo çözümümü denedim. İşte benim düşüncelerim:
BlockEngine çözümü:
- Bu sadece alternatifleri göz önünde bulundurarak çok fazla kod gerektirir.
- Yanlış bir ofset olsaydı bir bloğun üzerine başka bir blok yazmayı çok kolay buldum.
- Başlangıçta biçimlendirmenin blok düzeyinde eklenebileceğini belirtmiştim. Bunu, biçimlendirmeyi blok içeriğinden ayrı yapmaktan daha iyi bulmadım. İçeriği ve biçimlendirmeyi birleştirmenin iyi bir yolunu düşünemiyorum. Onları ayrı tutmanın iyi bir yolunu da bulamıyorum. Bu sadece bir karmaşa.
XML Elektronik Tablosu çözümü:
- Şimdilik bu çözümü kullanıyorum.
- Bu çözümün çok daha az kod gerektirdiğini yineliyor. BlockEngine'i Excel'in kendisiyle etkili bir şekilde değiştiriyorum. Yer imleri ve sayfa sonları gibi özellikler için hala bir saldırıya ihtiyacım var.
- XML Elektronik Tablosu biçimi titizdir, ancak küçük bir değişiklik yapmak ve sonuçları favori Diff programınızdaki mevcut bir dosyayla karşılaştırmak kolaydır. Ve bir kez kendine özgü bir şey bulduktan sonra, onu yerine koyabilir ve oradan unutabilirsiniz.
- Hala bu çözümün eski bir Excel dosya biçimine dayandığından endişeleniyorum.
- Oluşturduğum XSLT dosyasının çalışması kolaydır. Biçimlendirme ile uğraşmak burada BlockEngine çözümüyle olduğundan çok daha basittir.