2012-10-09 2 views
1

OLEDB를 사용하면 Excel 시트에서 3200 행을 읽는 데 2-3 초 밖에 걸리지 않습니다. OpenXML 형식으로 바뀌었고 Excel 시트에서 3200 행을 읽는 데 1 분 이상 걸립니다.OpenXML은 Excel 시트에서 행을 읽는 데 OLEDB보다 훨씬 오래 걸립니다.

public static DataTable ReadExcelFileDOM(string filename) 
{ 
    DataTable table; 

    using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(filename, true)) 
    { 
     WorkbookPart workbookPart = myDoc.WorkbookPart; 
     Sheet worksheet = workbookPart.Workbook.Descendants<Sheet>().First(); 
     WorksheetPart worksheetPart = 
     (WorksheetPart)(workbookPart.GetPartById(worksheet.Id)); 
     SheetData sheetData = 
      worksheetPart.Worksheet.Elements<SheetData>().First(); 
     List<List<string>> totalRows = new List<List<string>>(); 
     int maxCol = 0; 

     foreach (Row r in sheetData.Elements<Row>()) 
     { 
      // Add the empty row. 
      string value = null; 
      while (totalRows.Count < r.RowIndex - 1) 
      { 
       List<string> emptyRowValues = new List<string>(); 
       for (int i = 0; i < maxCol; i++) 
       { 
        emptyRowValues.Add(""); 
       } 
       totalRows.Add(emptyRowValues); 
      } 


      List<string> tempRowValues = new List<string>(); 
      foreach (Cell c in r.Elements<Cell>()) 
      { 
       #region get the cell value of c. 
       if (c != null) 
       { 
        value = c.InnerText; 

        // If the cell represents a numeric value, you are done. 
        // For dates, this code returns the serialized value that 
        // represents the date. The code handles strings and Booleans 
        // individually. For shared strings, the code looks up the 
        // corresponding value in the shared string table. For Booleans, 
        // the code converts the value into the words TRUE or FALSE. 
        if (c.DataType != null) 
        { 
         switch (c.DataType.Value) 
         { 
          case CellValues.SharedString: 
           // For shared strings, look up the value in the shared 
           // strings table. 
           var stringTable = workbookPart. 
            GetPartsOfType<SharedStringTablePart>().FirstOrDefault(); 

           // If the shared string table is missing, something is 
           // wrong. Return the index that you found in the cell. 
           // Otherwise, look up the correct text in the table. 
           if (stringTable != null) 
           { 
            value = stringTable.SharedStringTable. 
             ElementAt(int.Parse(value)).InnerText; 
           } 
           break; 

          case CellValues.Boolean: 
           switch (value) 
           { 
            case "0": 
             value = "FALSE"; 
             break; 
            default: 
             value = "TRUE"; 
             break; 
           } 
           break; 
         } 
        } 

        Console.Write(value + " "); 
       } 
       #endregion 

       // Add the cell to the row list. 
       int i = Convert.ToInt32(c.CellReference.ToString().ToCharArray().First() - 'A'); 

       // Add the blank cell in the row. 
       while (tempRowValues.Count < i) 
       { 
        tempRowValues.Add(""); 
       } 
       tempRowValues.Add(value); 
      } 

      // add the row to the totalRows. 
      maxCol = processList(tempRowValues, totalRows, maxCol); 

      Console.WriteLine(); 
     } 

     table = ConvertListListStringToDataTable(totalRows, maxCol); 
    } 
    return table; 
} 

/// <summary> 
/// Add each row to the totalRows. 
/// </summary> 
/// <param name="tempRows"></param> 
/// <param name="totalRows"></param> 
/// <param name="MaxCol">the max column number in rows of the totalRows</param> 
/// <returns></returns> 
private static int processList(List<string> tempRows, List<List<string>> totalRows, int MaxCol) 
{ 
    if (tempRows.Count > MaxCol) 
    { 
     MaxCol = tempRows.Count; 
    } 

    totalRows.Add(tempRows); 
    return MaxCol; 
} 

private static DataTable ConvertListListStringToDataTable(List<List<string>> totalRows, int maxCol) 
{ 
    DataTable table = new DataTable(); 
    for (int i = 0; i < maxCol; i++) 
    { 
     table.Columns.Add(); 
    } 
    foreach (List<string> row in totalRows) 
    { 
     while (row.Count < maxCol) 
     { 
      row.Add(""); 
     } 
     table.Rows.Add(row.ToArray()); 
    } 
    return table; 
} 

읽기 프로세스가 조금 더 빨리 할 수 ​​있도록 곳이 코드를 변경하기위한 효율적인 방법이 있나요 : 아래

내 코드? 이 코드를 어떻게 빨리 읽을 수 있도록 변경할 수 있습니까?

+0

누구든지 도와주세요. –

답변

0

SAX 방식을 사용해 보셨습니까? DOM 접근법은 DOM에로드되기 때문에 느리다.

http://blogs.msdn.com/b/brian_jones/archive/2010/05/27/parsing-and-reading-large-excel-files-with-the-open-xml-sdk.aspx

당신은 모든 세포 (예 : 'A1')를 셀 참조가 있는지 있다면, 그럼 그냥 (대신 행 클래스, 다음 자식 셀 클래스를 통해 구문 분석의) 모든 셀 클래스를 통해 구문 분석합니다. 나는 Microsoft Excel이 그렇게 믿습니다. 셀 참조는 Open XML 사양에 따라 선택적 특성입니다.

관련 문제