This might be the duplicate as many posts refer to this kind of issues but I could not find an exact answer to this case.
So, what I have is an Excel file where cell "E4" contains a formula "=C4+D4". All other cells are empty, which means I cannot search or get them via OpenXml, simply because they do not exist in Xml. So in order to fill the cells "C4" and "D4" I have to create them (like this:)
var cell = new Cell(){
CellReference = new StringValue("C4"),
DataType = new EnumValue<CellValues>(CellValues.Number),
CellValue = new CellValue("123")
}
the same for cell "D4" and then append these cells to the row
row.Append(cell);
After I open the excel file it show an error "Excel found unreadable content in file.xlsx. Do you want to recover the contents of this workbook? If you trust the source of this workbook, click Yes."
I checked and when there is no formula in excel file the cells are appended correctly.
So my question is, using OpenXml how do I append cells in Excel file, which contains formula, so that not to break the file?
So the XML is malformed and corrupted the has file, hence the error:
Excel found unreadable content in file
To troubleshoot and fix this I suggest you compare the manually created xlsx to the programmatically created xlsx.
To do this you rename both files extensions from XLSX to ZIP > extract them to different folders > use a WinDiff tool (or better the "OpenXML SDK Productivity Tool") to compare the files.
Once you find how its malformed change your code to try and fix it up.
I solved my problem using EPPLUS
using (ExcelPackage excelPackage = new ExcelPackage(fileStream))
{
ExcelWorkbook excelWorkBook = excelPackage.Workbook;
ExcelWorksheet excelWorksheet = excelWorkBook.Worksheets.First();
excelWorksheet.Cells["C4"].Value = "123";
excelWorksheet.Cells["D4"].Value = "321";
excelPackage.SaveAs(memoryStream);
}
Related
I have a project where my goal is to produce an .xlsm Excel spreadsheet using .NET and the EEPlus 5.8.14 Excel Spreadsheet library. I can do this using EEPlus's documented techniques, (though some of these I cannot get to work). As I was working on this, I realized that what my code needed to do was relatively small, and it made sense to use an existing .xlsm file as a template and just make changes to what I needed to change using EEPlus.
So now I am including the .xlsm file as a resource compiled into the assembly. This works great, and I can read the file from the resources and produce it from my controller. But once read, this data inside EPPlus seems to be read-only. So while this produces an Excel file:
public ActionResult ExcelFile(){
const string ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Byte[] bytes = Properties.Resources.AssetsEntry;
string fstem = Path.GetRandomFileName();
int unique = 0;
string filePath = String.Format("{0}#AutoGen_{1}_{2}.{3}", Path.GetTempPath(), fstem, ++unique, "xlsm");
var outStream = System.IO.File.OpenWrite(filePath);
var writer = new BinaryWriter(outStream);
writer.Write(bytes);
outStream.Close();
ExcelPackage excelPackage = new ExcelPackage(filePath);
var sheet = excelPackage.Workbook.Worksheets[1];
//place where I might want to change data
//sheet.Cells["B3"].Value = "testing";
var excelData = excelPackage.GetAsByteArray();
var fileName = "ExcelFile.xlsm";
return File(excelData, ContentType, fileName);
}
If I try to uncomment out the second commented-out line, that code fails to change the resulting Excel spreadsheet (though there is no error). How do I go about reading in an Excel spreadsheet and making changes using EEPlus?
UPDATE: I can add new worksheets to an uploaded spreadsheet, and I can alter those added sheets. But I cannot alter data on uploaded worksheets. Fortunately, for this particular project, that is acceptable. But it would be frustrating if I wanted to be able to set up a worksheet in Excel and then populate it programmatically.
I want to read data from excel using EEPLUS in C#. Who can teach me or share the link to teach it? Thanks for reading!
It is really easy to use, just read through the GetStarted of their GitHub.
Example:
//Open the workbook (or create it if it doesn't exist)
var fi=new FileInfo(#"c:\workbooks\myworkbook.xlsx")
using (var p = new ExcelPackage(fi))
{
//Get the Worksheet created in the previous codesample.
var ws=p.Workbook.Worksheets["MySheet"];
Set the cell value using row and column.
ws.Cells[2, 1].Value = "This is cell A2. It is set to bolds";
//The style object is used to access most cells formatting and styles.
ws.Cells[2, 1].Style.Font.Bold=true;
//Save and close the package.
p.Save();
}
I'm generating the head of different CSV files so my users can see the format
var output = new MemoryStream()
var writer = new StreamWriter(output, Encoding.UTF8);
//this function gets the row depending of the enumerator name in this format a;b;c;d
var header = ModelosCsv.GetCsvByEnum("HeadRowFileLoad");
writer.WriteLine(header);
writer.Flush();
output.Position = 0;
return File(output, "application/csv", "format.csv");
The code is creating the CSV correctly but if they open the CSV with excel and save it, excel will overwrite all the ";" for triple spaces.
If I edit the result with notepad++ and put back the ";" excel won't do it again.
I have opened both archives with excel and clicked "save as", the first one (freshly generated by c#) is set as default as "text archive" the second one (edited by notepad++) is set as CSV.
Am I missing something code?
How could I do to stop excel messing up my archives?
I found the solution in this answered question
Export to CSV using MVC, C# and jQuery
var header = ModelosCsv.GetCsvByEnum("HeadRowFileLoad");
return File(new System.Text.UTF8Encoding().GetBytes(header), "application/csv", "format.csv");
This way Excel identifies the archive as CSV and editing wont break the format.
I want to use EPPLUS to clear a range of cells. I tried the syntax below, but it gives me an error of
object reference not set to an instance of an object
What would be the proper way to clear the contents of cells A24:C36 with EPPLUS?
ExcelPackage package = new ExcelPackage();
ExcelWorksheet ws = package.Workbook.Worksheets["Sheet1"];
ws.Cells["A24:C36"].Clear();
Your code is correct. I think the .xlsx file does not have Worksheets with Sheet1 name.
For example, I created this excel file like this:
I wanted to erase A24:C36. I encountered null reference error before executing ws.Cells["A24:C36"].Clear(); like this:
If I use code below instead of it, it works properly (Sheet2).
ExcelPackage package = new ExcelPackage();
ExcelWorksheet ws = package.Workbook.Worksheets["Sheet2"];
ws.Cells["A24:C36"].Clear();
Notice that having no value in A24:C36 does not make an error.
I want to read excel file but in this way is too slow. What pattern should I use to read excel file faster. Should I try csv ?
I am using the following code:
ApplicationClass excelApp = excelApp = new ApplicationClass();
Workbook myWorkBook = excelApp.Workbooks.Open(#"C:\Users\OWNER\Desktop\Employees.xlsx");
Worksheet mySheet = (Worksheet)myWorkBook.Sheets["Sheet1"];
for (int row = 1; row <= mySheet.UsedRange.Rows.Count; row++)
{
for (int col = 1; col <= mySheet.UsedRange.Columns.Count; col++)
{
Range dataRange = (Range)mySheet.Cells[row, col];
Console.Write(String.Format(dataRange.Value2.ToString() + " "));
}
Console.WriteLine();
}
excelApp.Quit();
The reason your program is slow is because you are using Excel to open your Excel files. Whenever you are doing anything with the file you have to do a COM+ interop, which is extremely slow, as you have to pass memory across two different processes.
Microsoft has dropped support for reading .xlsx files using Excel interop. They released the OpenXML library specifically for this reason.
I suggest you use a wrapper library for using OpenXML, since the API is pretty hairy. You can check out this SO for how to use it correctly.
open xml reading from excel file
You're accessing Excel file through excel interop. By doing reads cell by cell you're doing a lot of P/Invoke's which is not very performant.
You can read data in ranges, not cell by cell. This loads the data into memory and you could iterate it much faster. (Eg. try to load column by column.)
BTW: You could use some library instead like http://epplus.codeplex.com which reads excel files directly.
Excel Data Reader
Lightweight and very fast if reading is your only concern.