简体   繁体   中英

How to export a DataGrid to Excel in WPF

I am working on a project and I have not been able to export the information that I have in my DataGrid to excel.

how can I do it?

I created an simple app to exporting DataGrid to Excel file.

Xaml:

<StackPanel>
    <!--Export button-->
    <Button Name="ToExcelButton"
            Content="ToExcel"
            Margin="8"
            Padding="8"
            HorizontalAlignment="Center"
            Click="ToExcelButton_OnClick"/>

    <!--Users DataGrid-->
    <DataGrid Name="UsersDataGrid"
              AutoGenerateColumns="False"
              DataContext="{Binding}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="120" />
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="180" />
            <DataGridTextColumn Header="Username" Binding="{Binding Username}" Width="150" />
        </DataGrid.Columns>
    </DataGrid>
</StackPanel>

C#:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        UsersDataGrid.ItemsSource = GetUsers();
    }

    private static IEnumerable<User> GetUsers()
    {
        var users = new List<User>
        {
            new User {Id = 1, Name = "User1", Username = "u123"},
            new User {Id = 2, Name = "User2", Username = "u321"},
            new User {Id = 3, Name = "User3", Username = "u852"},
        };

        return users;
    }

    private void ToExcelButton_OnClick(object sender, RoutedEventArgs e)
    {
        var d = UsersDataGrid.ItemsSource.Cast<User>();
        var data = ToDataTable(d.ToList());
        ToExcelFile(data, "test.xlsx");
    }

    public static DataTable ToDataTable<T>(List<T> items)
    {
        var dataTable = new DataTable(typeof(T).Name);

        //Get all the properties
        var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var prop in properties)
        {
            //Defining type of data column gives proper data table 
            var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
            //Setting column names as Property names
            dataTable.Columns.Add(prop.Name, type);
        }
        foreach (var item in items)
        {
            var values = new object[properties.Length];
            for (var i = 0; i < properties.Length; i++)
            {
                //inserting property values to data table rows
                values[i] = properties[i].GetValue(item, null);
            }
            dataTable.Rows.Add(values);
        }
        //put a breakpoint here and check data table
        return dataTable;
    }

    public static void ToExcelFile(DataTable dataTable, string filePath, bool overwriteFile = true)
    {
        if (File.Exists(filePath) && overwriteFile)
            File.Delete(filePath);

        using (var connection = new OleDbConnection())
        {
            connection.ConnectionString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={filePath};" +
                                          "Extended Properties='Excel 12.0 Xml;HDR=YES;'";
            connection.Open();
            using (var command = new OleDbCommand())
            {
                command.Connection = connection;
                var columnNames = (from DataColumn dataColumn in dataTable.Columns select dataColumn.ColumnName).ToList();
                var tableName = !string.IsNullOrWhiteSpace(dataTable.TableName) ? dataTable.TableName : Guid.NewGuid().ToString();
                command.CommandText = $"CREATE TABLE [{tableName}] ({string.Join(",", columnNames.Select(c => $"[{c}] VARCHAR").ToArray())});";
                command.ExecuteNonQuery();
                foreach (DataRow row in dataTable.Rows)
                {
                    var rowValues = (from DataColumn column in dataTable.Columns select (row[column] != null && row[column] != DBNull.Value) ? row[column].ToString() : string.Empty).ToList();
                    command.CommandText = $"INSERT INTO [{tableName}]({string.Join(",", columnNames.Select(c => $"[{c}]"))}) VALUES ({string.Join(",", rowValues.Select(r => $"'{r}'").ToArray())});";
                    command.ExecuteNonQuery();
                }
            }

            connection.Close();
        }
    }
}

User class:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Username { get; set; }
}

Install Microsoft.Office.Interop.Excel Nuget package in your application. Right-click on your project -> "References" and choose "Manage NuGet Packages..." , then just search for Excel. Otherwise, select Tools -> Nuget Package Manager -> Package Manager Console -> then install the Excel nuget ( https://www.nuget.org/packages/Microsoft.Office.Interop.Excel/ ).

Bind the items in DataGrid and then export data to excel as like below,

        private void btnExport_Click(object sender, RoutedEventArgs e)
        {            
            Microsoft.Office.Interop.Excel.Application excel = null;
            Microsoft.Office.Interop.Excel.Workbook wb = null;
            object missing = Type.Missing;
            Microsoft.Office.Interop.Excel.Worksheet ws = null;
            Microsoft.Office.Interop.Excel.Range rng = null;

            // collection of DataGrid Items
            var dtExcelDataTable = ExcelTimeReport(txtFrmDte.Text, txtToDte.Text, strCondition);

            excel = new Microsoft.Office.Interop.Excel.Application();
            wb = excel.Workbooks.Add();
            ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.ActiveSheet;
            ws.Columns.AutoFit();
            ws.Columns.EntireColumn.ColumnWidth = 25;

            // Header row
            for (int Idx = 0; Idx < dtExcelDataTable.Columns.Count; Idx++)
            {
                ws.Range["A1"].Offset[0, Idx].Value = dtExcelDataTable.Columns[Idx].ColumnName;                    
            }

            // Data Rows
            for (int Idx = 0; Idx < dtExcelDataTable.Rows.Count; Idx++)
            {  
                ws.Range["A2"].Offset[Idx].Resize[1, dtExcelDataTable.Columns.Count].Value = dtExcelDataTable.Rows[Idx].ItemArray;
            }

            excel.Visible = true;
            wb.Activate();
        }

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM