2011-05-13 11 views
11

मेरे पास एक स्प्रेडशीट है जिसे मैं पीओआई (मेरे पास xls और xlsx प्रारूप दोनों) के साथ पढ़ने की कोशिश कर रहा हूं, लेकिन इस मामले में, समस्या xls फ़ाइल के साथ है। मेरी स्प्रेडशीट में लगभग 10,000 पंक्तियां और 75 कॉलम हैं, और इसे पढ़ने में कई मिनट लग सकते हैं (हालांकि एक्सेल कुछ सेकंड में खुलता है)। मैं पूरी फाइल को स्मृति में पढ़ने के बजाय ईवेंट आधारित पढ़ने का उपयोग कर रहा हूं। मेरे कोड का मांस नीचे है। यह अभी थोड़ा गन्दा है, लेकिन यह वास्तव में सिर्फ एक लंबा स्विच स्टेटमेंट है जिसे ज्यादातर पीओआई उदाहरणों से कॉपी किया गया था।बड़े स्प्रेडशीट्स के लिए अपाचे पीओआई जावा एक्सेल प्रदर्शन

क्या यह घटना मॉडल का उपयोग करके पीओआई प्रदर्शन के लिए सामान्य है? क्या ऐसा कुछ है जो मैं इसे तेज करने के लिए करता हूं? मुझे लगता है कि मेरे आवेदन के लिए कई मिनट अस्वीकार्य होंगे।

