कोड में एक्सेल (xlsx) फ़ाइल बनाने के लिए एक अच्छा डिज़ाइन पैटर्न क्या है?


12

अधिक के लिए नीचे मेरा अपडेट देखें।


मेरे पास कभी-कभी ऐसी परियोजनाएँ होती हैं जहाँ मुझे कुछ डेटा एक्सेल फ़ाइल (xlsx प्रारूप) के रूप में आउटपुट करने होते हैं। प्रक्रिया आमतौर पर है:

  1. मेरे आवेदन में उपयोगकर्ता कुछ बटन क्लिक करता है

  2. मेरा कोड एक DB क्वेरी चलाता है और किसी तरह परिणाम संसाधित करता है

  3. मेरा कोड एक्सेल कॉम इंटरॉप लाइब्रेरीज़ या कुछ थर्ड पार्टी लाइब्रेरी (जैसे, असपोज़.कैल्स) का उपयोग करके * .xlsx फ़ाइल बनाता है।

इसे आसानी से ऑनलाइन कैसे किया जाए, इसके लिए मैं कोड उदाहरण आसानी से पा सकता हूं, लेकिन मैं इसे करने के लिए अधिक मजबूत तरीका ढूंढ रहा हूं। मैं अपने कोड को कुछ डिज़ाइन सिद्धांतों का पालन करना चाहूंगा ताकि यह सुनिश्चित हो सके कि मेरा कोड रखरखाव योग्य है और आसानी से समझ में आता है।


यहाँ एक 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);

पेशेवरों: ज्यादा नहीं। यह काम करता है, इसलिए यह अच्छा है।

विपक्ष:

  • सेल संदर्भ हार्डकोड किए गए हैं, इसलिए मेरे पास पूरे कोड में मैजिक नंबर हैं।
  • कई सेल संदर्भों को अपडेट किए बिना कॉलम और पंक्तियों को जोड़ना या निकालना मुश्किल है।
  • मुझे कुछ तृतीय-पक्ष पुस्तकालय सीखने की आवश्यकता है। कुछ पुस्तकालयों का उपयोग अन्य पुस्तकालयों की तरह किया जाता है, लेकिन अभी भी समस्याएं हो सकती हैं। मुझे एक समस्या थी जहां कॉम इंटरॉप लाइब्रेरीज़ 1-आधारित सेल रेफ़रिंग का उपयोग करती हैं, जबकि असोज़.केल्स 0-आधारित सेल रेफ़रिंग का उपयोग करती हैं।

यहां एक समाधान है जो ऊपर सूचीबद्ध कुछ विपक्षों को संबोधित करता है। मैं डेटा की एक तालिका को अपनी स्वयं की वस्तु के रूप में व्यवहार करना चाहता था जिसे सेल हेरफेर में खोदने और अन्य सेल संदर्भों को परेशान किए बिना बदल दिया जा सकता है। यहाँ कुछ छद्मकोड है:

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);

इस समाधान के एक हिस्से के रूप में, मेरे पास कुछ ब्लॉकबाईन ऑब्जेक्ट होंगे जो ब्लॉक के एक कंटेनर को लेते हैं और डेटा को * .xlsx फ़ाइल के रूप में आउटपुट करने के लिए आवश्यक सेल जोड़तोड़ करते हैं। किसी ब्लॉक ऑब्जेक्ट में इससे जुड़ी फ़ॉर्मेटिंग हो सकती है।

पेशेवरों:

  • यह उन अधिकांश मैजिक नंबरों को हटा देता है जो मेरे शुरुआती कोड में थे।
  • यह बहुत सारे सेल हेरफेर कोड को छुपाता है, हालांकि ब्लॉकबाइन ऑब्जेक्ट में सेल हेरफेर अभी भी आवश्यक है जो मैंने उल्लेख किया था।
  • स्प्रैडशीट के अन्य हिस्सों को प्रभावित किए बिना पंक्तियों को जोड़ना और निकालना बहुत आसान है।

