Npoi xls file save corrupts excel file - c#

So I am able to open and dig through an xls (Excel 97-2003) file. However, the problem is when I try to save it. After I save it, and it succeeds, I then go and manually open the Excel file and get an error saying that it cannot open the Excel file and that it is corrupt. This happens regardless of whether I make any changes or not.
I am still able to, within the program, open the excel file and read through the data.
I am using NPOI 2.2.1 and 2.3.0 (which I installed via Nuget). Both versions have the same results.
string excelLocation = settings.GetExcelDirectory() + week.ExcelLocation;
HSSFWorkbook wbXLS;
// Try to open and read existing workbook
using (FileStream stream = new FileStream(excelLocation, FileMode.Open, FileAccess.Read))
{
wbXLS = new HSSFWorkbook(stream);
}
ISheet sheet = wbXLS.GetSheet("Schedule");
using (FileStream stream = new FileStream(excelLocation, FileMode.Create, FileAccess.Write))
{
wbXLS.Write(stream);
}

Do you have multi-line cell contents (with a line break)?
I just came across such a problem with my column headers in row 0.
Excel encodes a line break by replacing it with _x000a_ (i.e. line1_x000a_line2), NPOI doesn't do that.
Tried with nuget 2.3.0 and xlsx file, but might also be helpful in your case.
I worked around (and verified the cause) by replacing line feeds before saving:
// Encode LineFeeds in column headers (row 0)
IRow rowColHeaders = sheet.GetRow(0);
foreach (ICell cell in rowColHeaders.Cells)
{
string content = cell.StringCellValue;
if (content.Contains("\n"))
cell.SetCellValue(content.Replace("\n", "_x000a_"));
}

try something like
FileStream sw = File.Create(excelLocation);
wbXLS.Write(sw);
sw.Close();

Related

Is there any way to read xlsx when i open a excel to edit it at the same time in c#?

When I use c# to read a excel which I use excel to open it, there is a error The process cannot access the file 'xxxx' because it is being used by another process.
Is there any way to do this, I don't wan't open it for every time.
I'm not sure how you're trying to read the xlsx file, so it might not be possible using the library or tool that you are currently using.
It is possible to open the file stream for reading while Excel has the file open. However, you should be aware that it is also inherently dangerous. The process reading the excel file expects to be reading a consistent view of the file. If Excel decides to write to that same file while it is being read, then it is almost assured that the reading process will fail in some catastrophic way. Since an .xlsx file is just a zip file, the most likely result will be a failure in accessing or decompressing one of the .xlsx entries.
Here is an example of how you can do this using a library I maintain: Sylvan.Data.Excel.
var file = "myfile.xlsx";
// DANGEROUS: open it for reading, but allow other processes to write to it at the same time.
var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// gets the workbook type from the filename extension
var type = ExcelDataReader.GetWorkbookType(file);
// create the data reader
var reader = ExcelDataReader.Create(stream, type);
// loop over rows
while (reader.Read())
{
// write out the data in the row
Console.WriteLine("Row: " + reader.RowNumber);
for (int i = 0; i < reader.RowFieldCount; i++)
{
Console.WriteLine(reader.GetString(i));
}
Console.WriteLine();
}

NPOI corrupting xlsm workbook

I am required to write some data into an macro enabled workbook which was developed in 1998, i am using NPOI dotnet core library for this task. I am able to write the values into the excel correctly, however i am seeing that alignment and formatting of the sheets is lost. Screenshots below:
First one shows the file after open the file using NPOI and downloading the same, and second shows the file when it is locally opened.
below is the code i am using
public XSSFWorkbook OpenExcelFile(string filePath, string tempSavePath)
{
using (var stream = new FileStream(tempSavePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var temphssfwb = new XSSFWorkbook(OPCPackage.Open(filePath));
temphssfwb.Write(stream);
}
XSSFWorkbook hssfwb;
hssfwb = new XSSFWorkbook(OPCPackage.Open(tempSavePath));
hssfwb.CreateSheet("casevalidationsheet");
return hssfwb;
}
Can someone please help me understand why NPOI is ruining the alignment of my excel workbook?

Excel file generated with C # is corrupted (ExcelExportEngine & IExportEngine)

I have an application made in C # that allows to generate an excel file from a list (List <>).
The code that generates the excel file has worked without problems but today a user who still uses windows 7 has indicated that the excel file has been generated but when it is opened it is unreadable.
The code to generate the excel is as follows:
IExportEngine engine = new ExcelExportEngine();
engine.AddData(productListExport);
MemoryStream memory = engine.Export();
FileStream fileStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel files (*.xls or .xlsx)|.xls;*.xlsx";
saveFileDialog1.Title = "Export product list to Excel";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
String path = Path.GetFullPath(saveFileDialog1.FileName);
fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
memory.WriteTo(fileStream);
fileStream.Close();
}
When you open the excel file, a message appears saying that the format and extension does not match, if you choose to open the option to open anyway, it looks like the following image:
Any suggestions or comments are welcome.
UPDATE:
About ExcelExportEngine:
https://github.com/vvenegasv/exportable
The screenshot looks like the contents of an xlsx file. An xlsx file is a zip package containing XML files. The various xml paths in there are a very strong indication. The PK bytes too, but I saw docProps.xml first.
The code itself has a serious problem - it generates the Excel file contents before asking for a format. Given that the xls format became obsolete 13 years ago, the only sensible default is to use xlsx. If an xlsx file is saved as xls, Excel will complain. In my case though, it was able to load the file.
It looks like the code uses the Exportable package. The examples in the Github repo show how to specify the format. Apart from MemoryStream Export() though, the library also has an Export(string path) that writes to a file. The source code shows that Export(string) selects the format based on the extension and throws if it's invalid.
This means that the code can be reduced to :
IExportEngine engine = new ExcelExportEngine();
engine.AddData(productListExport);
var saveFileDialog1 = new SaveFileDialog(){
Filter = "Excel files (*.xls or .xlsx)|.xls;*.xlsx",
Title = "Export product list to Excel"
}
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
var path = Path.GetFullPath(saveFileDialog1.FileName);
engine.Export(path);
}
I'd also suggest getting rid of the xls option too. It's not just that it was replaced 13 years ago. The format wasn't well defined to begin so libraries always have issues producing the same output Excel did. Services like Google Sheets or Office Online only work with xlsx. You have to pay to get xls support. The file size is a lot smaller too.