POIFSFileSystem poifs = new POIFSFileSystem(fis); 
    InputStream din = poifs.createDocumentInputStream("Workbook"); 
    try 
    { 
     HSSFRequest req = new HSSFRequest(); 
     listener = new FormatTrackingHSSFListener(new HSSFListener() { 
      @Override 
      public void processRecord(Record rec) 
      { 
       thisString = null; 
       int sid = rec.getSid(); 
       switch (sid) 
       { 
        case SSTRecord.sid: 
         strTable = (SSTRecord) rec; 
         break; 
        case LabelSSTRecord.sid: 
         LabelSSTRecord labelSstRec = (LabelSSTRecord) rec; 
         thisString = strTable.getString(labelSstRec 
           .getSSTIndex()).getString(); 
         row = labelSstRec.getRow(); 
         col = labelSstRec.getColumn(); 
         break; 
        case RKRecord.sid: 
         RKRecord rrk = (RKRecord) rec; 
         thisString = ""; 
         row = rrk.getRow(); 
         col = rrk.getColumn(); 
         break; 
        case LabelRecord.sid: 
         LabelRecord lrec = (LabelRecord) rec; 
         thisString = lrec.getValue(); 
         row = lrec.getRow(); 
         col = lrec.getColumn(); 
         break; 
        case BlankRecord.sid: 
         BlankRecord blrec = (BlankRecord) rec; 
         thisString = ""; 
         row = blrec.getRow(); 
         col = blrec.getColumn(); 
         break; 
        case BoolErrRecord.sid: 
         BoolErrRecord berec = (BoolErrRecord) rec; 
         row = berec.getRow(); 
         col = berec.getColumn(); 
         byte errVal = berec.getErrorValue(); 
         thisString = errVal == 0 ? Boolean.toString(berec 
           .getBooleanValue()) : ErrorConstants 
           .getText(errVal); 
         break; 
        case FormulaRecord.sid: 
         FormulaRecord frec = (FormulaRecord) rec; 
         switch (frec.getCachedResultType()) 
         { 
          case Cell.CELL_TYPE_NUMERIC: 
           double num = frec.getValue(); 
           if (Double.isNaN(num)) 
           { 
            // Formula result is a string 
            // This is stored in the next record 
            outputNextStringRecord = true; 
           } 
           else 
           { 
            thisString = formatNumericValue(frec, num); 
           } 
           break; 
          case Cell.CELL_TYPE_BOOLEAN: 
           thisString = Boolean.toString(frec 
             .getCachedBooleanValue()); 
           break; 
          case Cell.CELL_TYPE_ERROR: 
           thisString = HSSFErrorConstants 
             .getText(frec.getCachedErrorValue()); 
           break; 
          case Cell.CELL_TYPE_STRING: 
           outputNextStringRecord = true; 
           break; 
         } 
         row = frec.getRow(); 
         col = frec.getColumn(); 
         break; 
        case StringRecord.sid: 
         if (outputNextStringRecord) 
         { 
          // String for formula 
          StringRecord srec = (StringRecord) rec; 
          thisString = srec.getString(); 
          outputNextStringRecord = false; 
         } 
         break; 
        case NumberRecord.sid: 
         NumberRecord numRec = (NumberRecord) rec; 
         row = numRec.getRow(); 
         col = numRec.getColumn(); 
         thisString = formatNumericValue(numRec, numRec 
           .getValue()); 
         break; 
        case NoteRecord.sid: 
         NoteRecord noteRec = (NoteRecord) rec; 
         row = noteRec.getRow(); 
         col = noteRec.getColumn(); 
         thisString = ""; 
         break; 
        case EOFRecord.sid: 
         inSheet = false; 
       } 
       if (thisString != null) 
       { 
        // do something with the cell value 
       } 
      } 
     }); 
     req.addListenerForAllRecords(listener); 
     HSSFEventFactory factory = new HSSFEventFactory(); 
     factory.processEvents(req, din); 
+0

क्या यह xls है जो धीमा और xlsx है जो ठीक काम करता है? मेरे लिए यह विपरीत है, कई पंक्तियों वाली फाइल लिखना सिर्फ xls के लिए कुछ मेगाबाइट्स ढेर का उपयोग करता है, लेकिन 2 जीबी xlsx के लिए पर्याप्त नहीं था। यदि एक्स एक्स पंक्तियों से अधिक है तो मुझे xls पर फ़ॉलबैक करने की आवश्यकता है – rlovtang

+0

@rlovtang, xlsx भी धीमा है। मेरा मतलब था कि मैं जेईएक्ससेल जैसे कुछ की बजाय पीओआई का उपयोग कर रहा हूं क्योंकि मुझे एक्सएलएस और एक्सएलएसएक्स दोनों से निपटने की ज़रूरत है। –

उत्तर

6

मैंने हजारों बड़ी एक्सेल फाइलों के साथ कुछ प्रसंस्करण भी किया और मेरी राय में पीओआई बहुत तेज है। एक्सेल फाइलों को लोड करना एक्सेल में लगभग 1 मिनट भी लेता है। तो मैं पुष्टि करता हूं कि समस्या पीओआई कोड

+0

मेरा जवाब देखें, आप सही हैं। –

1

मैंने कुछ और विस्तृत प्रोफाइलिंग किया और ऐसा लगता है कि समस्या वास्तव में पीओआई के बाहर कोड में है। मैंने अभी माना कि यह बाधा थी, लेकिन मेरा मानना ​​है कि यह गलत है।

+2

क्या आप कोड कहां से अधिक जानकारी प्रदान कर सकते हैं? क्या यह आपका स्वयं का कोड था, या तृतीय पक्ष जार था? – davo

+1

यह मेरा खुद का कोड था। मैं गलती से टेक्स्ट फ़ील्ड के कुछ बहुत अक्षम अक्षम करने की कोशिश कर रहा था यह देखने के लिए कि उनके पास दिनांक मूल्य हैं (जब उपयोगकर्ता ने उन कक्षों में टेक्स्ट तिथियां दर्ज कीं जिनके पास दिनांक प्रारूप नहीं था)। –

2

से बाहर है, मैं स्ट्रीमिंग एचएसएसएफ का उपयोग करने की कोशिश करता हूं, साथ ही साथ poi-beta3 में पेश किया जाता है। इसने 1000+ कॉलम के साथ बड़ी स्प्रेडशीट पर स्मृति समस्याओं को मदद की।

1

यदि आप बड़ी एक्सेल फ़ाइल उत्पन्न करने के लिए अपाचे पीओआई का उपयोग कर रहे हैं, तो कृपया शीट नोट करें .autoSizeColumn ((लघु) पी); लाइन क्योंकि यह प्रदर्शन को प्रभावित करेगा।

http://stanicblog.blogspot.sg/2013/07/generate-large-excel-report-by-using.html

+1

यह सच नहीं हो सकता है क्योंकि आलेख में autoSizeColumn को लूप में बुलाया जाता है क्योंकि प्रत्येक पंक्ति को जोड़ा जा रहा है, और सभी पंक्तियों को एक बार लूप के बाद नहीं किया जाता है। – Somu

11

आप च Apache POI का उपयोग कर रहे बड़े उत्कृष्टता फ़ाइल उत्पन्न करने के लिए, कृपया निम्न पंक्ति ध्यान दें:

sheet.autoSizeColumn((short) p);

क्योंकि इस प्रदर्शन में कमी होगी।

+2

_How_ क्या यह प्रदर्शन को प्रभावित करेगा? क्या इससे मदद मिलेगी या इससे बाधा आएगी? –

+1

यह वास्तव में मेरी मदद करता है, मैं एक साधारण 3000 लाइन आउटपुट चला रहा था जो 10 मिनट से 2 सेकंड (शाब्दिक) ले रहा था। आप इस मुद्दे को नोटिस करेंगे क्योंकि आपका कोड लिखने पर धीमा हो जाता है। धन्यवाद @ सैम्स – Dennis

संबंधित मुद्दे