DataGrid to Excel?

本文关键字:Excel to DataGrid | 更新日期: 2023-09-27 18:29:03

我在WPF中创建了一个程序。它显示一个DataGrid,其中包含MySQL数据库中的数据。我想做的是允许用户将DataGrid的内容导出到Excel文件中。WPF有可能做到这一点吗?

当我使用此处显示的方法时:https://www.outcoldman.ru/en/blog/show/201

导入到xls文件的唯一一行是标题。

DataGrid to Excel?

我也在寻找类似的东西来帮助将数据网格中的数据导出到excel中,但没有找到任何有效的方法。至少我刚刚将DataGrid的内容转换为一个2D字符串数组,并使用interop.dll导出它。

代码看起来像这样:

    Excel.Application xlApp;
    Excel.Workbook xlWorkBook;
    Excel.Worksheet xlWorkSheet;
    object misValue = System.Reflection.Missing.Value;
    Excel.Range rangeToHoldHyperlink;
    Excel.Range CellInstance;
    xlApp = new Excel.Application();
    xlWorkBook = xlApp.Workbooks.Add(misValue);
    xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
    xlApp.DisplayAlerts = false;
    //Dummy initialisation to prevent errors.
    rangeToHoldHyperlink = xlWorkSheet.get_Range("A1", Type.Missing);
    CellInstance = xlWorkSheet.get_Range("A1", Type.Missing);
    for (int i = 0; i < NumberOfCols; i++)
    {
            for (int j = 0; j <= NumberOfRows; j++)
            {
                xlWorkSheet.Cells[j + 1, i + 1] = DataToWrite[j][i];
            }
     }

如果你正在寻找一些格式化,它们也在这里得到支持。我想添加一个超链接,下面的代码做到了:

 CellInstance = xlWorkSheet.Cells[j + 1, i + 1];
                xlWorkSheet.Hyperlinks.Add(
                    CellInstance,
                    DataToWrite[j][i],
                    Type.Missing,
                    "Hover Text Comes Here",
                    "Text to be displayed");

如果你想让第一行成为标题,你可以如下突出显示它们:

Excel.Range Range1 = xlWorkSheet.get_Range("A1");
Range1.EntireRow.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Black);
Range1.EntireRow.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightSkyBlue);
Range1.EntireRow.Font.Size = 14;
Range1.EntireRow.AutoFit();

最后将excel保存在所需路径中:

