Good morning, I would like to edit some cells from already existing excell file. I tried use EPPlus and normal OpenXml classes. However I failed. In both situation program won't crash but always return old (not modified) excel. Please, what am I doing wrong?
Trial 1 - EPPlus:
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"
};
How i said it returns old excel. But in debug mode it contains new value also. It looks like memoryStream cannot be modified.
Trial 2 - OpenXml classes
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"
};
And helper methods:
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;
}
Once more thank you for help.
The problem in both cases is that the modified workbook is not saved back to the stream:
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"
};