I'm trying to take XLSX data and putting it into an DataGridView using the ExcelDataReader NuGet package. But i get a Object reference not set to an instance of an object error on line 35
foreach (DataTable dt in result.Tables)
Here is the full code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
using Excel;
namespace MyForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
DataSet result;
private void butOpen_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == DialogResult.OK)
{
FileStream fs = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = ExcelReaderFactory.CreateBinaryReader(fs);
reader.IsFirstRowAsColumnNames = true;
result = reader.AsDataSet();
cboSheet.Items.Clear();
foreach (DataTable dt in result.Tables)
cboSheet.Items.Add(dt.TableName);
reader.Close();
}
}
}
private void cboSheet_SelectedIndexChanged(object sender, EventArgs e)
{
dataGridView.DataSource = result.Tables[cboSheet.SelectedIndex];
}
}
}
Here is the error message: Error
In response to the comments:
The property IsFirstRowAsColumnNames
is no longer available on newer versions of the package.
From the GitHub page LINK :
AsDataSet configuration options
The AsDataSet() function accepts an optional configuration object to modify the behavior of the DataSet conversion:
var result = reader.AsDataSet(new ExcelDataSetConfiguration() {
// Gets or sets a value indicating whether to set the DataColumn.DataType
// property in a second pass.
UseColumnDataType = true,
// Gets or sets a callback to obtain configuration options for a DataTable.
ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration() {
// Gets or sets a value indicating the prefix of generated column names.
EmptyColumnNamePrefix = "Column",
// Gets or sets a value indicating whether to use a row from the
// data as column names.
UseHeaderRow = false,
// Gets or sets a callback to determine which row is the header row.
// Only called when UseHeaderRow = true.
ReadHeaderRow = (rowReader) => {
// F.ex skip the first row and use the 2nd row as column headers:
rowReader.Read();
}
}
});
I'm guessing that the line UseHeaderRow = true;
in the ExcelDataTAbleConfiguration
would result in the wanted behavior.
EDIT: Add working example
This example works for me with a new .xlsx file created in Excel 2016. The file contains two sheets: Sheet 1 and Sheet 2. Both contain two columns with two rows of text.
List<string> tblNames = new List<string>();
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() ?? false)
{
using (FileStream fs = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (IExcelDataReader reader = ExcelReaderFactory.CreateReader(fs))
{
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
UseColumnDataType = true,
ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
foreach (DataTable dt in result.Tables)
tblNames.Add(dt.TableName);
}
}
}
This is a WPF application, so the usage of OpenFileDialog
looks a bit different.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.