xlWorkBook.SaveAs(@FilePath, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close();

对interop的引用添加如下:

Right Click on the Project name -> Click "Add reference" -> Goto "COM" tab -> Search for "Microsoft Excel Object Library" click "OK" to add the reference.

您必须使用以下命名空间:

using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

您还可以将DataGrid内容导出到CSV文件中。

我不知道你是否在使用数据绑定,这里我假设你使用了。

var items = LoadItemsFromUnderlyingDataStore();
itemsDataGrid.ItemsSource = items;
private void ItemsDataGridExportButton_Click(object sender, EventArgs e) {
    var filename = AutoGenerateDateTimedFileName();
    using (var csv = new FileStream(filename)) {
        // if you want any column header in your Excel file, uncomment line below.            
        //csv.WriteLine("Column1,Column2,Column3,Column4");
        items.ForEach(item => 
            csv.WriteLine("{0},{1},{2},{3}"
                , item.PropertyFromFirstColumn
                , item.PropertyFromSecondColumn
                , item.PropertyFromThirdColumn
                , item.PropertyFromFourthColumn);
        try { csv.Flush(); }
        catch(IOException ex) { 
            // Handle error (log, whatever...)
            throw; // If you need to let the exception bubble up...
        }
    }
}
private string AutoGenerateDateTimedFileName() {
    return string.Format("DataGridExport_{0}_{1}.csv"
        , DataTime.Today.ToShortDateString()
        , DateTime.Now.ToLongTimeString());
}

总之,这个代码示例应该使用CSV文件,之后您可以使用Excel打开它。您甚至可以在创建文件时启动Excel。

private void ItemsDataGridExportButton_Click(object sender, EventArgs e) {
    // here's the upper code sample, and add the following:
    Process.Start(filename)
}

现在,使用Excel Interop。

object[,] values = BuildTwoDimensionalMatrixFromDataGridContent();
Worksheet.Cells.Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault) = values;

这可能是在Excel文件中设置值的最快方法,而且不需要迭代。

第一个提出的使用CSV文件的解决方案可能是最容易理解和使用的。

免责声明

这段代码是我从头开始创建的,因此还没有经过测试。为了使此代码与程序的上下文正确工作,可能需要进行一些更改。此外,这里显示的带有interop的代码和您将能够与WPF一起使用的代码之间可能需要进行细微的差异分析

最好的方法可能是为自己编写一个类库,该类库将与用普通C#编写的解决方案一起部署,这样您就可以使用简单的Interop指令。

此链接可能对您有用-

从Silverlight/WPF DataGrid 将数据导出到Excel

示例代码从C:''Windows''WinSxS中检索所有目录的列表,将其绑定到DataGrid并将DataGrid导出到Excel。这里的核心是要知道,将数据导出到Excel的最快方法是将数组分配给工作表。但问题是我们不能直接从DataGrid中获取这个数组。因此,我们首先需要填充它。使用一点反射,我们可以获得属性值并填充数组。导出数据完全是一行。我电脑上的WinSxS文件夹包含14880个目录。该代码运行约3秒(填充DataGrid+export)。

    using Excel = Microsoft.Office.Interop.Excel;
    private void ExportDataGrid()
    {
        // Fetch directories
        var dirInfo = new DirectoryInfo(@"C:'Windows'WinSxS'");
        var items = dirInfo.EnumerateDirectories();
        dataGrid.ItemsSource = items;
        var source = dataGrid.ItemsSource;
        // Create Excel app
        var excel = new Excel.Application { Visible = true };
        excel.ScreenUpdating = false; //Some speed-up
        var book = excel.Workbooks.Add();
        var sheet = (Excel.Worksheet)book.Sheets[1];
        int row = -1; //The row in array
        Type type = null;
        // Create array to hold data
        int rows = items.Count(), cols = dataGrid.Columns.Count;
        var arr = new object[rows, cols];
        foreach (DirectoryInfo dir_info in dataGrid.ItemsSource)
        {
            ++row;
            // You can also use GetType().GetTypeInfo() as of .NET 4.5+.
            // The return type will be TypeInfo.
            type = dir_info.GetType();
            for (int col = 0; col < cols; ++col)
            {
                var column_name = (string)dataGrid.Columns[col].Header;
                var value = type.GetProperty(column_name).GetValue(dir_info);
                arr.SetValue(value, row, col);
            }
        }
        // Create header
        for (int col = 0; c < cols; ++c)
        {
            sheet.Cells[1, col + 1].Value = dataGrid.Columns[col].Header;
        }
        // Dump array - the fastest way
        sheet.Range["A2"].Resize[rows, cols].Value = arr;
        // Restore screen updating - otherwise Excel will not response to actions
        excel.ScreenUpdating = true;
    }
private void data2Exel(DataGrid dataGrid)
        {
            Excel.Application excel = new Excel.Application();
            excel.Visible = true; //www.yazilimkodlama.com
            Workbook workbook = excel.Workbooks.Add(System.Reflection.Missing.Value);
            Worksheet sheet1 = (Worksheet)workbook.Sheets[1];
            for (int j = 0; j < dataGrid.Columns.Count; j++) //Başlıklar için
            {
                Range myRange = (Range)sheet1.Cells[1, j + 1];
                sheet1.Cells[1, j + 1].Font.Bold = true; //Başlığın Kalın olması için
                sheet1.Columns[j + 1].ColumnWidth = 15; //Sütun genişliği ayarı
                myRange.Value2 = dataGrid.Columns[j].Header;
            }
            for (int i = 0; i < dataGrid.Columns.Count; i++)
            {
                for (int j = 0; j < dataGrid.Items.Count; j++)
                {
                    TextBlock b = dataGrid.Columns[i].GetCellContent(dataGrid.Items[j]) as TextBlock;
                    Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[j + 2, i + 1];
                    myRange.Value2 = b.Text;
                }
            }
        }