【问题标题】:Export all DataGrid rows (including non visible) WPF to Excel将所有 DataGrid 行(包括不可见的)WPF 导出到 Excel
【发布时间】:2026-02-18 07:15:01
【问题描述】:

我正在尝试将 WPF DataGrid 中的数据导出到 Excel 文档中。当我运行此按钮时,它会导出屏幕上可见或适合窗口的所有内容。 DataGrid 已填满,您必须向下滚动才能查看所有值,这些隐藏的值不会导出到 excel 文档中,并且会出现错误“对象引用未设置为对象的实例”。发生。如果所有值都适合屏幕,则没有问题。

private void Button_Click(object sender, RoutedEventArgs e)
  {
    Excel.Application excel = new Excel.Application();
    excel.Visible = true;
    Workbook workbook = excel.Workbooks.Add(System.Reflection.Missing.Value);
    Worksheet sheet1 = (Worksheet)workbook.Sheets[1];

    for (int ExcelRow = 1, GridRow = 0; ExcelRow <= dgrid.Items.Count - 1; 
         ExcelRow++, GridRow++)

        {
         Range myRange = (Range)sheet1.Cells[ExcelRow, 1];
         myRange.Value2 = dgrid.Columns[0].Header;

         TextBlock b = dgrid.Columns[0].GetCellContent(dgrid.Items[GridRow]) 
                       as TextBlock;

         Microsoft.Office.Interop.Excel.Range myRange2 = 
                  (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[2, 1];

         myRange.Value2 = b.Text;
         ///////////////////////

         myRange = (Range)sheet1.Cells[ExcelRow, 2];
         myRange.Value2 = dgrid.Columns[1].Header;

         b = dgrid.Columns[1].GetCellContent(dgrid.Items[GridRow]) as 
             TextBlock;

         myRange2 = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[3, 2];
         myRange.Value2 = b.Text;
         /////////////////////////

         myRange = (Range)sheet1.Cells[ExcelRow, 3];
         myRange.Value2 = dgrid.Columns[2].Header;

         b = dgrid.Columns[2].GetCellContent(dgrid.Items[GridRow]) as 
             TextBlock;

         myRange2 = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[4, 3];
         myRange.Value2 = b.Text;
        }

    }

【问题讨论】:

  • 既然它拥有一切,为什么不直接从 DataGrid 的 DataContext / ItemsSource 中吸出数据呢?直接从 UI 控件而不是视图模型中提取它很奇怪。

标签: c# wpf excel datagrid


【解决方案1】:

如果您不需要数据网格中的任何内容(例如自定义列排序或其他),您应该直接从数据源本身导出数据。

有了这个,有很多可用的选项。就个人而言,我喜欢这里的方法,扩展方法可以处理所有事情。

https://*.com/a/13973274/1415307

using System;
using System.Collections.Generic;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using System.Data;
using System.Data.OleDb;

DataTable dt;
// fill table data in dt here 
...

// export DataTable to excel
// save excel file without ever making it visible if filepath is given
// don't save excel file, just make it visible if no filepath is given
dt.ExportToExcel(ExcelFilePath);

DataTable类的扩展方法:

public static class My_DataTable_Extensions
{

    // Export DataTable into an excel file with field names in the header line
    // - Save excel file without ever making it visible if filepath is given
    // - Don't save excel file, just make it visible if no filepath is given
    public static void ExportToExcel(this DataTable tbl, string excelFilePath = null) {
        try {
            if (tbl == null || tbl.Columns.Count == 0)
                throw new Exception("ExportToExcel: Null or empty input table!\n");

            // load excel, and create a new workbook
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();

            // single worksheet
            Excel._Worksheet workSheet = excelApp.ActiveSheet;

            // column headings
            for (var i = 0; i < tbl.Columns.Count; i++) {
                workSheet.Cells[1, i + 1] = tbl.Columns[i].ColumnName;
            }

            // rows
            for (var i = 0; i < tbl.Rows.Count; i++) {
                // to do: format datetime values before printing
                for (var j = 0; j < tbl.Columns.Count; j++) {
                    workSheet.Cells[i + 2, j + 1] = tbl.Rows[i][j];
                }
            }

            // check file path
            if (!string.IsNullOrEmpty(excelFilePath)) {
                try {
                    workSheet.SaveAs(excelFilePath);
                    excelApp.Quit();
                    MessageBox.Show("Excel file saved!");
                }
                catch (Exception ex) {
                    throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
                                        + ex.Message);
                }
            } else { // no file path is given
                excelApp.Visible = true;
            }
        }
        catch (Exception ex) {
            throw new Exception("ExportToExcel: \n" + ex.Message);
        }
    }
}

此外,这也要求消费者安装了 Excel。这可能会导致一些并发症。如果您不需要 Excel 中的任何内容而只需要 Excel 可以读取的输出,我建议您只创建一个 CSV。

【讨论】:

    【解决方案2】:

    我之前也遇到过同样的问题,我发现你需要在 ScrollViewer 中添加你自己的 DataGrid,让我们看看下面这个例子 添加 scrollViewer 后,我确信您的代码将在 Excel 处于活动状态时完美运行。

     <ScrollViewer Grid.Row="0"
                      Margin="5 5 5 5">
            <Grid Grid.Row="0">
                <DataGrid 
                    Name="DataGridName"
                    HorizontalAlignment="Stretch" 
                    Margin="10,10,10,10" 
                    VerticalAlignment="Top" 
                    Height="Auto" Width="Auto" 
                    IsReadOnly="True"
                    CanUserSortColumns="False"
                    FontSize="13"
                    ItemsSource="{Binding Path=ListCustomer}"/>
            </Grid>
        </ScrollViewer>
    

    【讨论】:

      最近更新 更多