Does NPOI have support to .xlsx format? - c#

Will NPOI DLL recognize .xlsx file?
Currently I'm using NPOI 1.2.5 version DLL for Microsoft Excel 97-2003, but I need to access Excel sheets of extension .xlsx also.
Will NPOI support the above?
Code snippet:
static void Main(string[] args) {
XSSFWorkbook xssfwb;
using(FileStream file=new FileStream(
#"C:\Users\347702\Desktop\Hello.xlsx",
FileMode.Open, FileAccess.Read)) {
xssfwb=new XSSFWorkbook(file);
}
ISheet sheet=xssfwb.GetSheet("sheet1");
sheet.GetRow(1048576);
Console.WriteLine(sheet.GetRow(1048576).GetCell(0).StringCellValue);
}

You can read Excel files in .xls and .xlsx extensions with NPOI, you only need to add the next in the using section
using NPOI.HSSF.UserModel;
using NPOI.HPSF;
using NPOI.POIFS.FileSystem;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;
The main thing is at the time you open the file, you have to distinguish between the extensions so you use the appropiate componente, and use an ISheet interface so you can reference the sheet independently of the file extension
//We get the file extension
fileExt = Path.GetExtension(fileName);
//Declare the sheet interface
ISheet sheet;
//Get the Excel file according to the extension
if (fileExt.ToLower() == ".xls")
{
//Use the NPOI Excel xls object
HSSFWorkbook hssfwb;
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
hssfwb = new HSSFWorkbook(file);
}
//Assign the sheet
sheet = hssfwb.GetSheet(sheetName);
}
else //.xlsx extension
{
//Use the NPOI Excel xlsx object
XSSFWorkbook hssfwb;
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
hssfwb = new XSSFWorkbook(file);
}
//Assign the sheet
sheet = hssfwb.GetSheet(sheetName);
}
Once you have the excel object you only need to read it (in NPOI rows and columns are zero based)
//Loop through the rows until we find an empty one
for (int row = 0; row <= sheet.LastRowNum; row++)
{
//Get the cell value
string cellValue = sheet.GetRow(row).GetCell(0).ToString().Trim(); //In the method GetCell you specify the column number you want to read, in the method GetRow you spacify the row
string cellValue2 = sheet.GetRow(row).GetCell(0).StringCellValue.Trim();
}
To read the cell valur you can use the .ToString() method or the StringCellValue property, but be careful the StringCellValue only works with string cells, with number and date cells it throws an exception.

Yes it does. NPOI 2.0 beta works. Here's a sample code to get you started:
class Program
{
static XSSFWorkbook hssfworkbook;
static DataSet dataSet1 = new DataSet();
static void Main(string[] args)
{
InitializeWorkbook(#"E:\Docs\HoursWidget_RTM.xlsx");
xlsxToDT();
DisplayData(dataSet1.Tables[0]);
Console.ReadLine();
}
static void InitializeWorkbook(string path)
{
using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
{
hssfworkbook = new XSSFWorkbook(file);
}
}
static void xlsxToDT()
{
DataTable dt = new DataTable();
ISheet sheet = hssfworkbook.GetSheetAt(1);
IRow headerRow = sheet.GetRow(0);
IEnumerator rows = sheet.GetRowEnumerator();
int colCount = headerRow.LastCellNum;
int rowCount = sheet.LastRowNum;
for (int c = 0; c < colCount; c++)
{
dt.Columns.Add(headerRow.GetCell(c).ToString());
}
bool skipReadingHeaderRow = rows.MoveNext();
while (rows.MoveNext())
{
IRow row = (XSSFRow)rows.Current;
DataRow dr = dt.NewRow();
for (int i = 0; i < colCount; i++)
{
ICell cell = row.GetCell(i);
if (cell != null)
{
dr[i] = cell.ToString();
}
}
dt.Rows.Add(dr);
}
hssfworkbook = null;
sheet = null;
dataSet1.Tables.Add(dt);
}
static void DisplayData(DataTable table)
{
foreach (DataRow row in table.Rows)
{
foreach (DataColumn col in table.Columns)
{
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
}
Console.WriteLine("-------------------------------------------");
}
}
}

May be the library didn't had this feature when the original answer(s) was provided, but now you can handle both xls and xlsx using the same code base without checking for file extensions.
The trick is to use WorkbookFactory class to transparently load both types of files. This will work as long as you are not using special features specific to either version.
using (FileStream fileStream = File.OpenRead(fullPathToExcelFile)) //fullPathToExcelFile can hold either a xls or xlsx, we don't care
{
IWorkbook workbook = WorkbookFactory.Create(fileStream);
ISheet worksheet = workbook.GetSheet("SampleSheet");
//Now read from the worksheet anyway you like
var value = worksheet.GetRow(1).GetCell(1);
}

NPOI 2.0 supports xlsx. You can download it from https://npoi.codeplex.com/releases/view/112932

Related

Get Excel HyperLink Cell String

I'm trying to get the hyperlink string from an Excel cell using the excel data reader library in C#, but retrieving the cell and calling the ToString method didn't work.
This is my code so far:
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)){
using var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
DataTable table = result.Tables[0];
bool jumpCol = true; // Avoid first lane
foreach (DataRow row in table.Rows)
{
if (jumpCol)
{
jumpCol = false;
continue;
}
}
PlateImage = row[6].ToString(); //This returns 0
I just need the hyperlink string:
=HYPERLINK("thisString.jpg")
Any ideas? Any library that allows me to do this?
Install Free Spire.XLS from NuGet:
Install-Package FreeSpire.XLS
Next, you can read the hyperlinks from Excel with the following code:
using Spire.Xls;
using System;
namespace RetrieveHyperlink
{
class Program
{
static void Main(string[] args)
{
Workbook wb = new Workbook();
wb.LoadFromFile(#"C:\Users\Administrator\Desktop\Hyperlinks.xlsx");
Worksheet sheet = wb.Worksheets[0];
foreach (var item in sheet.HyperLinks)
{
string address = item.Address;
CellRange range = item.Range;
Console.WriteLine(string.Format("Cell[{0},{1}] contains URL: {2}", range.Row, range.Column, address));
}
}
}
}
Keep in mind that the free version has a limitation of 5 sheets and 200 rows per sheet for .xls file format.

save excel file to csv format without opening in .net core 3.1

I have a situation where I need to download and save excel file(.xlsx) to .CSV format in .net core console application.
Since, Microsoft.Interop packages are not compatible with .Net core 3.1, what other approach I can use to save Excel file as .CSV?
Appreciate suggestions.
This is a combination of multiple existing answers on SO.
First is from here
Convert the xlsx to a DataTable using ClosedXML
using ClosedXML.Excel;
...
public static DataTable GetDataFromExcel(string path, dynamic worksheet)
{
//Save the uploaded Excel file.
DataTable dt = new DataTable();
//Open the Excel file using ClosedXML.
using (XLWorkbook workBook = new XLWorkbook(path))
{
//Read the first Sheet from Excel file.
IXLWorksheet workSheet = workBook.Worksheet(worksheet);
//Create a new DataTable.
//Loop through the Worksheet rows.
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//Use the first row to add columns to DataTable.
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
if (!string.IsNullOrEmpty(cell.Value.ToString()))
{
dt.Columns.Add(cell.Value.ToString());
}
else
{
break;
}
}
firstRow = false;
}
else
{
int i = 0;
DataRow toInsert = dt.NewRow();
foreach (IXLCell cell in row.Cells(1, dt.Columns.Count))
{
try
{
toInsert[i] = cell.Value.ToString();
}
catch (Exception ex)
{
//Handle this, or don't.
}
i++;
}
dt.Rows.Add(toInsert);
}
}
return dt;
}
If you need to do any data transformations, do it while the data is in a DataTable.
Then use CSVHelper to export as a CSV (SO answer I found had a solution that didn't use the Culture Info which was added as a requirement to the Library a few updates ago):
using CSVHelper;
using System.Globilization;
....
public static void SaveCSV(DataTable records)
{
string newFile = #"C:\somePath.csv";
using (StreamWriter writer = new StreamWriter(newFile))
{
using (CsvWriter csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
//add headers
foreach (DataColumn dc in records.Columns)
{
csv.WriteField(dc.ColumnName);
}
csv.NextRecord();
foreach(DataRow dr in records.Rows)
{
for (int i = 0; i< records.Columns.Count; i++)
{
csv.WriteField(dr[i]);
}
csv.NextRecord();
}
}
}
}

Excel file is corrupted after generating multiple excel files using EPPLUS and Zipped using DotNetZip from an ActionResult in C#

I need to export multiple excel containing data from database. I'm using EPPLUS to do that. Since I can't return multiple file from an ActionResult I've to ZIP the excel files and then return that ZIP file. I've successfully zipped it and downloaded the zip file but when I try to open any excel file in the zip file it says my excel file is corrupted. If there is a single excel file in the zip file it works fine.
Here is my code-
public ActionResult ExportExcel()
{
try
{
projects="project1,project2";
var memoryStream = new MemoryStream();
var zip = new ZipFile();
var arrProject = projects.Split(',');
foreach (var pro in arrProject)
{
var v = GetProjectData(pro);//method to get data from database
//Construct DataTable
var dt = new DataTable();
dt.Columns.Add("Model", typeof(string));
dt.Columns.Add("Color", typeof(string));
dt.Columns.Add("BarCode", typeof(long));
dt.Columns.Add("BarCode2", typeof(long));
//Load data to DataTable
foreach (var item in v)
{
var row = dt.NewRow();
row["Model"] = item.Model;
row["Color"] = item.Color;
row["BarCode"] = Int64.Parse(item.BarCode);
row["BarCode2"] = Int64.Parse(item.BarCode2);
dt.Rows.Add(row);
}
//transfer data from DataTable to worksheet
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("IMEI");
worksheet.Cells["A1"].LoadFromDataTable(dt, PrintHeaders: true);
for (var col = 1; col < dt.Columns.Count + 1; col++)
{
worksheet.Column(col).AutoFit();
}
zip.AddEntry(pro + ".xlsx", package.GetAsByteArray());
zip.Save(memoryStream);
}
}
return File(memoryStream.ToArray(), System.Net.Mime.MediaTypeNames.Application.Zip, "report.zip");
}
catch (Exception ex)
{
}
}
The problem with your code at line zip.Save(memoryStream); which is being saving on each file.
Move that line before return statement would make one zip file containing all files.
Convert to as follows.
zip.Save(memoryStream);
return File(memoryStream.ToArray(), System.Net.Mime.MediaTypeNames.Application.Zip, "report.zip");