विपक्ष:

  • कॉलम जोड़ना या निकालना अभी भी मुश्किल है। यदि मैं कॉलम दो और तीन की स्थिति को स्वैप करना चाहता था, तो मुझे सीधे सेल सामग्री को स्वैप करना होगा। इस मामले में कि आठ संपादन होंगे, और इस प्रकार गलती करने के आठ अवसर होंगे।
    • यदि मेरे पास उन दो कॉलमों के लिए कोई प्रारूपण है, तो मुझे उसे भी अपडेट करना होगा।
  • यह समाधान क्षैतिज ब्लॉक प्लेसमेंट का समर्थन नहीं करता है; मैं केवल एक ब्लॉक को दूसरे से नीचे रख सकता हूं। यकीन है कि मैं कर सकता था tableRight.PutToRightOf(tableLeft), लेकिन अगर टेबलट्राइट और टेबल लाइफ़ की पंक्तियों की अलग-अलग संख्याएँ होतीं तो समस्याएँ पैदा होतीं। टेबल लगाने के लिए, इंजन को हर दूसरे टेबल के बारे में पता होना चाहिए। यह मुझे अनावश्यक रूप से जटिल लगता है।
  • मुझे अभी भी तृतीय-पक्ष कोड सीखने की आवश्यकता है, हालांकि ब्लॉक ऑब्जेक्ट्स और एक ब्लॉकबाइन के माध्यम से अमूर्त की एक परत के माध्यम से कोड मेरे प्रारंभिक प्रयास की तुलना में तीसरे पक्ष के पुस्तकालय के लिए कम कसकर युग्मित होगा। अगर मैं बहुत सारे अलग-अलग प्रारूपण विकल्पों का समर्थन करना चाहता था, तो मैं शायद बहुत सारे कोड लिखना चाहता हूं; मेरी BlockEngine एक बड़ी गड़बड़ होगी।

यहां एक समाधान है जो एक अलग मार्ग लेता है। यहाँ प्रक्रिया है:

  1. मैं अपना रिपोर्ट डेटा लेता हूं और अपने द्वारा चुने गए किसी प्रारूप में एक xml फ़ाइल उत्पन्न करता हूं।

  2. मैं तब xml फ़ाइल को Excel 2003 XML स्प्रेडशीट फ़ाइल में परिवर्तित करने के लिए एक xsl परिवर्तन का उपयोग करता हूं।

  3. वहाँ से मैं बस एक तृतीय पक्ष लाइब्रेरी का उपयोग करके xml स्प्रेडशीट को xlsx फ़ाइल में परिवर्तित करता हूँ।

मुझे यह पृष्ठ मिला जो एक समान प्रक्रिया का वर्णन करता है और इसमें कोड उदाहरण शामिल हैं।

पेशेवरों:

  • इस समाधान के लिए लगभग कोई सेल हेरफेर की आवश्यकता नहीं है। इसके बजाय आप अपने जोड़तोड़ करने के लिए xsl / xpath का उपयोग करें। किसी तालिका में दो कॉलम स्वैप करने के लिए, आप मेरे अन्य समाधानों के विपरीत पूरे कॉलम को xsl फ़ाइल में ले जाते हैं, जिसके लिए सेल-स्वैपिंग की आवश्यकता होगी।
  • जबकि आपको अभी भी एक तृतीय-पक्ष लाइब्रेरी की आवश्यकता है जो Excel 2003 XML स्प्रेडशीट को xlsx फ़ाइल में बदल सकती है, इसके लिए आपको लाइब्रेरी की आवश्यकता होगी। आपको जिस कोड को लिखना है, उसे तीसरे पक्ष के पुस्तकालय में कॉल करना होगा।
  • मुझे लगता है कि यह समाधान समझने में सबसे आसान है और इसके लिए कम से कम कोड की आवश्यकता होती है।
    • कोड जो मेरे अपने xml प्रारूप में डेटा बनाता है, सरल होगा।
    • Xsl फ़ाइल केवल जटिल होगी क्योंकि Excel 2003 XML स्प्रेडशीट जटिल है। हालाँकि xsl फ़ाइल के आउटपुट की जाँच करना आसान है: एक्सेल में आउटपुट को खोलें और त्रुटि संदेशों की जाँच करें।
    • नमूना 2003 Excel XML स्प्रैडशीट फ़ाइलों को बनाना आसान है: बस एक स्प्रेडशीट बनाएं जो आपकी वांछित xlsx फ़ाइल की तरह दिखती है, और फिर इसे Excel 2003 XML स्प्रेडशीट के रूप में सहेजें।

