2012-05-11 5 views
12

का उपयोग करके मुझे स्टैक ओवरव्लो का कुछ ऐसा (मूल रूप से) मूलभूत उपयोग करने से नफरत है, लेकिन मैं पिछले कुछ घंटों से माइक्रोसॉफ्ट के साथ लड़ रहा हूं और ऐसा लगता है कि यह एक मृत अंत है। मैं एक्सेल 2007+ स्प्रेडशीट्स (बड़े) को पढ़ने की कोशिश कर रहा हूं, और Google ने मुझे सूचित किया है कि ओपनएक्सएमएल एसडीके का उपयोग करना एक बहुत लोकप्रिय विकल्प है। तो मैंने चीज़ को एक शॉट दिया, कुछ ट्यूटोरियल पढ़े, माइक्रोसॉफ्ट के अपने पुस्तकालय पृष्ठों की जांच की, और उन सभी में से बहुत कम मिला।OpenXmlReader

मैं संख्याओं के केवल एक कॉलम और तारों में से एक के साथ एक छोटी टेस्ट स्प्रेडशीट का उपयोग कर रहा हूं - बड़े पैमाने पर परीक्षण बाद में आ जाएगा। मैंने पोस्ट किए जाने वाले एक के समान कई कार्यान्वयन की कोशिश की है, और उनमें से कोई भी डेटा पढ़ता नहीं है। नीचे दिया गया कोड ज्यादातर अन्य स्टैक ओवरफ्लो थ्रेड से लिया गया था, जहां ऐसा लगता था - मेरे लिए ऐसा नहीं। मैंने सोचा कि मैं आपके पास इस संस्करण के साथ लोगों की जांच/डीबग/सहायता करूंगा, क्योंकि आज जो कुछ भी मैंने लिखा है उससे कम टूटा होगा।

static void ReadExcelFileSAX(string fileName) 
    { 
     using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, true)) 
     { 
      WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; 
      WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); 

      OpenXmlPartReader reader = new OpenXmlPartReader(worksheetPart); 
      string text; 
      string rowNum; 
      while (reader.Read()) 
      { 
       if (reader.ElementType == typeof(Row)) 
       { 
        do 
        { 
         if (reader.HasAttributes) 
         { 
          rowNum = reader.Attributes.First(a => a.LocalName == "r").Value; 
          Console.Write("rowNum: " + rowNum); //we never even get here, I tested it with a breakpoint 
         } 

        } while (reader.ReadNextSibling()); // Skip to the next row 
        Console.ReadKey(); 
        break; // We just looped through all the rows so no need to continue reading the worksheet 
       } 
       if (reader.ElementType == typeof(Cell)) 
       { 

       } 

       if (reader.ElementType != typeof(Worksheet)) // Dont' want to skip the contents of the worksheet 
        reader.Skip(); // Skip contents of any node before finding the first row. 
      } 
      reader.Close(); 
      Console.WriteLine(); 
      Console.ReadKey(); 
     } 
    } 

और, एक तरफ ध्यान दें पर, OpenXML SDK मैं किसी भी तरह चूक गए उपयोग करने के लिए किसी भी अच्छे विकल्प हैं?

+0

यहां उपलब्ध ओपन एक्सएमएल एसडीके 2.0 उत्पादकता उपकरण का उपयोग करने का प्रयास करें: http://www.microsoft.com/en-us/download/details.aspx?id=5124। यह आपको किसी भी * xlsx * को खोलने और इसकी संरचना को देखने या सी # कोड देखने की अनुमति देता है जो फ़ाइल को फिर से बना सकता है। इस तरह आप देख सकते हैं कि आप जिस फाइल के साथ काम कर रहे हैं उसमें आप कहां पहुंचना चाहते हैं। –

उत्तर

18

मुझे लगता है कि आपने पंक्तियों को पढ़ने के लिए गलत WorksheetPart लिया है।

लाइन

workbookPart.WorksheetParts.First(); 

संग्रह जो जरूरी पहले कार्यपत्रक नहीं होना चाहिए के रूप में आप यह Microsoft Excel में देखने के पहले WorksheetPart हो जाता है।

तो, सभी WorksheetParts के माध्यम से पुनरावृत्त करें और आपको अपने कंसोल विंडो पर कुछ आउटपुट देखना चाहिए।

