Exporting DataGrid To Excel In WPF

This article is going to be helpful for those who often deal with grids and exporting the data. Before we proceed, I would like to mention a few things.

  1. I am using IList object to bind it to the DataGrid ItemsSource.
  2. While exporting DataGrid to Excel, I am using an extension method, which converts IList object to DataTable. (Extension method reference)

As shown below, I created a collection of the Person class having four properties (for the starters).

  1. public class Person  
  2. {  
  3.     public string FirstName {  
  4.         get;  
  5.         set;  
  6.     }  
  7.     public string LastName {  
  8.         get;  
  9.         set;  
  10.     }  
  11.     public string City {  
  12.         get;  
  13.         set;  
  14.     }  
  15.     public string Country {  
  16.         get;  
  17.         set;  
  18.     }  
  19. }  
Utilizing the Person class to create the objects needs to be bound to the Grid.
  1. IList < Person > lstPersons = new List < Person > ();  
  2. for (int i = 0; i < 5; i++) {  
  3.     lstPersons.Add(new Person {  
  4.         FirstName = "fname " + i, LastName = "lname " + i, City = "city " + i, Country = "country " + i  
  5.     });  
  6. }  
  7. dgExcel.ItemsSource = lstPersons; //dgExcel is the datagrid.  
Using the extension method, given below, to IList, you can convert the list, mentioned above, to DataTable. For simplicity, I have created a separate class, having the extension method, which deals with the conversion.
  1. public static DataTable ToDataTable < T > (this IList < T > data)  
  2. {  
  3.     PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));  
  4.     DataTable dt = new DataTable();  
  5.     foreach(PropertyDescriptor prop in properties) {  
  6.         dt.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ? ? prop.PropertyType);  
  7.     }  
  8.     foreach(T item in data) {  
  9.         DataRow row = dt.NewRow();  
  10.         foreach(PropertyDescriptor pdt in properties) {  
  11.             row[pdt.Name] = pdt.GetValue(item) ? ? DBNull.Value;  
  12.         }  
  13.         dt.Rows.Add(row);  
  14.     }  
  15.     return dt;  
  16. }  
Before you go further, please take a look at the various articles, which helps you to implement the Office Interop with your Application, used below.

Defining the class level variables, as I am dealing with WPF and saving Excel on the button click, I am going for the global variables.
  1. Microsoft.Office.Interop.Excel.Application excel;  
  2. Microsoft.Office.Interop.Excel.Workbook workBook;  
  3. Microsoft.Office.Interop.Excel.Worksheet workSheet;  
  4. Microsoft.Office.Interop.Excel.Range cellRange;  
Using the method, mentioned below, create an Excel Application and create the Workbook. I am making Excel Workbook invisible, so that you can do the rest of the work on the screen. If you like, you can make it visible and later save it.

(Take a look at highlighted line, don’t forget to specify the full name of the class, including the namespace, else, you will have to deal with ambiguity for DataRow Class.)
  1. private void GenerateExcel(DataTable DtIN)   
  2. {  
  3.     try {  
  4.         excel = new Microsoft.Office.Interop.Excel.Application();  
  5.         excel.DisplayAlerts = false;  
  6.         excel.Visible = false;  
  7.         workBook = excel.Workbooks.Add(Type.Missing);  
  8.         workSheet = (Microsoft.Office.Interop.Excel.Worksheet) workBook.ActiveSheet;  
  9.         workSheet.Name = "LearningExcel";  
  10.         System.Data.DataTable tempDt = DtIN;  
  11.         dgExcel.ItemsSource = tempDt.DefaultView;  
  12.         workSheet.Cells.Font.Size = 11;  
  13.         int rowcount = 1;  
  14.         for (int i = 1; i <= tempDt.Columns.Count; i++) //taking care of Headers.  
  15.         {  
  16.             workSheet.Cells[1, i] = tempDt.Columns[i - 1].ColumnName;  
  17.         }  
  18.         foreach(System.Data.DataRow row in tempDt.Rows) //taking care of each Row  
  19.             {  
  20.                 rowcount += 1;  
  21.                 for (int i = 0; i < tempDt.Columns.Count; i++) //taking care of each column  
  22.                 {  
  23.                     workSheet.Cells[rowcount, i + 1] = row[i].ToString();  
  24.                 }  
  25.             }  
  26.         cellRange = workSheet.Range[workSheet.Cells[1, 1], workSheet.Cells[rowcount, tempDt.Columns.Count]];  
  27.         cellRange.EntireColumn.AutoFit();  
  28.     } catch (Exception) {  
  29.         throw;  
  30.     }  
  31. }  
I am using the method, given below, to generate Excel sheet from the list.
  1. GenerateExcel(lstPersons.ToDataTable());  
On click event of the button, it is done to store the opened Excel file to the location, specified in the code.

Please note that, the SaveAs method takes the file path as a string and the path is not the filename only. It is the full path, including the filename. You can specify the path, as I did or it will choose the current folder and will create Excel file in the same.
  1. private void btnLocation_Click(object sender, RoutedEventArgs e)   
  2. {  
  3.         workBook.SaveAs(System.IO.Path.Combine(@ "Drive:\Folder(s)\","  
  4.                     Excel book Name "));  
  5.                     workBook.Close(); excel.Quit();  
  6.                 }  
Output: Once you click on the button on top of  the grid, you should be able to see Excel file in the location, mentioned above, with the grid data.

Output

Output

FYI: There is plenty of scope for improvement in the code, mentioned above. Feel free to do so. If there is any better way, please leave your comments for the same.

Please leave your suggestion(s)/question(s) in the comments. I will be happy to help.