visual studio net mostrar leer importar form datos data cargar archivo c# .net excel office-interop

studio - leer archivo excel c# windows form



Importación de Excel en una DataTable rápidamente (5)

Intento leer un archivo de Excel en una lista de Data.DataTable, aunque con mi método actual puede llevar mucho tiempo. En esencia, voy hoja de cálculo por hoja de trabajo, celda por celda, y tiende a tomar mucho tiempo. ¿Hay una manera más rápida de hacer esto? Aquí está mi código:

List<DataTable> List = new List<DataTable>(); // Counting sheets for (int count = 1; count < WB.Worksheets.Count; ++count) { // Create a new DataTable for every Worksheet DATA.DataTable DT = new DataTable(); WS = (EXCEL.Worksheet)WB.Worksheets.get_Item(count); textBox1.Text = count.ToString(); // Get range of the worksheet Range = WS.UsedRange; // Create new Column in DataTable for (cCnt = 1; cCnt <= Range.Columns.Count; cCnt++) { textBox3.Text = cCnt.ToString(); Column = new DataColumn(); Column.DataType = System.Type.GetType("System.String"); Column.ColumnName = cCnt.ToString(); DT.Columns.Add(Column); // Create row for Data Table for (rCnt = 0; rCnt <= Range.Rows.Count; rCnt++) { textBox2.Text = rCnt.ToString(); try { cellVal = (string)(Range.Cells[rCnt, cCnt] as EXCEL.Range).Value2; } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { ConvertVal = (double)(Range.Cells[rCnt, cCnt] as EXCEL.Range).Value2; cellVal = ConvertVal.ToString(); } // Add to the DataTable if (cCnt == 1) { Row = DT.NewRow(); Row[cCnt.ToString()] = cellVal; DT.Rows.Add(Row); } else { Row = DT.Rows[rCnt]; Row[cCnt.ToString()] = cellVal; } } } // Add DT to the list. Then go to the next sheet in the Excel Workbook List.Add(DT); }


Caling .Value2 es una operación costosa porque es una llamada COM-interop. En su lugar, leería todo el rango en una matriz y luego recorrería la matriz:

object[,] data = Range.Value2; // Create new Column in DataTable for (int cCnt = 1; cCnt <= Range.Columns.Count; cCnt++) { textBox3.Text = cCnt.ToString(); var Column = new DataColumn(); Column.DataType = System.Type.GetType("System.String"); Column.ColumnName = cCnt.ToString(); DT.Columns.Add(Column); // Create row for Data Table for (int rCnt = 0; rCnt <= Range.Rows.Count; rCnt++) { textBox2.Text = rCnt.ToString(); string CellVal = String.Empty; try { cellVal = (string)(data[rCnt, cCnt]); } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { ConvertVal = (double)(data[rCnt, cCnt]); cellVal = ConvertVal.ToString(); } DataRow Row; // Add to the DataTable if (cCnt == 1) { Row = DT.NewRow(); Row[cCnt.ToString()] = cellVal; DT.Rows.Add(Row); } else { Row = DT.Rows[rCnt]; Row[cCnt.ToString()] = cellVal; } } }


En caso de que alguien más esté usando EPPlus. Esta implementación es bastante ingenua, pero hay comentarios que llaman la atención sobre esto. Si fuera a GetWorkbookAsDataSet() capas a un método más GetWorkbookAsDataSet() en la parte superior, haría lo que el OP está pidiendo.

/// <summary> /// Assumption: Worksheet is in table format with no weird padding or blank column headers. /// /// Assertion: Duplicate column names will be aliased by appending a sequence number (eg. Column, Column1, Column2) /// </summary> /// <param name="worksheet"></param> /// <returns></returns> public static DataTable GetWorksheetAsDataTable(ExcelWorksheet worksheet) { var dt = new DataTable(worksheet.Name); dt.Columns.AddRange(GetDataColumns(worksheet).ToArray()); var headerOffset = 1; //have to skip header row var width = dt.Columns.Count; var depth = GetTableDepth(worksheet, headerOffset); for (var i = 1; i <= depth; i++) { var row = dt.NewRow(); for (var j = 1; j <= width; j++) { var currentValue = worksheet.Cells[i + headerOffset, j].Value; //have to decrement b/c excel is 1 based and datatable is 0 based. row[j - 1] = currentValue == null ? null : currentValue.ToString(); } dt.Rows.Add(row); } return dt; } /// <summary> /// Assumption: There are no null or empty cells in the first column /// </summary> /// <param name="worksheet"></param> /// <returns></returns> private static int GetTableDepth(ExcelWorksheet worksheet, int headerOffset) { var i = 1; var j = 1; var cellValue = worksheet.Cells[i + headerOffset, j].Value; while (cellValue != null) { i++; cellValue = worksheet.Cells[i + headerOffset, j].Value; } return i - 1; //subtract one because we''re going from rownumber (1 based) to depth (0 based) } private static IEnumerable<DataColumn> GetDataColumns(ExcelWorksheet worksheet) { return GatherColumnNames(worksheet).Select(x => new DataColumn(x)); } private static IEnumerable<string> GatherColumnNames(ExcelWorksheet worksheet) { var columns = new List<string>(); var i = 1; var j = 1; var columnName = worksheet.Cells[i, j].Value; while (columnName != null) { columns.Add(GetUniqueColumnName(columns, columnName.ToString())); j++; columnName = worksheet.Cells[i, j].Value; } return columns; } private static string GetUniqueColumnName(IEnumerable<string> columnNames, string columnName) { var colName = columnName; var i = 1; while (columnNames.Contains(colName)) { colName = columnName + i.ToString(); i++; } return colName; }


MS Office Interop es lento e incluso Microsoft no recomienda el uso de Interop en el lado del servidor y no se puede usar para importar archivos grandes de Excel. Para obtener más detalles, vea por qué no usar la automatización OLE desde el punto de vista de Microsoft.

En cambio, puede usar cualquier biblioteca de Excel, como EasyXLS por ejemplo. Este es un ejemplo de código que muestra cómo leer el archivo de Excel:

ExcelDocument workbook = new ExcelDocument(); DataSet ds = workbook.easy_ReadXLSActiveSheet_AsDataSet("excel.xls"); DataTable dataTable = ds.Tables[0];

Si su archivo Excel tiene varias hojas o para importar solo rangos de celdas (para un mejor rendimiento) eche un vistazo a más ejemplos de código sobre cómo importar Excel a DataTable en C # usando EasyXLS .



Dim sSheetName As String Dim sConnection As String Dim dtTablesList As DataTable Dim oleExcelCommand As OleDbCommand Dim oleExcelReader As OleDbDataReader Dim oleExcelConnection As OleDbConnection sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:/Test.xls;Extended Properties=""Excel 12.0;HDR=No;IMEX=1""" oleExcelConnection = New OleDbConnection(sConnection) oleExcelConnection.Open() dtTablesList = oleExcelConnection.GetSchema("Tables") If dtTablesList.Rows.Count > 0 Then sSheetName = dtTablesList.Rows(0)("TABLE_NAME").ToString End If dtTablesList.Clear() dtTablesList.Dispose() If sSheetName <> "" Then oleExcelCommand = oleExcelConnection.CreateCommand() oleExcelCommand.CommandText = "Select * From [" & sSheetName & "]" oleExcelCommand.CommandType = CommandType.Text oleExcelReader = oleExcelCommand.ExecuteReader nOutputRow = 0 While oleExcelReader.Read End While oleExcelReader.Close() End If oleExcelConnection.Close()