static void ReadExcelFileSAX(string fileName) 
{ 
    using (SpreadsheetDocument spreadsheetDocument = 
            SpreadsheetDocument.Open(fileName, true)) 
    { 
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; 

    // Iterate through all WorksheetParts 
    foreach (WorksheetPart worksheetPart in workbookPart.WorksheetParts) 
    {   
     OpenXmlPartReader reader = new OpenXmlPartReader(worksheetPart); 
     string text; 
     string rowNum; 
     while (reader.Read()) 
     { 
     if (reader.ElementType == typeof(Row)) 
     { 
      do 
      { 
      if (reader.HasAttributes) 
      { 
       rowNum = reader.Attributes.First(a => a.LocalName == "r").Value; 
       Console.Write("rowNum: " + rowNum); 
      } 

      } while (reader.ReadNextSibling()); // Skip to the next row 

      break; // We just looped through all the rows so no 
       // need to continue reading the worksheet 
     } 

     if (reader.ElementType != typeof(Worksheet)) 
      reader.Skip(); 
     } 
     reader.Close();  
    } 
    } 
} 

सभी सेल मान निम्न फ़ंक्शन का उपयोग करें पढ़ने के लिए (सभी त्रुटि हैंडलिंग विवरण छोड़े गए):

static void ReadAllCellValues(string fileName) 
{ 
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false)) 
    { 
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; 

    foreach(WorksheetPart worksheetPart in workbookPart.WorksheetParts) 
    { 
     OpenXmlReader reader = OpenXmlReader.Create(worksheetPart); 

     while (reader.Read()) 
     { 
     if (reader.ElementType == typeof(Row)) 
     { 
      reader.ReadFirstChild(); 

      do 
      { 
      if (reader.ElementType == typeof(Cell)) 
      { 
       Cell c = (Cell)reader.LoadCurrentElement(); 

       string cellValue; 

       if (c.DataType != null && c.DataType == CellValues.SharedString) 
       { 
       SharedStringItem ssi = workbookPart.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(int.Parse(c.CellValue.InnerText)); 

       cellValue = ssi.Text.Text; 
       } 
       else 
       { 
       cellValue = c.CellValue.InnerText; 
       } 

       Console.Out.Write("{0}: {1} ", c.CellReference, cellValue); 
      } 
      } while (reader.ReadNextSibling()); 
      Console.Out.WriteLine(); 
     }    
     } 
    } 
    } 
} 

कोड में ऊपर आप देखते हैं कि SharedString नियंत्रित किया जाना चाहिए डेटा प्रकार के साथ कोशिकाओं SharedStringTablePart का उपयोग कर ।

+0

अच्छा, यह काम किया - तरह का। यह पता चला है कि वर्कशीट को किसी कारण से पीछे की ओर समझाया गया है (इसलिए मेरी तीन चादरों में से पहला वास्तव में सूचकांक 3 है)। अगली समस्या> मैं यह नहीं समझ सकता कि पंक्ति को कैप्चर करने और इसकी सामग्री का निरीक्षण कैसे करें।यह आसान हो सकता है, लेकिन मैं अब 7+ घंटे के लिए रहा हूं और मेरा दिमाग मर रहा है ... – Argent

+1

@Aggent: एक्सेल फ़ाइल में शामिल वर्कशीट्स से सभी सेल मानों को पढ़ने वाले फ़ंक्शन के साथ मेरा उत्तर अपडेट किया गया। – Hans

+0

धन्यवाद! यह मेरे जैसा ही था, लेकिन आपका संस्करण कम गन्दा दिखता है। मैं थोड़ी देर के लिए इसके साथ खेलूँगा, और यदि आपके कोई और प्रश्न हैं तो मैं आपको परेशान कर दूंगा। और जब हम इसमें हैं, तो क्या आपने OpenXML का उपयोग करने के तरीके पर कोई सभ्य ट्यूटोरियल/गाइड देखा है? जैसा कि मैं जाता हूं, मैं इसे समझने की तरह हूं, और यह ... काउंटर-उत्पादक हो सकता है। – Argent

0

खाली कोशिकाओं को पढ़ने के लिए, मैं पंक्ति पाठक के बाहर आवंटित एक चर का उपयोग कर रहा हूं और लूप के दौरान, मैं जांच कर रहा हूं कि कॉलम अनुक्रमणिका मेरे चर से अधिक है या नहीं, क्योंकि प्रत्येक सेल पढ़ने के बाद इसे बढ़ाया जा रहा है। यदि यह मेल नहीं खाता है, तो मैं अपने कॉलम को उस मूल्य के साथ भर रहा हूं जिसे मैं चाहता हूं। यह वह चाल है जिसका उपयोग मैं अपने सम्मानित कॉलम मान में खाली कोशिकाओं को पकड़ने के लिए करता था। यहाँ कोड है: इस कोड को पढ़ता खाली कोशिकाओं 2. पूरा पढ़ने के बाद खाली पंक्तियों को छोड़ 1.:

