Getting a corrupted XLS file using NPOI - c#

I tried to debug this code, but I didn't manage. Do any of you have any idea why my script creates a corrupted XLS file?
string strCaleSalvareTest = #"C:\Users\andrei.tudor\Documents\TipMacheta.xls";
HSSFWorkbook wbXLS;
strEr = "Er";
try
{
fsXLSCitire = new FileStream(strCaleSalvareTest, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
wbXLS = new HSSFWorkbook(fsXLSCitire);
strEr = string.Empty;
}
catch (Exception ex)
{
strEr = ex.Message;
}
When I try to run this, it jumps from wbXLS creation to the catch exception block.

You're getting an exception because you are creating a new FileStream for writing (FileAccess.Write) and passing it to the constructor of HSSFWorkbook which is expecting to be able to read from the stream. The file is corrupt because the FileStream is creating the file, but nothing is ever written to it.
If you're just trying to create a new blank workbook and save it to a file, you can do that as shown below. Note that you need to add at least one worksheet to the new workbook, or you will still generate a corrupt file.
// Create a new workbook with an empty sheet
HSSFWorkbook wbXLS = new HSSFWorkbook();
ISheet sheet = wbXLS.CreateSheet("Sheet1");
// Write the workbook to a file
string fileName = #"C:\Users\andrei.tudor\Documents\TipMacheta.xls";
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
wbXLS.Write(stream);
}
If you're trying to read an existing workbook OR create a new one if it doesn't exist, you need to do something like this:
string fileName = #"C:\Users\andrei.tudor\Documents\TipMacheta.xls";
HSSFWorkbook wbXLS;
try
{
// Try to open and read existing workbook
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
wbXLS = new HSSFWorkbook(stream);
}
}
catch (FileNotFoundException)
{
// Create a new workbook with an empty sheet
wbXLS = new HSSFWorkbook();
wbXLS.CreateSheet("Sheet1");
}
ISheet sheet = wbXLS.GetSheetAt(0); // Get first sheet
// ...
// Write workbook to file
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
wbXLS.Write(stream);
}

Related

How to create a new column when editing an Excel file C# NPOI