Read first line of XLS without specific sheet name

I've found how to read first line from Excel file with specific sheet name, but in my case I have to read first line of the first sheet.
How can I realize that or I have to use CSV instead of XLS?
Did you take a look at the EPPlus library? It makes very easy to work with excel files.
Here is how you would do that using EPPlus:
FileInfo existingFile = new FileInfo("yourfilepathname");
using (var package = new ExcelPackage(existingFile))
{
ExcelWorkbook workbook = package.Workbook;
if (workbook != null && workbook.Worksheets.Count > 0)
{
//Gets the first worksheet. You can use index also to select your worksheet.
ExcelWorksheet worksheet = workbook.Worksheets.First();
int rowIndex = 0;
int colIndex = 0;
//To get the first cell:
var cellValue = worksheet.Cells[rowIndex, colIndex].Value;
//YOU CAN ALSO DO A LOOP TO GET ALL VALUES FROM THE FIRST ROW.
}
}
NPOI is another good option and it can handle XLS files too.
Here's a snippet of NPOI code:
HSSFWorkbook _hssfworkbook = new HSSFWorkbook(OpenFileStream(filePath));
//Getting the sheet
_currentSheet = _hssfworkbook.GetSheetAt(0);
//Getting the row:
_row = CurrentSheet.GetRow(0);
//Getting the cell
_cell = _row.GetCell(0);
Have you considered SpreadsheetLight? Here's how you do it:
SLDocument sl = new SLDocument("YourExcelFile.xlsx", "TheSheetName");
string FirstLine = sl.GetCellValueAsString("A1");
sl.CloseWithoutSaving();
Disclaimer: I wrote SpreadsheetLight.

how to create multiple excel sheets

well i have to creat just one excel file and 2 sheets both are fill using a 2 diferent DataTable, it gives the name the user only has to click save, the next code allows me to seend one datatable to one sheet (i am using C#, asp.net, and NOT using Visual Studio, i am writing in the Notepad my code):
string name2="Centroids";
HttpContext context = HttpContext.Current;
context.Response.Clear();
foreach (System.Data.DataRow row in _myDataTable2.Rows)
{
for (int i = 0; i < _myDataTable2.Columns.Count; i++)
{
context.Response.Write(row[i].ToString().Replace(",", string.Empty) + ",");
}
context.Response.Write(Environment.NewLine);
}
context.Response.ContentType = "text2/csv";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name2 + ".csv");
but i have no idea how to creat the second sheet and use the second DataTable, any ideas of how to find a solution, this way the user has only to save and donwload only one document and not save as many DataTable are in the programa
You probably want to explore the possibility of using EPPlus. In my experience, using Response object has lot of constraints and take too much development effort to generate Excel file.
Url:
http://epplus.codeplex.com/
You should use open source libraries for generating native excel files, there is no way you can create two sheets with csv.
Use NPOI (xls) or / and EPPlus (xlsx) and fully control your excel export, in this answer https://stackoverflow.com/a/9569827/351383 you can see example of creating excel file from DataTable with EPPlus. You can edit that method to accept DataTable list and create new sheets for each table, it's simple, just :
ExcelPackage pack = new ExcelPackage();
ExcelWorksheet ws = pack.Workbook.Worksheets.Add(sheetName);
public bool LlenarExcelxlsx(List<DatosEntidad> listaOrigen)
{
bool exito = false;
string[] tipoLista = { "A", "B", "C" };
string nombreArchivo = #"D:\prueba.xlsx";
IWorkbook wb = new XSSFWorkbook();
using (FileStream fileData = new FileStream(nombreArchivo, FileMode.Create, FileAccess.Write))
{
for (int k = 0; k < tipoLista.Length; k++)
{
List<DatosEntidad> listaDestino = listaOrigen
.Where(c => c.tipo == tipoLista[k]).ToList();
DataTable dt = ToDataTable(listaDestino);
ISheet sheetx = wb.CreateSheet("Res_" + tipoLista[k] + k);
ICreationHelper cH = wb.GetCreationHelper();
for (int i = 0; i < dt.Rows.Count; i++)
{
IRow row = sheetx.CreateRow(i);
for (int j = 0; j < 13; j++)
{
ICell cell = row.CreateCell(j);
cell.SetCellValue(cH.CreateRichTextString(dt.Rows[i].ItemArray[j].ToString()));
}
}
}
wb.Write(fileData);
exito = true;
}
return exito;
}

Categories

Resources