How to specify 6 columns and name them in datagridview so that when I import an excel sheet with missing columns it adds the missing columns. I need to keep the content empty and arrange the columns based on what I specify in datagridview. Note: column name does not change.
For example, I specify columns A,B,C,D in datagridview and the excel sheet has the same column names, but some of them are missing, for example (A,C)
This is what I did to import excel sheet into the application:
namespace excelreaderdesktop
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fil = new OpenFileDialog();
fil.ShowDialog();
string path = fil.FileName.ToString();
ExcelFileReader(path);
}
public void ExcelFileReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
foreach(DataTable table in tables)
{
dataGridView1.DataSource = table;
}
}
}
}
Hello and welcome to Stackoverfow,
if I have understand your question correct, look wich columns are exist in the dataGridView1 and check them against the excel file in the excel-file.
Example:
// create an exapmle DataTabel (in your case your tables from the excel-file)
// The excel-file has the columns B and D
DataTable table = new DataTable();
table.Columns.Add("B");
table.Columns.Add("D");
// loop over the columns in the dataGridView1
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
// xheck whether the column exists in the table, otherwise add it.
if (!table.Columns.Contains(column.Name))
{
table.Columns.Add(column.Name);
}
}
// clear old columns from dataGridView1
dataGridView1.Columns.Clear();
// update dataGridView1
dataGridView1.DataSource = dt;
Hoppefully this helps you.
//Need to update Excel sheet columns while retrieving data from data table enter code here
foreach (DataRow datarow in dt.Rows)
{
int[] colNumber = new int[] { 9,5,13,24,111,17,76,34,38 };
rowcount += 1;
for (int i = 0; i < colNumber.Length; i++)
{ string value = datarow[i].ToString();
ws.Cells[rowcount, colNumber[i]] = value;
}
}
The problem will not be solved by using EntityFramework as I'm afraid you are focusing on the wrong area. The main reason for this delay is that you are trying to access the worksheet object for each record in dt.Rows.
I recommend using GemBox.Spreadsheet for this purpose. You can directly attach the datatable to the worksheet. Also, you don't need to explicitly convert values to string.
----------
// Code sample.
private void Download()
{
DataTable datatable=yourDatatable;// callStore Procedure to fetch DataTable
ExcelFile csvFile = new ExcelFile();//GemBox.Spreadsheet ExcelFile
ExcelWorksheet ws = csvFile.Worksheets.Add("YourWorkSheetName");
if (ws != null)
{
ws.InsertDataTable(datatable, 0, 0, true);
// Use MemoryStream to save or to send it to client as response.
}
}
----------
I have some C# code to import Excel into a database, but it can only import data from the first sheet (Sheet1) into the SQL Server database. I want to import data from the second sheet (Sheet2) of Excel file into the database. Please modify the code to teach me how to do that.
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ope = new OpenFileDialog();
ope.Filter = "Excel Files|*.xls;*.xlsx;*slsm";
if (ope.ShowDialog() == DialogResult.Cancel)
return;
FileStream stream = new FileStream(ope.FileName, FileMode.Open);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
DataClasses1DataContext conn = new DataClasses1DataContext();
foreach(DataTable table in result.Tables)
{
//Default start value of foreach statement is 0
//Please tell me: How to count dr from 1 instead of 0???
foreach (DataRow dr in table.Rows)
{
//if index of dr==1, then continue
if (table.Rows.IndexOf(dr) == 0)
{
continue;
}
test addtable = new test()
{
id = Convert.ToInt32(dr[0]),
name = Convert.ToString(dr[1]),
surname = Convert.ToString(dr[2]),
age = Convert.ToInt32(dr[3])
};
conn.tests.InsertOnSubmit(addtable);
}
}
conn.SubmitChanges();
excelReader.Close();
stream.Close();
MessageBox.Show("Import table completed!");
}
Assuming you are looking to get the data from the spreadsheet Sheet2, this should work :
DataSet result = excelReader.AsDataSet();
while (excelReader.NextResult())
{
if (excelReader.Name == "Sheet2")
{
result = excelReader.AsDataSet();
break;
}
}
Following code works for me to generate only single excel file and single sheet in that.
I want to generate separate sheets for every CustomerOrders how can I do it?
List<MyData> Data = //code to get list of data
DataTable reportDataTable = new DataTable();
reportDataTable.Columns.Add("no");
reportDataTable.Columns.Add("Code");
int count =0
if (Data != null)
{
foreach (MyData dataobj in Data)
{
count++;
foreach (var innerdata in dataobj.CustomerData.OrderBy(t => t.Number))
{
foreach (var orderobj in dataobj.CustomerOrders)
{
DataRow row = reportDataTable.NewRow();
row[0] = "No";
row[1] = "Code"+count;
reportDataTable.Rows.Add(row);
}
}
}
}
GridView grid = new GridView();
grid.DataSource = reportDataTable;
grid.DataBind();
return new DownloadFileResult(grid, "MYEXCELFILE.xls");
public DownloadFileResult(GridView gv, string FileName)
{
GridView = gv; // property
fileName = FileName; //property
}
How do I generate those multiple sheets in one MYEXCELFILE.xls file?
For above i have used following link code
http://www.codeproject.com/Articles/325103/MVC-Grid-to-Excel-file-download
Try this source code:
//Create an instance of the object that generates the Excel file
ExcelDocument xls = new ExcelDocument();
//Loop for each CustomerOrders
{
//Add an worksheet for each CustomerOrders sheet
ExcelWorksheet xlsSheet = new ExcelWorksheet();
xlsSheet.setSheetName("CustomerOrders #no");
xls.easy_addWorksheet(xlsSheet);
//Create a dataset that contains the gridview datatable
DataSet dataSet = new DataSet();
dataSet.Tables.Add((DataTable)gridView.DataSource);
//Add the datatable
xlsSheet.easy_insertDataSet(dataSet, "A1", true);
}
//Export Excel file
xls.easy_WriteXLSFile("MYEXCELFILE.xls ");
For formatting the cells see this link:
http://www.easyxls.com/manual/FAQ/export-gridview-to-excel.html
This code uses EasyXLS library for generating Excel files.
I know that there are different ways to read an Excel file:
Iterop
Oledb
Open Xml SDK
Compatibility is not a question because the program will be executed in a controlled environment.
My Requirement :
Read a file to a DataTable / CUstom Entities (I don't know how to make dynamic properties/fields to an object[column names will be variating in an Excel file])
Use DataTable/Custom Entities to perform some operations using its data.
Update DataTable with the results of the operations
Write it back to excel file.
Which would be simpler.
Also if possible advice me on custom Entities (adding properties/fields to an object dynamically)
Take a look at Linq-to-Excel. It's pretty neat.
var book = new LinqToExcel.ExcelQueryFactory(#"File.xlsx");
var query =
from row in book.Worksheet("Stock Entry")
let item = new
{
Code = row["Code"].Cast<string>(),
Supplier = row["Supplier"].Cast<string>(),
Ref = row["Ref"].Cast<string>(),
}
where item.Supplier == "Walmart"
select item;
It also allows for strongly-typed row access too.
I realize this question was asked nearly 7 years ago but it's still a top Google search result for certain keywords regarding importing excel data with C#, so I wanted to provide an alternative based on some recent tech developments.
Importing Excel data has become such a common task to my everyday duties, that I've streamlined the process and documented the method on my blog: best way to read excel file in c#.
I use NPOI because it can read/write Excel files without Microsoft Office installed and it doesn't use COM+ or any interops. That means it can work in the cloud!
But the real magic comes from pairing up with NPOI Mapper from Donny Tian because it allows me to map the Excel columns to properties in my C# classes without writing any code. It's beautiful.
Here is the basic idea:
I create a .net class that matches/maps the Excel columns I'm interested in:
class CustomExcelFormat
{
[Column("District")]
public int District { get; set; }
[Column("DM")]
public string FullName { get; set; }
[Column("Email Address")]
public string EmailAddress { get; set; }
[Column("Username")]
public string Username { get; set; }
public string FirstName
{
get
{
return Username.Split('.')[0];
}
}
public string LastName
{
get
{
return Username.Split('.')[1];
}
}
}
Notice, it allows me to map based on column name if I want to!
Then when I process the excel file all I need to do is something like this:
public void Execute(string localPath, int sheetIndex)
{
IWorkbook workbook;
using (FileStream file = new FileStream(localPath, FileMode.Open, FileAccess.Read))
{
workbook = WorkbookFactory.Create(file);
}
var importer = new Mapper(workbook);
var items = importer.Take<CustomExcelFormat>(sheetIndex);
foreach(var item in items)
{
var row = item.Value;
if (string.IsNullOrEmpty(row.EmailAddress))
continue;
UpdateUser(row);
}
DataContext.SaveChanges();
}
Now, admittedly, my code does not modify the Excel file itself. I am instead saving the data to a database using Entity Framework (that's why you see "UpdateUser" and "SaveChanges" in my example). But there is already a good discussion on SO about how to save/modify a file using NPOI.
Using OLE Query, it's quite simple (e.g. sheetName is Sheet1):
DataTable LoadWorksheetInDataTable(string fileName, string sheetName)
{
DataTable sheetData = new DataTable();
using (OleDbConnection conn = this.returnConnection(fileName))
{
conn.Open();
// retrieve the data using data adapter
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [" + sheetName + "$]", conn);
sheetAdapter.Fill(sheetData);
conn.Close();
}
return sheetData;
}
private OleDbConnection returnConnection(string fileName)
{
return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + "; Jet OLEDB:Engine Type=5;Extended Properties=\"Excel 8.0;\"");
}
For newer Excel versions:
return new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=Excel 12.0;");
You can also use Excel Data Reader an open source project on CodePlex. Its works really well to export data from Excel sheets.
The sample code given on the link specified:
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//...
//4. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
//5. Data Reader methods
while (excelReader.Read())
{
//excelReader.GetInt32(0);
}
//6. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
Reference: How do I import from Excel to a DataSet using Microsoft.Office.Interop.Excel?
Try to use this free way to this, https://freenetexcel.codeplex.com
Workbook workbook = new Workbook();
workbook.LoadFromFile(#"..\..\parts.xls",ExcelVersion.Version97to2003);
//Initialize worksheet
Worksheet sheet = workbook.Worksheets[0];
DataTable dataTable = sheet.ExportDataTable();
If you can restrict it to just (Open Office XML format) *.xlsx files, then probably the most popular library would be EPPLus.
Bonus is, there are no other dependencies. Just install using nuget:
Install-Package EPPlus
Try to use Aspose.cells library (not free, but trial is enough to read), it is quite good
Install-package Aspose.cells
There is sample code:
using Aspose.Cells;
using System;
namespace ExcelReader
{
class Program
{
static void Main(string[] args)
{
// Replace path for your file
readXLS(#"C:\MyExcelFile.xls"); // or "*.xlsx"
Console.ReadKey();
}
public static void readXLS(string PathToMyExcel)
{
//Open your template file.
Workbook wb = new Workbook(PathToMyExcel);
//Get the first worksheet.
Worksheet worksheet = wb.Worksheets[0];
//Get cells
Cells cells = worksheet.Cells;
// Get row and column count
int rowCount = cells.MaxDataRow;
int columnCount = cells.MaxDataColumn;
// Current cell value
string strCell = "";
Console.WriteLine(String.Format("rowCount={0}, columnCount={1}", rowCount, columnCount));
for (int row = 0; row <= rowCount; row++) // Numeration starts from 0 to MaxDataRow
{
for (int column = 0; column <= columnCount; column++) // Numeration starts from 0 to MaxDataColumn
{
strCell = "";
strCell = Convert.ToString(cells[row, column].Value);
if (String.IsNullOrEmpty(strCell))
{
continue;
}
else
{
// Do your staff here
Console.WriteLine(strCell);
}
}
}
}
}
}
Read from excel, modify and write back
/// <summary>
/// /Reads an excel file and converts it into dataset with each sheet as each table of the dataset
/// </summary>
/// <param name="filename"></param>
/// <param name="headers">If set to true the first row will be considered as headers</param>
/// <returns></returns>
public DataSet Import(string filename, bool headers = true)
{
var _xl = new Excel.Application();
var wb = _xl.Workbooks.Open(filename);
var sheets = wb.Sheets;
DataSet dataSet = null;
if (sheets != null && sheets.Count != 0)
{
dataSet = new DataSet();
foreach (var item in sheets)
{
var sheet = (Excel.Worksheet)item;
DataTable dt = null;
if (sheet != null)
{
dt = new DataTable();
var ColumnCount = ((Excel.Range)sheet.UsedRange.Rows[1, Type.Missing]).Columns.Count;
var rowCount = ((Excel.Range)sheet.UsedRange.Columns[1, Type.Missing]).Rows.Count;
for (int j = 0; j < ColumnCount; j++)
{
var cell = (Excel.Range)sheet.Cells[1, j + 1];
var column = new DataColumn(headers ? cell.Value : string.Empty);
dt.Columns.Add(column);
}
for (int i = 0; i < rowCount; i++)
{
var r = dt.NewRow();
for (int j = 0; j < ColumnCount; j++)
{
var cell = (Excel.Range)sheet.Cells[i + 1 + (headers ? 1 : 0), j + 1];
r[j] = cell.Value;
}
dt.Rows.Add(r);
}
}
dataSet.Tables.Add(dt);
}
}
_xl.Quit();
return dataSet;
}
public string Export(DataTable dt, bool headers = false)
{
var wb = _xl.Workbooks.Add();
var sheet = (Excel.Worksheet)wb.ActiveSheet;
//process columns
for (int i = 0; i < dt.Columns.Count; i++)
{
var col = dt.Columns[i];
//added columns to the top of sheet
var currentCell = (Excel.Range)sheet.Cells[1, i + 1];
currentCell.Value = col.ToString();
currentCell.Font.Bold = true;
//process rows
for (int j = 0; j < dt.Rows.Count; j++)
{
var row = dt.Rows[j];
//added rows to sheet
var cell = (Excel.Range)sheet.Cells[j + 1 + 1, i + 1];
cell.Value = row[i];
}
currentCell.EntireColumn.AutoFit();
}
var fileName="{somepath/somefile.xlsx}";
wb.SaveCopyAs(fileName);
_xl.Quit();
return fileName;
}
I used Office's NuGet Package: DocumentFormat.OpenXml and pieced together the code from that component's doc site.
With the below helper code, was similar in complexity to my other CSV file format parsing in that project...
public static async Task ImportXLSX(Stream stream, string sheetName) {
{
// This was necessary for my Blazor project, which used a BrowserFileStream object
MemoryStream ms = new MemoryStream();
await stream.CopyToAsync(ms);
using (var document = SpreadsheetDocument.Open(ms, false))
{
// Retrieve a reference to the workbook part.
WorkbookPart wbPart = document.WorkbookPart;
// Find the sheet with the supplied name, and then use that
// Sheet object to retrieve a reference to the first worksheet.
Sheet theSheet = wbPart?.Workbook.Descendants<Sheet>().Where(s => s?.Name == sheetName).FirstOrDefault();
// Throw an exception if there is no sheet.
if (theSheet == null)
{
throw new ArgumentException("sheetName");
}
WorksheetPart wsPart = (WorksheetPart)(wbPart.GetPartById(theSheet.Id));
// For shared strings, look up the value in the
// shared strings table.
var stringTable =
wbPart.GetPartsOfType<SharedStringTablePart>()
.FirstOrDefault();
// I needed to grab 4 cells from each row
// Starting at row 11, until the cell in column A is blank
int row = 11;
while (true) {
var accountNameCell = GetCell(wsPart, "A" + row.ToString());
var accountName = GetValue(accountNameCell, stringTable);
if (string.IsNullOrEmpty(accountName)) {
break;
}
var investmentNameCell = GetCell(wsPart, "B" + row.ToString());
var investmentName = GetValue(investmentNameCell, stringTable);
var symbolCell = GetCell(wsPart, "D" + row.ToString());
var symbol = GetValue(symbolCell, stringTable);
var marketValue = GetCell(wsPart, "J" + row.ToString()).InnerText;
// DO STUFF with data
row++;
}
}
}
private static string? GetValue(Cell cell, SharedStringTablePart stringTable) {
try {
return stringTable.SharedStringTable.ElementAt(int.Parse(cell.InnerText)).InnerText;
} catch (Exception) {
return null;
}
}
private static Cell GetCell(WorksheetPart wsPart, string cellReference) {
return wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference.Value == cellReference)?.FirstOrDefault();
}