public static DataTable ReadIntoDatatableFromExcel(string newFilePath) 
     { 
      /*Creating a table with 20 columns*/ 
      var dt = CreateProviderRvenueSharingTable(); 

      try 
      { 
       /*using stream so that if excel file is in another process then it can read without error*/ 
       using (Stream stream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
       { 
        using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(stream, false)) 
        { 
         var workbookPart = spreadsheetDocument.WorkbookPart; 
         var workbook = workbookPart.Workbook; 

         /*get only unhide tabs*/ 
         var sheets = workbook.Descendants<Sheet>().Where(e => e.State == null); 

         foreach (var sheet in sheets) 
         { 
          var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id); 

          /*Remove empty sheets*/ 
          List<Row> rows = worksheetPart.Worksheet.Elements<SheetData>().First().Elements<Row>() 
           .Where(r => r.InnerText != string.Empty).ToList(); 

          if (rows.Count > 1) 
          { 
           OpenXmlReader reader = OpenXmlReader.Create(worksheetPart); 

           int i = 0; 
           int BTR = 0;/*Break the reader while empty rows are found*/ 

           while (reader.Read()) 
           { 
            if (reader.ElementType == typeof(Row)) 
            { 
             /*ignoring first row with headers and check if data is there after header*/ 
             if (i < 2) 
             { 
              i++; 
              continue; 
             } 

             reader.ReadFirstChild(); 

             DataRow row = dt.NewRow(); 

             int CN = 0; 

             if (reader.ElementType == typeof(Cell)) 
             { 
              do 
              { 
               Cell c = (Cell)reader.LoadCurrentElement(); 

               /*reader skipping blank cells so data is getting worng in datatable's rows according to header*/ 
               if (CN != 0) 
               { 
                int cellColumnIndex = 
                 ExcelHelper.GetColumnIndexFromName(
                  ExcelHelper.GetColumnName(c.CellReference)); 

                if (cellColumnIndex < 20 && CN < cellColumnIndex - 1) 
                { 
                 do 
                 { 
                  row[CN] = string.Empty; 
                  CN++; 
                 } while (CN < cellColumnIndex - 1); 
                } 
               } 

               /*stopping execution if first cell does not have any value which means empty row*/ 
               if (CN == 0 && c.DataType == null && c.CellValue == null) 
               { 
                BTR++; 
                break; 
               } 

               string cellValue = GetCellValue(c, workbookPart); 
               row[CN] = cellValue; 
               CN++; 

               /*if any text exists after T column (index 20) then skip the reader*/ 
               if (CN == 20) 
               { 
                break; 
               } 
              } while (reader.ReadNextSibling()); 
             } 

             /*reader skipping blank cells so fill the array upto 19 index*/ 
             while (CN != 0 && CN < 20) 
             { 
              row[CN] = string.Empty; 
              CN++; 
             } 

             if (CN == 20) 
             { 
              dt.Rows.Add(row); 
             } 
            } 
            /*escaping empty rows below data filled rows after checking 5 times */ 
            if (BTR > 5) 
             break; 
           } 
           reader.Close(); 
          }        
         } 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
      return dt; 
     } 

    private static string GetCellValue(Cell c, WorkbookPart workbookPart) 
     { 
      string cellValue = string.Empty; 
      if (c.DataType != null && c.DataType == CellValues.SharedString) 
      { 
       SharedStringItem ssi = 
        workbookPart.SharedStringTablePart.SharedStringTable 
         .Elements<SharedStringItem>() 
         .ElementAt(int.Parse(c.CellValue.InnerText)); 
       if (ssi.Text != null) 
       { 
        cellValue = ssi.Text.Text; 
       } 
      } 
      else 
      { 
       if (c.CellValue != null) 
       { 
        cellValue = c.CellValue.InnerText; 
       } 
      } 
      return cellValue; 
     } 

public static int GetColumnIndexFromName(string columnNameOrCellReference) 
     { 
      int columnIndex = 0; 
      int factor = 1; 
      for (int pos = columnNameOrCellReference.Length - 1; pos >= 0; pos--) // R to L 
      { 
       if (Char.IsLetter(columnNameOrCellReference[pos])) // for letters (columnName) 
       { 
        columnIndex += factor * ((columnNameOrCellReference[pos] - 'A') + 1); 
        factor *= 26; 
       } 
      } 
      return columnIndex; 
     } 

     public static string GetColumnName(string cellReference) 
     { 
      /* Advance from L to R until a number, then return 0 through previous position*/ 
      for (int lastCharPos = 0; lastCharPos <= 3; lastCharPos++) 
       if (Char.IsNumber(cellReference[lastCharPos])) 
        return cellReference.Substring(0, lastCharPos); 

      throw new ArgumentOutOfRangeException("cellReference"); 
     } 

कोड के लिए काम करता है। 3. आरोही क्रम में पहले से शीट को पढ़ें 4. यदि एक्सेल फ़ाइल किसी अन्य प्रक्रिया से हो रही है, तो OpenXML अभी भी इसे पढ़ता है।

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

  • कोई संबंधित समस्या नहीं^_^