How can I get content of the Active sheet or the default sheet of an .xlsx workbook? I have to read many workbooks and I do not know the name of the Active sheets.
FileStream stream = File.Open("C:\\test\\test.xlsx", FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
excelReader.IsFirstRowAsColumnNames = true;
while (excelReader.Read()) {
Console.WriteLine(excelReader.GetString(0));
}
I know how to do it using OfficeOpenXml but ExcelDataReader is lightweight and AsDataSet makes it very easy to turn excel data into JSON.
Using (var pck = new OfficeOpenXml.ExcelPackage()) {
using (var stream = System.IO.File.OpenRead(path))
{
pck.Load(stream);
}
var ws = pck.Workbook.Worksheets.FirstOrDefault(f => f.View.TabSelected);
string ActiveSheetName = ws.Name;
}
Any help here is highly appreciated!
Related
I use NPOI 2.6.0-rc-3 with .net framework 4.8.1 for updating .xlsx file. Excel file includes charts with it. excel file get crashed and after saving. After recovering the same file it losses charts in excel.
Used the following code.
XSSFWorkbook wb1 = null;
using (var file = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
wb1 = new XSSFWorkbook(file);
file.Close();
//Updated the cell values here
using (var file2 = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
{
wb1.Write(file2);
file2.Close();
}
}
Please help regrading this matter
Try to modify the cells out of the using block (you dont need to keep the file open to modify the IWorkbook) and then save it using a diferent stream:
IWorkbook wb1 = null;
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
wb1 = new XSSFWorkbook(file);
}
//Updated the cell values here
using (FileStream fileWrite = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
wb1.Write(fileWrite);
}
I made a program for splitting a cell into two cells and write them in a different sheets but after I run it the excel file gets corrupted.
IWorkbook workbook;
using(FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
workbook = new XSSFWorkbook(stream);
}
IWorkbook newWorkbook = new XSSFWorkbook();
ISheet sheet = workbook.GetSheetAt(0);
ISheet oneWordSheet = newWorkbook.CreateSheet();
ISheet moreWordsSheet = newWorkbook.CreateSheet();
IRow tmpRow;
for(int i = 5; i < 100/*sheet.LastRowNum*/ + 1; i++)
{
tmpRow = sheet.GetRow(i);
string[] strings = tmpRow.GetCell(2).StringCellValue.Split(' ');
string companyName = strings[0];
bool parseFailed = true;
for(int j = 1; parseFailed && j < strings.Length; j++)
{
try
{
int.Parse(strings[j]);
parseFailed = false;
}
catch (FormatException)
{
companyName += strings[j];
j++;
}
}
tmpRow.CreateCell(4).SetCellValue(companyName);
if(companyName.Trim().Split(' ').Length < 2)
{
copyRowToSheet(tmpRow, oneWordSheet);
}
else
{
copyRowToSheet(tmpRow, moreWordsSheet);
}
}
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Write))
{
newWorkbook.Write(stream);
}
I made a copyRowToSheet method like this. It should be correct
private static void copyRowToSheet(IRow row, ISheet sheet)
{
IRow newRow = sheet.CreateRow(sheet.LastRowNum + 1);
newRow.CreateCell(0).SetCellValue(row.GetCell(0).NumericCellValue);
newRow.CreateCell(1).SetCellValue(row.GetCell(1).StringCellValue);
newRow.CreateCell(2).SetCellValue(row.GetCell(4).StringCellValue);
newRow.CreateCell(3).SetCellValue(row.GetCell(2).StringCellValue);
newRow.CreateCell(4).SetCellValue(row.GetCell(3).StringCellValue);
}
I tried writing from workbook instead of newWorkbook, but it still corrupts the file, I also tried removing copyRowToSheet method (just leaving both the if and else case empty but the result doesn't change...
Edit:
I tried removing the whole body of the program leaving just this:
IWorkbook workbook;
using(FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
workbook = new XSSFWorkbook(stream);
stream.Close();
}
IWorkbook newWorkbook = new XSSFWorkbook();
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Write))
{
workbook.Write(stream);
stream.Close();
}
If I'm not wrong this should only read the file and then save it back without editing anything, but it still corrupts the file
I hit the same issue myself a couple of weeks ago when i was starting out with npoi. Quite a tricky one to diagnose as the code you are using is repeated time and again in tutorials and blogs.
The problem occurs when you are creating your second FileStream to write back the spreadsheet to disk. You are writing to the same file that you read earlier.
The behavour of FileMode.Open when writing to an existing file is to append the data to the end of the file. This results in you having 2 excel spreadsheets in a single file which when you open it is declared corrupt.
FileMode.Create on the other hand will overwrite an existing file so this is more likely to be what you need.
using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write))
{
workbook.Write(stream);
stream.Close();
}
Here's the docs file FileMode as there are alternates to Create that you may prefer.
Doc for FileMode
I have an application that have to read excel and convert it to array. So far so good. Everything works file until I try to convert a larger file. I try OpenXML and try SAX approach:
using (SpreadsheetDocument xlsx = SpreadsheetDocument.Open(filePath, false))
{
WorkbookPart workbookPart = xlsx.WorkbookPart;
List<List<string>> parsedContent = new List<List<string>>();
foreach (WorksheetPart worksheet in workbookPart.WorksheetParts)
{
OpenXmlReader xlsxReader = OpenXmlReader.Create(worksheet);
while (xlsxReader.Read())
{
}
}
}
This is working well for files in range 1 - 10MB. My problem is when I try to load 10+ MB file. The result is OutOfMemoryException. How to proper read that big chunk of data? How to do it memory efficient?
P.s. I try libraries like ClosedXML, EPPlus and few others.
Every solution will be appreciated. Thank you in advance
If you plan on only performing a read on the excel file content, I suggest you use the ExcelDataReader library instead Link, which extracts the worksheetData into a DataSet object.
IExcelDataReader reader = null;
string FilePath = "PathToExcelFile";
//Load file into a stream
FileStream stream = File.Open(FilePath, FileMode.Open, FileAccess.Read);
//Must check file extension to adjust the reader to the excel file type
if (Path.GetExtension(FilePath).Equals(".xls"))
reader = ExcelReaderFactory.CreateBinaryReader(stream);
else if (Path.GetExtension(FilePath).Equals(".xlsx"))
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
if (reader != null)
{
//Fill DataSet
DataSet content = reader.AsDataSet();
//Read....
}
Use ExcelDataReader. It is easy to install through Nuget and should only require a few lines of code:
Nuget:
Install-Package ExcelDataReader
Usage:
using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream))
{
DataSet result = excelReader.AsDataSet();
foreach (DataRow dr in result[0])
{
//Do stuff
}
}
}
I need to copy a sheet from one workbook to another. I am trying with the below code, but it is not working:
ISheet newSheet = wb.GetSheetAt(0).CopySheet("WeeklyReport");
string filePath = "billing_template2.xlsx";
XSSFWorkbook billingWorkbook;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
billingWorkbook = new XSSFWorkbook(fs);
}
billingWorkbook.Add(newSheet);
where wb is the source workbook and billingWorkbook is my destination workbook.
Note: My destination workbook already had a sheet. I need to add the copied sheet after this one.
i have an excel file named test.xls and i want to get the contents in the excel sheet into a Dataset.Is it possible
i tried a code but it throws exception,here is my code
string FilePath = Server.MapPath("portals\\_default") + "\\" + upprice.FileName;
upprice.PostedFile.SaveAs(FilePath);
FileStream stream = File.Open(FilePath, FileMode.Open, FileAccess.Read);
if (upprice.FileName.Contains(".xlsx"))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
DataSet result = excelReader.AsDataSet();
}
I'm going to assume you're using this http://exceldatareader.codeplex.com/
From your code:
if (upprice.FileName.Contains(".xlsx"))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
DataSet result = excelReader.AsDataSet();
}
else if (upprice.FileName.Contains(".xls"))
{
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
}
these tests are backwards. ".xlsx" files are zipped xml documents. "xls" are the older binary files. Also consider using System.IO.Path.GetExtension() to get the file extension since you'll notice Contains(".xls") is true for both file types.