In this example I will show how to read data from excel using C# and how to show it in WPF DataGrid.
In order to work with excel in C# you have to add reference to Microsoft.Office.Interop.Excel library.
As I said before I want also show the excel data in WPF DataGrid, so I created ExcelData class which contains Data property. My DataGrid will be bound to this Data property.
Let's see what we got inside of it:
So instead of DataTable I'm simply returning DefaultView.
Let's now see what we have in XAML:
In order to work with excel in C# you have to add reference to Microsoft.Office.Interop.Excel library.
As I said before I want also show the excel data in WPF DataGrid, so I created ExcelData class which contains Data property. My DataGrid will be bound to this Data property.
Let's see what we got inside of it:
using Excel = Microsoft.Office.Interop.Excel; public class ExcelData { public DataView Data { get { Excel.Application excelApp = new Excel.Application(); Excel.Workbook workbook; Excel.Worksheet worksheet; Excel.Range range; workbook = excelApp.Workbooks.Open(Environment.CurrentDirectory + "\\Excel.xlsx"); worksheet = (Excel.Worksheet)workbook.Sheets["Test Sheet"]; int column = 0; int row = 0; range = worksheet.UsedRange; DataTable dt = new DataTable(); dt.Columns.Add("ID"); dt.Columns.Add("Name"); dt.Columns.Add("Position"); dt.Columns.Add("Web Site"); for (row = 2; row <= range.Rows.Count; row++) { DataRow dr = dt.NewRow(); for (column = 1; column <= range.Columns.Count; column++) { dr[column - 1] = (range.Cells[row, column] as Excel.Range).Value2.ToString(); } dt.Rows.Add(dr); dt.AcceptChanges(); } workbook.Close(true, Missing.Value, Missing.Value); excelApp.Quit(); return dt.DefaultView; } } }As you can see reading excel in .NET Framework 4 is pretty simple task to do. I read excel worksheet and put the data into DataTable. The tricky part of it is to bind my property to the DataGrid. You cannot bind DataTable to a DataGrid because DataGrid does not implement IEnumerable interface.
So instead of DataTable I'm simply returning DefaultView.
Let's now see what we have in XAML:
<Window x:Class="WPFReadExcel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Reading Excel - www.CodeArsenal.net" Height="226" Width="346"> <Grid> <DataGrid Name="dataGrid1" ItemsSource="{Binding Data}"> </DataGrid> </Grid> </Window>ItemSource bound to the Data property. In the code behind I just specifying DataContext for the DataGrid:
ExcelData exceldata = new ExcelData(); this.dataGrid1.DataContext = exceldata;You're welcome to download the source code of this example (Visual Studio 2010 Project)
Instead of hardcoding column names in ExcelData class......get the column names from the worksheet (assuming headings are in row one)
ReplyDeleteThen any table can be imported!
// amend code as such
DataTable dt = new DataTable();
//dt.Columns.Add("ID");
//dt.Columns.Add("Name");
//dt.Columns.Add("Position");
//dt.Columns.Add("Web Site");
for (column = 1; column <= range.Columns.Count; column++)
{
//dr[column - 1] = (range.Cells[row, column] as Excel.Range).Value2.ToString();
dt.Columns.Add((range.Cells[1, column] as Excel.Range).Value2.ToString());
}
Good point!
DeleteThank you.
Thanks for the article!
ReplyDeleteI can not open Excel file.I got an error as "Microsoft Excel cannot access the file 'C:\Excel.xlsx'" in this line....
ReplyDeleteworkbook = excelApp.Workbooks.Open(Environment.CurrentDirectory + "\\Excel.xlsx");
Plz help me...I spent lot of time in this
There are several possible reasons:
ReplyDelete• The file name or path does not exist.
• The file is being used by another program.
Thanks a lot! Very good example!
ReplyDeleteNice Article ................
ReplyDeletejust a little advice you never create an instance of an object inside a "for"
ReplyDeleteit should be like this
DataRow dr=new DataRow();
for(stuff in here)
{
dr.stuff= morestuff;
}
If there's an empty cell, this line:
ReplyDeleterange.Cells[row, column] as Excel.Range).Value2.ToString()
breaks. I could put it in a try catch where the catch sets that one cell to an empty string, but that doesn't seem like it would be best practice. Any thoughts on how to handle this scenario?
Just write this thing:
Deletedr[column - 1] = (range.Cells[row, column] as Excel.Range).Value2!=null ? (range.Cells[row, column] as Excel.Range).Value2.ToString() : "";
An easier way to handle this row:
Deleterange.Cells[row, column] as Excel.Range).Value2.ToString()
is to change it to:
Convert.ToString((range.Cells[row, column] as Excel.Range).Value2);
.ToString() can't handle nulls but Convert.ToString() can. It allows for less code too.