विपक्ष:

  • Excel 2003 XML स्प्रेडशीट कुछ सुविधाओं का समर्थन नहीं करता है। आप उदाहरण के लिए कॉलम की चौड़ाई को ऑटोफिट नहीं कर सकते। आप शीर्ष लेख या पाद लेख में चित्र शामिल नहीं कर सकते। यदि आप परिणामी xlsx फ़ाइल को pdf में निर्यात करने जा रहे हैं, तो आप pdf बुकमार्क सेट नहीं कर सकते। (मैंने सेल टिप्पणियों का उपयोग करके इसे ठीक करने के लिए एक साथ हैक किया।) आपको अपने तीसरे पक्ष के पुस्तकालय का उपयोग करके ऐसा करना होगा।
  • एक पुस्तकालय की आवश्यकता है जो Excel 2003 XML स्प्रेडशीट का समर्थन करता है।
  • एक 11 वर्षीय एमएस ऑफिस फ़ाइल प्रारूप का उपयोग करता है।

नोट: मुझे पता है कि xlsx फाइलें वास्तव में xml फाइलों वाली ज़िप फाइलें हैं, लेकिन xml स्वरूपण मेरे उद्देश्यों के लिए बहुत जटिल लगता है।


अंत में, मैंने SSRS से जुड़े समाधानों पर ध्यान दिया है, लेकिन ऐसा लगता है कि यह मेरे उद्देश्यों के लिए बहुत फूला हुआ है।


मेरे प्रारंभिक प्रश्न पर वापस, कोड में एक्सेल फाइल बनाने के लिए एक अच्छा डिज़ाइन-पैटर्न क्या है? मैं कुछ समाधानों के बारे में सोच सकता हूं, लेकिन कोई भी आदर्श के रूप में बाहर रहना नहीं चाहता है। प्रत्येक में कमियां हैं।


अपडेट: तो मैंने समान XLSX फ़ाइलों को बनाने के लिए मेरे ब्लॉकबाइन समाधान और मेरे XML स्प्रैडशीट समाधान दोनों की कोशिश की। यहाँ उनके बारे में मेरी राय हैं:

  • BlockEngine समाधान:

    • इसके लिए विकल्पों पर विचार करते हुए बहुत अधिक कोड की आवश्यकता होती है।
    • मुझे यह बहुत आसान लगा कि अगर मैं एक ऑफसेट गलत था, तो दूसरे के साथ एक ब्लॉक को ओवरराइट कर सकता हूं।
    • मैंने मूल रूप से कहा है कि प्रारूपण को ब्लॉक स्तर पर संलग्न किया जा सकता है। मैंने पाया कि यह ब्लॉक सामग्री से अलग स्वरूपण करने से ज्यादा बेहतर नहीं है। मैं सामग्री और स्वरूपण को मिलाने का अच्छा तरीका नहीं सोच सकता। न ही मैं उन्हें अलग रखने का अच्छा तरीका खोज सकता हूं। यह सिर्फ एक गड़बड़ है।
  • XML स्प्रेडशीट समाधान:

    • मैं अभी के लिए इस समाधान के साथ जा रहा हूँ।
    • यह दोहराता है कि इस समाधान को बहुत कम कोड की आवश्यकता है। मैं ब्लॉक एक्वाइन को एक्सेल के साथ प्रभावी रूप से प्रतिस्थापित कर रहा हूं। मुझे अभी भी बुकमार्क और पेज ब्रेक जैसी सुविधाओं के लिए हैक की आवश्यकता है।
    • एक्सएमएल स्प्रेडशीट का प्रारूप बारीक है, लेकिन एक छोटा सा बदलाव करना और अपने पसंदीदा डिफ प्रोग्राम में मौजूदा फाइल के परिणामों की तुलना करना आसान है। और एक बार जब आप कुछ idiosyncrasy का पता लगाते हैं, तो आप इसे जगह में रख सकते हैं और वहां से इसके बारे में भूल सकते हैं।
    • मैं अभी भी चिंतित हूं कि यह समाधान पुराने Excel फ़ाइल प्रारूप पर निर्भर करता है।
    • मेरे द्वारा बनाई गई XSLT फ़ाइल के साथ काम करना आसान है। ब्लॉकचेन समाधान के साथ प्रारूपण से निपटना यहां बहुत सरल है।

