OpenXML richiede molto più tempo di OLEDB per leggere le righe dal foglio Excel

Quando ho usato OLEDB, ci vogliono solo 2-3 secondi per leggere 3200 righe da un foglio Excel. Ho cambiato il formato OpenXML e ora ci vuole più di 1 minuto per leggere 3200 righe da un foglio Excel.

Di seguito è riportato il mio codice:

public static DataTable ReadExcelFileDOM(string filename) { DataTable table; using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(filename, true)) { WorkbookPart workbookPart = myDoc.WorkbookPart; Sheet worksheet = workbookPart.Workbook.Descendants().First(); WorksheetPart worksheetPart = (WorksheetPart)(workbookPart.GetPartById(worksheet.Id)); SheetData sheetData = worksheetPart.Worksheet.Elements().First(); List<List> totalRows = new List<List>(); int maxCol = 0; foreach (Row r in sheetData.Elements()) { // Add the empty row. string value = null; while (totalRows.Count < r.RowIndex - 1) { List emptyRowValues = new List(); for (int i = 0; i < maxCol; i++) { emptyRowValues.Add(""); } totalRows.Add(emptyRowValues); } List tempRowValues = new List(); foreach (Cell c in r.Elements()) { #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().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; } ///  /// Add each row to the totalRows. ///  ///  ///  /// the max column number in rows of the totalRows ///  private static int processList(List tempRows, List<List> totalRows, int MaxCol) { if (tempRows.Count > MaxCol) { MaxCol = tempRows.Count; } totalRows.Add(tempRows); return MaxCol; } private static DataTable ConvertListListStringToDataTable(List<List> totalRows, int maxCol) { DataTable table = new DataTable(); for (int i = 0; i < maxCol; i++) { table.Columns.Add(); } foreach (List row in totalRows) { while (row.Count < maxCol) { row.Add(""); } table.Rows.Add(row.ToArray()); } return table; } 

C’è un modo efficace per cambiare questo codice da qualche parte in modo che il processo di lettura possa essere un po ‘più veloce? Come posso cambiare questo codice per leggere più velocemente?

Hai provato l’approccio SAX? L’approccio DOM è più lento perché carica nel, bene, DOM.

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

Se sei sicuro che ogni cella abbia un riferimento di cella (come “A1”), quindi analizza tutte le classi di celle (invece di analizzare le classi di riga, quindi le classi di celle figlio). Credo che Microsoft Excel lo faccia. Il riferimento di cella è un attributo opzionale in base alle specifiche Open XML.