使用EPPlus Excel到DataTable – excellocking进行编辑

我正在使用以下代码使用EPPlus将Excel转换为数据表:

public DataTable ExcelToDataTable(string path) { var pck = new OfficeOpenXml.ExcelPackage(); pck.Load(File.OpenRead(path)); var ws = pck.Workbook.Worksheets.First(); DataTable tbl = new DataTable(); bool hasHeader = true; foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column]) { tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column)); } var startRow = hasHeader ? 2 : 1; for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++) { var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column]; var row = tbl.NewRow(); foreach (var cell in wsRow) { row[cell.Start.Column - 1] = cell.Text; } tbl.Rows.Add(row); } pck.Dispose(); return tbl; } 

它创build了Excel,但是,当我尝试打开它时,它给了我一个信息,表示它被locking以供其他用户编辑,而且我只能以只读模式打开它。

我以为用了:

 pck.Dispose(); 

将解决这个问题,但是我仍然得到相同的错误。

另外,当我尝试删除该文件时,我收到消息:由于该文件在WebDev.WebServer40.EXE中打开,因此操作无法完成。

任何想法如何解决这个问题? 提前致谢。 🙂

我明白了,这就是我最近在这里发布的 (现在已经更正了)。 由于ExcelPackageFileStream (来自File.OpenRead )在使用后不会被处理,因此可以进行改进。

 public static DataTable GetDataTableFromExcel(string path, bool hasHeader = true) { using (var pck = new OfficeOpenXml.ExcelPackage()) { using (var stream = File.OpenRead(path)) { pck.Load(stream); } var ws = pck.Workbook.Worksheets.First(); DataTable tbl = new DataTable(); foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column]) { tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column)); } var startRow = hasHeader ? 2 : 1; for (int rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++) { var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column]; DataRow row = tbl.Rows.Add(); foreach (var cell in wsRow) { row[cell.Start.Column - 1] = cell.Text; } } return tbl; } } 

Tim Schmelter的答案的扩展版本。

 public static DataTable ToDataTable(this ExcelWorksheet ws, bool hasHeaderRow = true) { var tbl = new DataTable(); foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column]) tbl.Columns.Add(hasHeaderRow ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column)); var startRow = hasHeaderRow ? 2 : 1; for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++) { var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column]; var row = tbl.NewRow(); foreach (var cell in wsRow) row[cell.Start.Column - 1] = cell.Text; tbl.Rows.Add(row); } return tbl; } 

这是对上面通用的一个改进。 使用是,如果你有一个类具有以下属性,“名称”,“姓氏”,“电话”,“传真”,你有一个Excel表格与第一行相同的名称,它会加载到Excel行类对象并将其popup到List中

 public static List<T> GetClassFromExcel<T>(string path, int fromRow, int fromColumn, int toRow = 0, int toColumn = 0) { if (toColumn != 0 && toColumn < fromColumn) throw new Exception("toColumn can not be less than fromColumn"); if (toRow != 0 && toRow < fromRow) throw new Exception("toRow can not be less than fromRow"); List<T> retList = new List<T>(); using (var pck = new ExcelPackage()) { using (var stream = File.OpenRead(path)) { pck.Load(stream); } //Retrieve first Worksheet var ws = pck.Workbook.Worksheets.First(); //If the to column is empty or 0, then make the tocolumn to the count of the properties //Of the class object inserted toColumn = toColumn == 0 ? typeof(T).GetProperties().Count() : toColumn; //Read the first Row for the column names and place into a list so that //it can be used as reference to properties Dictionary<string, int> columnNames = new Dictionary<string, int>(); // wsRow = ws.Row(0); var colPosition = 0; foreach (var cell in ws.Cells[1, 1, 1, toColumn == 0 ? ws.Dimension.Columns : toColumn]) { columnNames.Add(cell.Value.ToString(), colPosition); colPosition++; } //create a instance of T T objT = Activator.CreateInstance<T>(); //Retrieve the type of T Type myType = typeof(T); //Get all the properties associated with T PropertyInfo[] myProp = myType.GetProperties(); //Loop through the rows of the excel sheet for (var rowNum = fromRow; rowNum <= (toRow == 0? ws.Dimension.End.Row : toRow); rowNum++) { var wsRow = ws.Cells[rowNum, fromColumn, rowNum, ws.Cells.Count()]; foreach (var propertyInfo in myProp) { if (columnNames.ContainsKey(propertyInfo.Name)) { int position = 0; columnNames.TryGetValue(propertyInfo.Name, out position); //int position = columnNames.IndexOf(propertyInfo.Name); //To prevent an exception cast the value to the type of the property. propertyInfo.SetValue(objT, Convert.ChangeType(wsRow[rowNum, position + 1].Value, propertyInfo.PropertyType)); } } retList.Add(objT); } } return retList; } 

现在你可以使用列表作为数据绑定源,如果你需要…给我一个给你… 🙂 Daniel C. Vrey

更新为toColumn工作,并添加到行,并遵循安德烈亚斯的build议。 竖起大拇指为安德烈亚斯

我已经创build了一个使用EPPlus将Excel文件转换为DataTable的方法,并试图保持types安全性。 此外,处理重复的列名称,并使用布尔值来告诉方法表单中是否有标题行。 我已经创build了一个复杂的导入过程,上传后有几个步骤,在提交数据库之前需要用户input。

 private DataTable ExcelToDataTable(byte[] excelDocumentAsBytes, bool hasHeaderRow) { DataTable dt = new DataTable(); string errorMessages = ""; //create a new Excel package in a memorystream using (MemoryStream stream = new MemoryStream(excelDocumentAsBytes)) using (ExcelPackage excelPackage = new ExcelPackage(stream)) { ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1]; //check if the worksheet is completely empty if (worksheet.Dimension == null) { return dt; } //add the columns to the datatable for (int j = worksheet.Dimension.Start.Column; j <= worksheet.Dimension.End.Column; j++) { string columnName = "Column " + j; var excelCell = worksheet.Cells[1, j].Value; if (excelCell != null) { var excelCellDataType = excelCell; //if there is a headerrow, set the next cell for the datatype and set the column name if (hasHeaderRow == true) { excelCellDataType = worksheet.Cells[2, j].Value; columnName = excelCell.ToString(); //check if the column name already exists in the datatable, if so make a unique name if (dt.Columns.Contains(columnName) == true) { columnName = columnName + "_" + j; } } //try to determine the datatype for the column (by looking at the next column if there is a header row) if (excelCellDataType is DateTime) { dt.Columns.Add(columnName, typeof(DateTime)); } else if (excelCellDataType is Boolean) { dt.Columns.Add(columnName, typeof(Boolean)); } else if (excelCellDataType is Double) { //determine if the value is a decimal or int by looking for a decimal separator //not the cleanest of solutions but it works since excel always gives a double if (excelCellDataType.ToString().Contains(".") || excelCellDataType.ToString().Contains(",")) { dt.Columns.Add(columnName, typeof(Decimal)); } else { dt.Columns.Add(columnName, typeof(Int64)); } } else { dt.Columns.Add(columnName, typeof(String)); } } else { dt.Columns.Add(columnName, typeof(String)); } } //start adding data the datatable here by looping all rows and columns for (int i = worksheet.Dimension.Start.Row + Convert.ToInt32(hasHeaderRow); i <= worksheet.Dimension.End.Row; i++) { //create a new datatable row DataRow row = dt.NewRow(); //loop all columns for (int j = worksheet.Dimension.Start.Column; j <= worksheet.Dimension.End.Column; j++) { var excelCell = worksheet.Cells[i, j].Value; //add cell value to the datatable if (excelCell != null) { try { row[j - 1] = excelCell; } catch { errorMessages += "Row " + (i - 1) + ", Column " + j + ". Invalid " + dt.Columns[j - 1].DataType.ToString().Replace("System.", "") + " value: " + excelCell.ToString() + "<br>"; } } } //add the new row to the datatable dt.Rows.Add(row); } } //show error messages if needed Label1.Text = errorMessages; return dt; } 

点击Webformsbutton进行演示。

 protected void Button1_Click(object sender, EventArgs e) { if (FileUpload1.HasFile) { DataTable dt = ExcelToDataTable(FileUpload1.FileBytes, CheckBox1.Checked); GridView1.DataSource = dt; GridView1.DataBind(); } } 
 public static List<T> getClassFromExcel<T>(string path, int fromRow, int fromColumn, int toColumn = 0) where T : class { using (var pck = new OfficeOpenXml.ExcelPackage()) { List<T> retList = new List<T>(); using (var stream = File.OpenRead(path)) { pck.Load(stream); } var ws = pck.Workbook.Worksheets.First(); toColumn = toColumn == 0 ? typeof(T).GetProperties().Count() : toColumn; for (var rowNum = fromRow; rowNum <= ws.Dimension.End.Row; rowNum++) { T objT = Activator.CreateInstance<T>(); Type myType = typeof(T); PropertyInfo[] myProp = myType.GetProperties(); var wsRow = ws.Cells[rowNum, fromColumn, rowNum, toColumn]; for (int i = 0; i < myProp.Count(); i++) { myProp[i].SetValue(objT, wsRow[rowNum, fromColumn + i].Text); } retList.Add(objT); } return retList; } }