जवाबों:


7

यदि आप वास्तव में कुछ चाहते हैं जो आपके लिए अच्छी तरह से काम करता है, तो मेरा सुझाव है कि आपको "अनावश्यक रूप से जटिल" के विचार की आदत हो ... यह माइक्रोसॉफ्ट ऑफिस फ़ाइल स्वरूपों से निपटने की प्रकृति है।

"ब्लॉक" के आपके विचार की तरह मैं (सॉर्ट) ... मैं कोशिकाओं की धारणा से स्वतंत्र कॉलम और पंक्तियों के साथ तालिका की तरह उप-वर्गीकृत ब्लॉक ऑब्जेक्ट बनाऊंगा। फिर इन्हें XSLS फ़ाइलों में बदलने के लिए अपने ब्लॉक इंजन का उपयोग करें।

मैंने अतीत में सफलतापूर्वक OpenXML SDK का उपयोग किया है , लेकिन दस्तावेज़ीकरण को पढ़ने और खरोंच से शुरू करने की कोशिश न करें। इसके बजाय, आप जो चाहते हैं उसके एक्सेल में एक सटीक प्रतिलिपि बनाएं, इसे सहेजें, और दिए गए दस्तावेज़ परावर्तक उपकरण का उपयोग करके निरीक्षण करें। यह आपको दस्तावेज़ बनाने के लिए आवश्यक सी # कोड देगा, जिसे आप तब से सीख सकते हैं और संशोधित कर सकते हैं।


Office दस्तावेज़ों हैं नहीं "अनावश्यक रूप से जटिल" - वे क्या कर रहे हैं या संचालन का एक विशाल रेंज की अनुमति देता है, स्वरूपण, कार्यक्षमता, आदि
वॉरेन

5
मैं यह तर्क नहीं दे रहा हूं कि फ़ाइल प्रारूप खुद ही अनावश्यक रूप से जटिल हैं जितना कि मैं तर्क दे रहा हूं कि उनके साथ काम करना है। उदाहरण के लिए, OpenXML SDK का उपयोग करने के लिए, आपको आवश्यक है कि आप उस मैजिक ऑर्डर को जानें जिसमें तत्वों को जोड़ना है ... उदाहरण के लिए स्लाइड लेआउट को जोड़ना, उदाहरण के लिए, काम नहीं करता है। आपको इसे पहले स्लाइड में जोड़ना होगा, और फिर प्रस्तुति में। क्यों? क्योंकि Microsoft ने पुस्तकालयों को इस तरह कोडित किया था। प्रबंधन करने के लिए बहुत सारे अजीब परिपत्र संदर्भ हैं। मैं समझता हूं कि प्रारूप को जटिलता की आवश्यकता है, लेकिन इसके साथ काम करना इतना दर्दनाक नहीं होना चाहिए।
mgw854

3

यहाँ एक समाधान है जो मैंने अतीत में अक्सर इस्तेमाल किया है:

  • टेम्पलेट के रूप में एक नियमित रूप से एक्सेल डॉक्यूमेंट (आमतौर पर xlsx फॉर्मेट में) बनाते हैं, जिसमें सभी कॉलम हेडर होते हैं, जिसमें उनका शीर्षक और कॉलम के लिए एक डिफ़ॉल्ट स्वरूपण और शायद शीर्षक कोशिकाओं के लिए प्रारूपण शामिल होता है।

  • उस टेम्पलेट को अपने प्रोग्राम के संसाधनों में एम्बेड करें। रनटाइम पर, पहला कदम टेम्पलेट को एक नई फ़ाइल के रूप में निकालना और इसे गंतव्य फ़ोल्डर में रखना है

  • नए बनाए गए xlsx में डेटा भरने के लिए इंटरॉप या थर्ड पार्टी लाइब्रेरी का उपयोग करें। हार्डकोड किए गए कॉलम नंबरों का संदर्भ न लें, इसके बजाय सही कॉलम की पहचान करने के लिए कुछ मेटाडेटा (उदाहरण के लिए कॉलम हेडर) का उपयोग करें।