Can't edit the existing Excel file with NPOI?

I've tried creating a new Excel file with NPOI and it works OK, reading (only) an Excel file is also OK. However now I want to open an existing Excel file and append some rows on it, it's crashed right at the code line of the NPOI.HSSF.UserModel.HSSFWorkbook constructor. Here is the code:
using(FileStream fs = new FileStream(myFile, FileMode.Append)){
HSSFWorkbook wb = new HSSFWorkbook(fs); //<-- It is crashed right at here
....
}
There is no exception detail, it just shows a window saying that the app is crashed and give 3 options to choose, the middle one is to close the application:
snapshot
That's why I can't understand and feel hard to solve it.
If I change the FileMode to FileMode.Open, the constructor can work well, but that's just for reading. I think there is some thing related to FileAccess policy and tried this:
using(FileStream fs = new FileStream(myFile, FileMode.Append, FileAccess.ReadWrite)){//<-- However it is crashed right at here
HSSFWorkbook wb = new HSSFWorkbook(fs);
....
}
I've tried a workaround by opening (read only) the existing Excel file, copy 1 sheet of it and add this sheet to a new HSSFWorkbook and write (write only) to a new file stream, however there is no way to do that, because the HSSFWorkbook has no collection of Worksheet and there is also no Add method, the new sheet is just created by CreateSheet() method. It's so annoying.
Could you please help me with this? I'm trying NPOI first, then I'll try EPPlus.Your help would be highly appreciated.Thanks.
What's your file format? xls or xlsx? If xlsx, you can try NPOI 2.0 now. xlsx is supported.
Here is the download link: https://npoi.codeplex.com/releases/view/112932

Read excel file from a stream

I need a way to read a Excel file from a stream. It doesn't seem to work with the ADO.NET way of doing things.
The scenario is that a user uploads a file through a FileUpload and i need to read some values from the file and import to a database.
For several reasons I can't save the file to disk, and there is no reason to do so either.
So, anyone know of a way to read a Excel file from a FileUpload stream?
It seems i found a soultion to the problem myself.
http://www.codeplex.com/ExcelDataReader
This library seems to work nicely and it takes a stream to read the excel file.
ExcelDataReader reader = new ExcelDataReader(ExcelFileUpload.PostedFile.InputStream);
This can be done easily with EPPlus.
//the excel sheet as byte array (as example from a FileUpload Control)
byte[] bin = FileUpload1.FileBytes;
//gen the byte array into the memorystream
using (MemoryStream ms = new MemoryStream(bin))
using (ExcelPackage package = new ExcelPackage(ms))
{
//get the first sheet from the excel file
ExcelWorksheet sheet = package.Workbook.Worksheets[1];
//loop all rows in the sheet
for (int i = sheet.Dimension.Start.Row; i <= sheet.Dimension.End.Row; i++)
{
//loop all columns in a row
for (int j = sheet.Dimension.Start.Column; j <= sheet.Dimension.End.Column; j++)
{
//do something with the current cell value
string currentCellValue = sheet.Cells[i, j].Value.ToString();
}
}
}
SpreadsheetGear can do it:
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbookSet().Workbooks.OpenFromStream(stream);
You can try it for yourself with the free evaluation.
Disclaimer: I own SpreadsheetGear LLC
Infragistics has an excel component that can read an excel file from a stream.
I'm using it in a project here and it works well.
Also the open source myXls component could easily be modified to support this. The XlsDocument contstructor only supports loading from a file given by a file name, but it works by creating a FileStream and then reading the Stream, so changing it to support loading from streams should be trivial.
Edit:
I see that you found a solution but I just wanted to note that I updated the source code for the component so that it now can read an excel file directly from a stream. :-)
I use ClosedXML nuget package to read excel content from stream. It has a constructor overload in XLWorkbook class which takes stream pointing to an excel file (aka workbook).
imported namespace at the top of your code file:
using ClosedXML.Excel;
Source code:
var stream = /*obtain the stream from your source*/;
if (stream.Length != 0)
{
//handle the stream here
using (XLWorkbook excelWorkbook = new XLWorkbook(stream))
{
var name = excelWorkbook.Worksheet(1).Name;
//do more things whatever you like as you now have a handle to the entire workbook.
var firstRow = excelWorkbook.Worksheet(1).Row(1);
}
}

Categories

Resources