I'm Trying to read Excel to DataTable using NPOI.Every thing working fine but only issue is If we have any Column cell is empty in that row it is not reading .In Excel i have 4 row's with (each row have some empty values for cells).
Excel File Image : enter image description here
After Reading That Excel To data table :enter image description here
I want like this in data table
private DataTable GetDataTableFromExcel(String Path)
{
XSSFWorkbook wb;
XSSFSheet sh;
String Sheet_name;
using (var fs = new FileStream(Path, FileMode.Open, FileAccess.Read))
{
wb = new XSSFWorkbook(fs);
Sheet_name = wb.GetSheetAt(0).SheetName; //get first sheet name
}
DataTable DT = new DataTable();
DT.Rows.Clear();
DT.Columns.Clear();
// get sheet
sh = (XSSFSheet)wb.GetSheet(Sheet_name);
int i = 0;
while (sh.GetRow(i) != null)
{
// add neccessary columns
if (DT.Columns.Count < sh.GetRow(i).Cells.Count)
{
for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
{
DT.Columns.Add("", typeof(string));
}
}
// add row
DT.Rows.Add();
// write row value
for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
{
var cell = sh.GetRow(i).GetCell(j);
DT.Rows[i][j] = sh.GetRow(i).GetCell(j);
}
i++;
}
return DT;
}
Plese hlp me.
you may have to try something along this line. its workable code to read the excel using NPOI.
// read the current row data
XSSFRow headerRow = (XSSFRow)sheet.GetRow(0);
// LastCellNum is the number of cells of current rows
int cellCount = headerRow.LastCellNum;
// LastRowNum is the number of rows of current table
int rowCount = sheet.LastRowNum + 1;
bool isBlanKRow = false;
//Start reading data after first row(header row) of excel sheet.
for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)
{
XSSFRow row = (XSSFRow)sheet.GetRow(i);
DataRow dataRow = dt.NewRow();
isBlanKRow = true;
try
{
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (null != row.GetCell(j) && !string.IsNullOrEmpty(row.GetCell(j).ToString()) && !string.IsNullOrWhiteSpace(row.GetCell(j).ToString()))
{
dataRow[j] = row.GetCell(j).ToString();
isBlanKRow = false;
}
}
}
catch (Exception Ex)
{
}
if (!isBlanKRow)
{
dt.Rows.Add(dataRow);
}
}
Related
trying to get a value from a data table, and output its contents to a textbox. seems im nearly there but for some reason studio doesnt like dt.rows[][];
ive seen multiple examples online in this format, but i get error CS002, cannot apply indexing with [] to an expression of type 'DataGridViewRow'.
im trying to locate the current row, and i can figure out the column either by putting an index number or by using the name of the column if that works better.
here is datatable_selectionChanged
private void dt_SelectionChanged(object sender, EventArgs e)
{
int row = dt.CurrentCell.RowIndex;
int col = dt.CurrentCell.ColumnIndex;
textBox1.Text = Convert.ToString(row);
textBox2.Text = Convert.ToString(col);
}
here is my mainform_load
private void mainForm_Load(object sender, EventArgs e)
{
string file = #"C:\Users\User\OneDrive - Motion Controls Robotics, Inc\Desktop\test inventory\TIS.xlsm"; //variable for the Excel File Location
DataTable dt = new DataTable(); //container for our excel data
DataRow row;
try
{
//Create Object for Microsoft.Office.Interop.Excel that will be use to read excel file
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(file);
Microsoft.Office.Interop.Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[1];
Microsoft.Office.Interop.Excel.Range excelRange = excelWorksheet.UsedRange;
int rowCount = excelRange.Rows.Count; //get row count of excel data
int colCount = excelRange.Columns.Count;//number of columns to display
//Get the first Column of excel file which is the Column Name
for (int i = 2; i <= rowCount;)
{
for (int j = 1; j <= colCount; j++)
{
dt.Columns.Add(excelRange.Cells[i, j].Value2.ToString());
}
break;
}
//Get Row Data of Excel
int rowCounter; //This variable is used for row index number
for (int i = 3; i <= rowCount; i++) //Loop for available row of excel data
{
row = dt.NewRow(); //assign new row to DataTable
rowCounter = 0;
for (int j = 1; j <= colCount; j++) //Loop for available column of excel data
{
//check if cell is empty
if (excelRange.Cells[i, j] != null && excelRange.Cells[i, j].Value2 != null)
{
row[rowCounter] = excelRange.Cells[i, j].Value2.ToString();
}
else
{
excelRange.Cells[i, j].value2 = "Empty";
//row[i] = "";
}
rowCounter++;
}
dt.Rows.Add(row); //add row to DataTable
}
this.dt.DataSource = dt; //assign DataTable as Datasource for DataGridview
//close and clean excel process
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(excelWorksheet);
//quit apps
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am trying to Merge more excel document into a single document using NPOI. Here is the code write:``
static void Main(string[] args)
{
DataTable dt = new DataTable();
string[] files = new string[] { #"C:\Users\Ionut\source\repos\ExcelMergeDocument\ExcelMergeDocument\bin\Debug\TAMUExport\Project1\Report3Item.xls",
#"C:\Users\Ionut\source\repos\ExcelMergeDocument\ExcelMergeDocument\bin\Debug\TAMUExport\Project2\Report3Item.xls"};
for (int i = 0; i < files.Length; i++)
{
MergeData(files[i], dt);
}
ExportEasy(dt, finalImagePathReport3full);
}
public static string imagePathReport3full = #"\ResultReport3Item.xls";
public static string finalImagePathReport3full = AssemblyDirectory + imagePathReport3full;
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return System.IO.Path.GetDirectoryName(path);
}
}
private static void MergeData(string path, DataTable dt)
{
XSSFWorkbook workbook = new XSSFWorkbook(path);
XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0);
XSSFRow headerRow = (XSSFRow)sheet.GetRow(0);
int cellCount = headerRow.LastCellNum;
if (dt.Rows.Count == 0)
{
for (int i = headerRow.FirstCellNum; i < cellCount; i++)
{
DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
dt.Columns.Add(column);
}
}
else
{
}
int rowCount = sheet.LastRowNum + 1;
for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)
{
XSSFRow row = (XSSFRow)sheet.GetRow(i);
DataRow dataRow = dt.NewRow();
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
dataRow[j] = row.GetCell(j).ToString();
}
dt.Rows.Add(dataRow);
}
workbook = null;
sheet = null;
}
public static void ExportEasy(DataTable dtSource, string strFileName)
{
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet();
HSSFRow dataRow = (HSSFRow)sheet.CreateRow(0);
foreach (DataColumn column in dtSource.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
}
for (int i = 0; i < dtSource.Rows.Count; i++)
{
dataRow = (HSSFRow)sheet.CreateRow(i + 1);
for (int j = 0; j < dtSource.Columns.Count; j++)
{
dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString());
}
}
using (MemoryStream ms = new MemoryStream())
{
using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
}
}
}
When I am run I have the following error:
ICSharpCode.SharpZipLib.Zip.ZipException: 'Cannot find central
directory'
what did I suppose to do?
NPUI work only with .xlsx extension? I have the only .xls extension for the excel document. But where I run the program with .xlsx extension I have other error :
System.IO.InvalidDataException: 'Zip File is closed'
The both error appear on this line of code :
XSSFWorkbook workbook = new XSSFWorkbook(path);
This is the modified that I do on the code:
private static void MergeData(string path, DataTable dt)
{
// HSSFWorkbook workbook = new HSSFWorkbook(path);
HSSFWorkbook workbook;
using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
{
workbook = new HSSFWorkbook();
}
HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0);
HSSFRow headerRow = (HSSFRow)sheet.GetRow(0);
int cellCount = headerRow.LastCellNum;
if (dt.Rows.Count == 0)
{
for (int i = headerRow.FirstCellNum; i < cellCount; i++)
{
DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
dt.Columns.Add(column);
}
}
else
{
}
int rowCount = sheet.LastRowNum + 1;
for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)
{
HSSFRow row = (HSSFRow)sheet.GetRow(i);
DataRow dataRow = dt.NewRow();
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
dataRow[j] = row.GetCell(j).ToString();
}
dt.Rows.Add(dataRow);
}
workbook = null;
sheet = null;
}
Now at this line of code : `
HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0);
he tell me System.ArgumentOutOfRangeException:
'Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index'.
I read about this error and I know to initializate the index or create one, I tried that too, but no effect. What I do wrong or maybe where suppose to initializate the index?
Rest of the code is the same as the previos panel, only this void I modified to Merge .xls document.
I am finding a running instance of excel and inserting data into one of the worksheets. Everything works, however inserting data is very slow. ~0.25 seconds for each cell.
Is there any way I can make this faster?
I have been looking for an approach that doesn't go cell by cell, but haven't found anything.
My code:
using System;
using System.Data;
using Microsoft.Office.Interop.Excel;
using Application = Microsoft.Office.Interop.Excel.Application;
using DataTable = System.Data.DataTable;
[STAThread]
static void Main()
{
Application xlApp = null;
try
{
xlApp = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
}
catch (Exception)//Excel not open
{
return;
}
xlApp.Visible = true;
var wb = xlApp.ActiveWorkbook;
Worksheet ws = null;
try
{
ws = (Worksheet)wb.Worksheets["SomeSheet"];
}
catch (Exception e)
{
return;
}
if (ws == null)
{
return;
}
var dt = new DataTable();
dt = new DataTable();
dt.Clear();
dt.Columns.Add("Col1");
dt.Columns.Add("Col2");
for (int ii = 0; ii < 20; ii++)
{
DataRow row = dt.NewRow();
row["Col1"] = "xxxx";
row["Col2"] = "yyyy";
dt.Rows.Add(row);
}
//Header
for (int i = 0; i < dt.Columns.Count; i++)
{
ws.Cells[1, i + 1] = dt.Columns[i].ColumnName;
}
//Data
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
ws.Cells[i + 2, j + 1] = dt.Rows[i][j];
}
}
}
Have you tried using a Range? Assigning a Array to the range ensuring the Range and Array are the same length should work.
https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.worksheet.range.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
I am trying to export a database from c# to excel but the first row from the database is not saving in excel.
private void exporttoexcel()
{
Microsoft.Office.Interop.Excel._Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
try
{
worksheet = workbook.ActiveSheet;
worksheet.Name = "ExportedFromDatGrid";
int cellRowIndex = 1;
int cellColumnIndex = 1;
//Loop through each row and read value from each column.
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
// Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
if (cellRowIndex == 1)
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Columns[j].HeaderText;
}
else
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
cellColumnIndex++;
}
cellColumnIndex = 1;
cellRowIndex++;
}
}
catch(Exception ex)
{
}
}
here is the code I'm using. could anyone help me ? I am new in coding.
You're not writing out the data but are only writing out column names when the cellColumnIndex is 1, skipping the first row. But after the first row has been processed, the row index will be incremented. Refactor your for-loop to look something like this:
// Add the column names
var index = 0;
foreach(var column in dataGridView1.Columns)
{
worksheet.Cells[0, index] = column.HeaderText;
index++;
}
//Loop through each row and read value from each column.
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
// Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Rows[i].Cells[j].Value.ToString();
cellColumnIndex++;
}
cellColumnIndex = 1;
cellRowIndex++;
}
Please have a look at ClosedXML. It simplifies writing your code, and eliminate the need to have Excel installed on the machine where you want to run this.
I am trying to get NPOI to work with ASP.NET (C#) and I want to read an excel file and put it in a DataSet. Here is the code I attempted:
public static DataTable getExcelData(string FileName, string strSheetName)
{
DataTable dt = new DataTable();
HSSFWorkbook hssfworkbook;
using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
hssfworkbook = new HSSFWorkbook(file);
}
ISheet sheet = hssfworkbook.GetSheet(strSheetName);
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
while (rows.MoveNext())
{
IRow row = (HSSFRow)rows.Current;
if (dt.Columns.Count == 0)
{
for (int j = 0; j < row.LastCellNum; j++)
{
dt.Columns.Add(row.GetCell(j).ToString());
}
continue;
}
DataRow dr = dt.NewRow();
for (int i = 0; i < row.LastCellNum; i++)
{
ICell cell = row.GetCell(i);
if (cell == null)
{
dr[i] = null;
}
else
{
dr[i] = cell.ToString();
}
}
dt.Rows.Add(dr);
}
return dt;
}
The Error that I get is
+ $exception {"Object reference not set to an instance of an object."} System.Exception {System.NullReferenceException}
The odd thing is that this actually works with 2 excel files that I have, but when I put in a third one it crashes with that error.
This returns null if strSheetName isn't found:
ISheet sheet = hssfworkbook.GetSheet(strSheetName);
try:
for( int iSheet = 0; iSheet < hssfworkbook.NumberOfSheets; ++iSheet )
{
ISheet sheet = hssfworkbook.GetSheetAt(iSheet); // could cast to HSSFSheet
String strSheetNameActual = sheet.SheetName;
}
Then figure out how you want to compare strSheetName to strSheetNameActual or which sheets you want to process and how.
Try using this:
for (int j = row.FirstCellNum; j < row.LastCellNum; j++)
and
for (int i = row.FirstCellNum; i < row.LastCellNum; i++)
Instead of:
for (int j = 0; j < row.LastCellNum; j++)
and
for (int i = 0; i < row.LastCellNum; i++)
Also, make sure that you manage the case when the cells on the first row are null:
if (dt.Columns.Count == 0)
{
int empty = 0;
for (int j = row.FirstCellNum; j < row.LastCellNum; j++)
{
ICell cell = row.GetCell(j);
if (cell == null)
{
dt.Columns.Add(String.Format("emptyColumnName_{0}", empty++));
}
else
{
dt.Columns.Add(row.GetCell(j).ToString());
}
}
continue;
}
If you always want to read from the first sheet (probably, to get rid of the second method parameter, the sheet name, which is also the cause of your error), you may use:
// rest of the method's code
ISheet sheet = hssfworkbook.GetSheetAt(0);
if (sheet == null)
return dt;
var rows = sheet.GetRowEnumerator();
// rest of the method's code