I am trying to create a new column in the middle of an existing .xlsx sheet, but I can't find any way to do it.
XSSFWorkbook workbook;
await using (var file = new FileStream(#"File.xlsx", FileMode.Open, FileAccess.Read))
{
workbook = new XSSFWorkbook(file);
file.Close();
}
var editSheet = workbook.GetSheetAt(0);
await using (var file = new FileStream(#"File.xlsx", FileMode.Open, FileAccess.Write))
{
workbook.Write(file);
file.Close();
}
I am able to easily create a new row using editSheet.CreateRow(2) but I can't find anything similar for creating a column.
I think, that You can operate only just on rows and cells.

how to close File Stream in C#

Please see this code.
string name = dt.Rows[0]["Name"].ToString();
byte[] documentBytes = (byte[])dt.Rows[0]["DocumentContent"];
int readBytes = 0;
//int index = 0;
readBytes = documentBytes.Length;
try
{
using (FileStream fs = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.Read))
{
fs.Write(documentBytes, 0, readBytes);
//System.Diagnostics.Process prc = new System.Diagnostics.Process();
//prc.StartInfo.FileName = fs.Name;
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Open(fs.Name);
Microsoft.Office.Interop.Excel._Worksheet worksheet = (Excel.Worksheet)workbook.Sheets[1]; // Explicit cast is not required here
// lastRow = worksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row;
app.Visible = true;
fs.Flush();
fs.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("You have clicked more than one time. File is already open.", "WorkFlow", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
I am opening an excel file using the file stream. Excel is showing up nicely. But I am not able to close file stream. It still comes with a small pop up that shows 'File Now available'. How to get rid of that? I can see fs.Close() and Flush() really not working here. Please help.
You're asking Excel to open the file while you still have the stream open. Given that you're just trying to write bytes to it, I'd just use:
// This will close the file handle after writing the data
File.WriteAllBytes(name, documentBytes);
// Then you're fine to get Excel to open it
var app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
var workbook = app.Workbooks.Open(name);

Read Excel using NPOI

I am trying to read excel[xls and xlsx] using NPOI,I am using following code, but it is giving 'Unable to Read entire header; 27 bytes Read; expected 512 bytes' while reading an 8KB xls file
byte[] byteArray = Encoding.UTF8.GetBytes(filepath);
MemoryStream stream = new MemoryStream(byteArray);
MemoryStream stream1 = new MemoryStream(Encoding.UTF8.GetBytes(filepath ?? ""));
NPOI.HSSF.UserModel.HSSFWorkbook hssfwb = default(HSSFWorkbook);
hssfwb = new NPOI.HSSF.UserModel.HSSFWorkbook(stream1);
Sheet sheet = hssfwb.GetSheetAt(0);
DataTable dtinputExcel = new DataTable();
I have tried every possible code available on net for this error. Please guide me what's the errorless method to read and excel[xls/xlsx] of any size.
The problem is that the constructor of HSSFWorkbook is expecting a stream containing the contents of the spreadsheet file, while you are passing it a MemoryStream containing the name of the file. You should be using a FileStream to read the file and passing that stream to the HSSFWorkbook constructor.
Try it like this:
IWorkbook hssfwb;
using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
{
hssfwb = new HSSFWorkbook(fs);
}
ISheet sheet = hssfwb.GetSheetAt(0);

update existing workbook using epplus C#

I am trying to add new worksheet into existing workbook, code runs fine without any error. But changes are not being updated to the excel file.
Here is my code
string path = "C:\\TestFileSave\\ABC.xlsx";
FileInfo filePath = new FileInfo(path);
if (File.Exists(path))
{
using(ExcelPackage p = new ExcelPackage())
{
using(stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
{
p.Load(stream);
ExcelWorksheet ws = p.Workbook.Worksheets.Add(wsName + wsNumber.ToString());
ws.Cells[1, 1].Value = wsName;
ws.Cells[1, 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
ws.Cells[1, 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
ws.Cells[1, 1].Style.Font.Bold = true;
p.Save();
}
}
}
The stream object is not tied to the package. The only relationship is it copies its bytes in your call to Load afterwards they are separate.
You do not need to even use a stream - better to let the package handle it on its own like this:
var fileinfo = new FileInfo(path);
if (fileinfo.Exists)
{
using (ExcelPackage p = new ExcelPackage(fileinfo))
{
//using (stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
{
//p.Load(stream);
ExcelWorksheet ws = p.Workbook.Worksheets.Add(wsName + wsNumber.ToString());
ws.Cells[1, 1].Value = wsName;
ws.Cells[1, 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
ws.Cells[1, 1].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(184, 204, 228));
ws.Cells[1, 1].Style.Font.Bold = true;
p.Save();
}
}
}
Here I have shown to write data into exiting excel file by creating a new sheet in same file. To answer your question: try using last two lines File.WriteAllBytes instead of p.Save().
string strfilepath = "C:\\Users\\m\\Desktop\\Employeedata.xlsx";
using (ExcelPackage p = new ExcelPackage())
{
using (FileStream stream = new FileStream(strfilepath, FileMode.Open))
{
p.Load(stream);
//deleting worksheet if already present in excel file
var wk = p.Workbook.Worksheets.SingleOrDefault(x => x.Name == "Hola");
if (wk != null) { p.Workbook.Worksheets.Delete(wk); }
p.Workbook.Worksheets.Add("Hola");
p.Workbook.Worksheets.MoveToEnd("Hola");
ExcelWorksheet worksheet = p.Workbook.Worksheets[p.Workbook.Worksheets.Count];
worksheet.InsertRow(5, 2);
worksheet.Cells["A9"].LoadFromDataTable(dt1, true);
// Inserting values in the 5th row
worksheet.Cells["A5"].Value = "12010";
worksheet.Cells["B5"].Value = "Drill";
worksheet.Cells["C5"].Value = 20;
worksheet.Cells["D5"].Value = 8;
// Inserting values in the 6th row
worksheet.Cells["A6"].Value = "12011";
worksheet.Cells["B6"].Value = "Crowbar";
worksheet.Cells["C6"].Value = 7;
worksheet.Cells["D6"].Value = 23.48;
}
//p.Save() ;
Byte[] bin = p.GetAsByteArray();
File.WriteAllBytes(#"C:\Users\m\Desktop\Employeedata.xlsx", bin);
}
I originally got the error code "A disk error occurred during a write operation. (Exception from HRESULT: 0x8003001D (STG_E_WRITEFAULT)) " from using this, but later learned that it was because the existing Excel file that I wanted to modify wasn't fully MS-Excel format compliant. I created thee original excel file in Open office as an .xls file, but EPPlus was not able to read it. When I regenerated this original excel file in Online Excel, everything worked fine.

c# Replace openfileDialog to a none gui stream

I am trying to separate the MIME gui from the code i need. I am almost there just one more gui element i dont know how to replace. This element is the openfiledialog. Here a code snippet.
Program.cs
var sfd = new OpenFileDialog();
sfd.FileName = "C:\\eml\\" + validOutputFilename;
try
{
var writer = new MimeMessageWriter();
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
}
catch (Exception ex)
{
//ignore
// need to log
}
message is an IMessage. A class created to store the information about an eml file. The open file dialog is allowing you to put in the file name with an eml extension and that is all. write.Write expects an IMessage and a stream. Inside writer.Write the file is being written The only part of the file that uses this code is when the file itself is writen at the end and write out any attachments. Here are those code snippets.
*MimeMessageWriter
-the attachment uses it here
var embeddedMessage = attachment.OpenAsMessage();
var messageWriter = new MimeMessageWriter();
var msgStream = new MemoryStream();
messageWriter.Write(embeddedMessage, msgStream);
var messageAttachment = ew DotNetOpenMail.FileAttachment(msgStream.ToArray());
messageAttachment.ContentType = "message/rfc822";
messageAttachment.FileName = filename + ".eml";
outMessage.AddMixedAttachment(messageAttachment);
-write out the file part of the file
using (var sw = new StreamWriter(stream))
sw.Write(outMessage.ToDataString());
I want to replace openFileDialog with something that will allow me to pass the filename to write out file in the MimeMessageWriter
Replace
using (var fs = sfd.OpenFile()) writer.Write(message, fs);
with
string fileName = #"c:\eml\myAttachment.eml";
using ( FileStream fs = new FileStream( fileName, FileMode.CreateNew ) )
{
writer.Write( message, fs )
}
See also: http://msdn.microsoft.com/de-de/library/47ek66wy.aspx

Categories

Resources