पेशेवरों:

  • आपके ब्लॉक दृष्टिकोण की तरह कुछ अब बेहतर काम करता है। उदाहरण के लिए, कॉलम स्वैपिंग: आपके ब्लॉक कोड में कुछ भी बदलने की आवश्यकता नहीं है, क्योंकि सही कॉलम उनके हेडर द्वारा पहचाने जाते हैं

  • जब तक आपके कॉलम में एक अद्वितीय स्वरूपण होता है, तब तक अधिकांश स्वरूपण आपके टेम्पलेट में हेरफेर करके सीधे एक्सेल में किया जा सकता है। यह आपको WYSIWYG का एहसास दिलाता है, साथ में एक्सेल में उपलब्ध किसी भी स्वरूपण विकल्प का उपयोग करने की स्वतंत्रता के साथ-साथ उसके लिए कोड लिखने की आवश्यकता के बिना।

विपक्ष:

  • आपको अभी भी किसी तीसरे पक्ष के परिवाद या इंटरोप का उपयोग करने की आवश्यकता है। क्या मैंने उल्लेख किया है कि इंटरोप धीमा है?

  • जब कॉलम हेडर आपके टेम्प्लेट में बदल जाते हैं, तो आपको अपने कोड को भी अनुकूलित करने की आवश्यकता होती है (लेकिन एक मान्यता रूटीन होने से आसानी से पता लगाया जा सकता है जो संकेत देते हैं कि अपेक्षित कॉलम गायब हैं)

  • जब आपको एक ही कॉलम में विभिन्न कोशिकाओं के डायनामिक स्वरूपण की आवश्यकता होती है, तब भी आपको उस कोड से निपटना होगा

एक सामान्य संकेत के रूप में, आप जो भी दृष्टिकोण चुनते हैं: इसमें सामग्री से लेआउट को अलग करने और घोषणात्मक समाधान का उपयोग करने के फायदे हैं।


0

विचार करने के लिए दो चीजें हैं:

  • किसी दिए गए प्रारूप में एक फ़ाइल बनाने की जटिलता
  • फ़ाइल की सामग्री की संरचना को बदलने के लिए कोड की टूटने की संवेदनशीलता।

पहले के बारे में:

यदि आपके द्वारा बनाई जाने वाली स्प्रैडशीट में कोई स्वरूपण या सूत्र नहीं हैं , तो आप वास्तविक XLSX के बजाय CSV या Tab-Delimited फ़ाइल बनाने के लिए बहुत सीधे हैं। एक्सेल इन फ़ाइलों को खोलता है, अक्सर कई पीसी पर डिफ़ॉल्ट रूप से। यह आपको कॉलम और पंक्तियों के आसपास हार्ड कोडिंग में मदद नहीं करेगा, लेकिन यह आपको एक्सेल ऑब्जेक्ट मॉडल में हेरफेर करने के अतिरिक्त काम से बचाएगा।

यदि आपको फ़ॉर्मेटिंग या फ़ार्मुलों की आवश्यकता है, तो एक्सेल ऑब्जेक्ट मॉडल के साथ काम करना एक उचित तरीका है, खासकर यदि आप एक स्प्रेडशीट का निर्माण करते हैं जो स्वयं "हार्ड-कोडेड" नहीं है। दूसरे शब्दों में, यदि आपकी स्प्रेडशीट सापेक्ष सूत्रों का उपयोग करती है और नामों को उचित रूप से उपयोग करती है तो यह मैजिक नंबरों की कम हार्ड कोडिंग के साथ मिल सकती है।

दूसरे के बारे में:

आप हार्ड-कोडित पंक्ति और स्तंभ संदर्भों के साथ सेल द्वारा सेल के माध्यम से काम कर सकते हैं, या आप forकोशिकाओं की आबादी को सामान्य बनाने के लिए सरणियों / सूची संग्रह और छोरों के साथ काम कर सकते हैं।


मैं अपने मूल प्रश्न में स्पष्ट नहीं था कि मैं प्रारूपण और मुद्रण के विकल्प और इस तरह के समाधान को नियंत्रित करना चाहता हूं। दूसरे बिंदु के बारे में, मुझे लगता है कि आप जिस बात का जिक्र कर रहे हैं, वह वही है जिसका मैंने अपने BlockEngineसमाधान में वर्णन किया है। मैं एक IList<IBusinessObject>और एक Blockवस्तु बाहर थूक सकता है । पेशेवरों और विपक्ष अभी भी एक ही होगा।
user2023861
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.