将所有DataGrid行(包括不可见的)WPF导出到Excel

时间:2017-07-03 17:00:03

标签: c# wpf excel datagrid

我正在尝试将数据从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;
        }

    }

2 个答案:

答案 0 :(得分:0)

如果你不需要datagrid中的任何东西(比如自定义列排序或其他),你应该直接从数据源本身导出数据。

有了这个,有很多选择。就个人而言,我喜欢这里的方法,其中扩展方法处理所有事情。

https://stackoverflow.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。

答案 1 :(得分:0)

之前我遇到了同样的问题,我发现你需要将自己的DataGrid添加到ScrollViewer中,让我们看一下以下示例 添加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>