Modify excel cell
早上好,
我想从现有的 Excel 文件中编辑一些单元格。我尝试使用 EPPlus 和普通的 OpenXml 类。然而我失败了。在这两种情况下,程序都不会崩溃,但总是返回旧的(未修改的)excel。请问,我做错了什么?
试验 1 - EPPlus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | MemoryStream memoryStream = new MemoryStream(); using (var fs = new FileStream(@"Path\\Test.xlsx", FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) { memoryStream.Write(buffer, 0, bytesRead); } } using (ExcelPackage excelPackage = new ExcelPackage(memoryStream)) { ExcelWorkbook excelWorkBook = excelPackage.Workbook; ExcelWorksheet excelWorksheet = excelWorkBook.Worksheets.First(); excelWorksheet.Cells[1, 1].Value ="Test"; excelWorksheet.Cells[3, 2].Value ="Test2"; excelWorksheet.Cells[3, 3].Value ="Test3"; excelPackage.Save(); } memoryStream.Position = 0; return new FileStreamResult(memoryStream,"application/xlsx") { FileDownloadName ="Tester.xlsx" }; |
我怎么说它返回旧的 excel。但在调试模式下,它也包含新值。看来不能修改 memoryStream。
试用 2 - OpenXml 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Stream stream = System.IO.File.Open(@"Path\\Test.xlsx", FileMode.Open); using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(stream, true)) { WorksheetPart worksheetPart = GetWorksheetPartByName(spreadSheet,"Sheet1"); Cell cell = GetCell(worksheetPart.Worksheet,"C", 3); cell.CellValue = new CellValue("Testos"); cell.DataType = new EnumValue<CellValues>(CellValues.String); worksheetPart.Worksheet.Save(); } stream.Position = 0; return new FileStreamResult(stream,"application/xlsx") { FileDownloadName ="Tester.xlsx" }; |
和辅助方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | private static Row GetRow(Worksheet worksheet, uint rowIndex) { Row row; if (worksheet.GetFirstChild<SheetData>().Elements<Row>().Where(r => r.RowIndex == rowIndex).Count() != 0) { row = worksheet.Elements<Row>().Where(r => r.RowIndex == rowIndex).FirstOrDefault(); } else { row = new Row() { RowIndex = rowIndex }; worksheet.Append(row); } return row; } private static Cell GetCell(Worksheet worksheet, string columnName, uint rowIndex) { Row row = GetRow(worksheet, rowIndex); string cellReference = columnName + rowIndex; if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex).Count() > 0) { return row.Elements<Cell>().Where(c => c.CellReference.Value == cellReference).FirstOrDefault(); } else { Cell refCell = null; foreach (Cell cell in row.Elements<Cell>()) { if (string.Compare(cell.CellReference.Value, cellReference, true) > 0) { refCell = cell; break; } } Cell newCell = new Cell() { CellReference = cellReference }; row.InsertBefore(newCell, refCell); worksheet.Save(); return newCell; } } private static WorksheetPart GetWorksheetPartByName(SpreadsheetDocument document, string sheetName) { IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name == sheetName); string relationshipId = sheets.First().Id.Value; WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId); return worksheetPart; } |
再次感谢您的帮助。
这两种情况的问题是修改后的工作簿没有保存回流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | MemoryStream ms = new MemoryStream(); using (FileStream fs = File.OpenRead(@"Path\\Test.xlsx")) using (ExcelPackage excelPackage = new ExcelPackage(fs)) { ExcelWorkbook excelWorkBook = excelPackage.Workbook; ExcelWorksheet excelWorksheet = excelWorkBook.Worksheets.First(); excelWorksheet.Cells[1, 1].Value ="Test"; excelWorksheet.Cells[3, 2].Value ="Test2"; excelWorksheet.Cells[3, 3].Value ="Test3"; excelPackage.SaveAs(ms); // This is the important part. } ms.Position = 0; return new FileStreamResult(ms,"application/xlsx") { FileDownloadName ="Tester.xlsx" }; |
虽然已经回答了这个问题,但我会根据我的经验补充一下。
从FileInfo而不是Stream打开ExcelPackage更容易,然后保存变得更简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | FileInfo file = new FileInfo(path); using (var package = new ExcelPackage(file)) { ExcelWorkbook workBook = package.Workbook; ExcelWorksheet currentWorksheet = workBook.Worksheets.SingleOrDefault(w => w.Name =="sheet1"); int totalRows = currentWorksheet.Dimension.End.Row; int totalCols = currentWorksheet.Dimension.End.Column; for (int i = 2; i <= totalRows; i++) { try { currentWorksheet.Cells[i, 1].Value ="AAA"; } catch (Exception ex) { _logger.Error(String.Format("Error: failed editing excel. See details: {0}", ex)); return; } } package.Save(); |
您可以使用 Microsoft 的 Interop dll 来编辑 Office 文档 http://msdn.microsoft.com/en-us/library/15s06t57.aspx。将"Microsoft.Office.Interop.Excel.dll"添加到您的解决方案中。使用此代码,我更改了 2 个单元格值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | static void Main(string[] args) { Application excel = new Application(); Workbook workbook = excel.Workbooks.Open(@"C:\\Users\\Martijn\\Documents\\Test.xlsx", ReadOnly: false, Editable:true); Worksheet worksheet = workbook.Worksheets.Item[1] as Worksheet; if (worksheet == null) return; Range row1 = worksheet.Rows.Cells[1, 1]; Range row2 = worksheet.Rows.Cells[2, 1]; row1.Value ="Test100"; row2.Value ="Test200"; excel.Application.ActiveWorkbook.Save(); excel.Application.Quit(); excel.Quit(); } |
在程序运行更改为正确值之后,我已经开始使用 Test1 和 Test2。
我正在使用 ClosedXML,其中更新单元格值很容易:
1 2 3 4 | var workbook = new XLWorkbook("HelloWorld.xlsx"); // load the existing excel file var worksheet = workbook.Worksheets.Worksheet(1); worksheet.Cell("A1").SetValue("Hello World!"); workbook.Save(); |
可以在此处找到 NuGet 包。
//这可以帮助您在文件 excel 中设置单元格:使用 System.Data.OleDb;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Directory.GetCurrentDirectory() +"/swtlist.xlsx;" + @"Extended Properties='Excel 12.0;HDR=Yes;';Persist Security Info=False;"; using (OleDbConnection connection = new OleDbConnection(connString)) { connection.Open(); try { OleDbCommand cmd = new OleDbCommand("UPDATE [Feuil1$] SET d='yes'", connection); cmd.ExecuteNonQuery(); connection.Close(); } catch (Exception ex) { } } |