WPF中DataGrid导出至Excel:适用于Office 2019的Microsoft.Office.Interop.Excel替代方案
Hey there, let's tackle your problem directly—you want an Excel export solution compatible with Office 2019/365 that works almost exactly like Microsoft.Office.Interop.Excel so you don't have to rewrite tons of code. Here are your best options:
方案1:升级官方Interop NuGet包(零代码改动)
First off, the Microsoft.Office.Interop.Excel library does support Office 2019 and 365—your compatibility issue is likely due to using an outdated version of the NuGet package.
- How to fix it:
- Uninstall any old version of
Microsoft.Office.Interop.Excelfrom your project. - Install the latest version via NuGet (currently v15.0.4795.1000+). This version supports all Office releases from 2013 through 365.
- Keep your existing code exactly as-is—no changes needed.
- Uninstall any old version of
This is the simplest fix if you want to stick with Microsoft's official library.
方案2:NetOffice.ExcelApi(开源,全版本兼容)
If you want a more robust, version-agnostic alternative that's 100% API-compatible with Microsoft's Interop, go with NetOffice. It's an open-source library that wraps Office Interop and works with every Office version from 2000 to 365. The best part? Your existing code will barely need any tweaks.
Step-by-step implementation:
- Install the NuGet package: Search for
NetOffice.Exceland install it in your project. - Update your using statement:
Replace this:
With this:using Microsoft.Office.Interop.Excel;using NetOffice.ExcelApi; - Keep the rest of your code identical: Every class (
Application,Workbook,Worksheet), method, and property matches the Interop API exactly. Your existingExportDataGridmethod will work without any other changes.
Modified code snippet (only the using part changes):
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using NetOffice.ExcelApi; // 仅修改这一行 namespace My.NameSpace { class ExcelExport { public static void ExportDataGrid(object sender) { // 你的原有代码完全不变... DataGrid currentGrid = sender as DataGrid; if (currentGrid != null) { StringBuilder sbGridData = new StringBuilder(); List<string> listColumns = new List<string>(); List<DataGridColumn> listVisibleDataGridColumns = new List<DataGridColumn>(); List<string> listHeaders = new List<string>(); Application application = null; Workbook workbook = null; Worksheet worksheet = null; int rowCount = 1; int colCount = 1; try { application = new Application(); workbook = application.Workbooks.Add(Type.Missing); worksheet = (Worksheet)workbook.Worksheets[1]; if (currentGrid.HeadersVisibility == DataGridHeadersVisibility.Column || currentGrid.HeadersVisibility == DataGridHeadersVisibility.All) { foreach (DataGridColumn dataGridColumn in currentGrid.Columns.Where(dataGridColumn => dataGridColumn.Visibility == Visibility.Visible)) { listVisibleDataGridColumns.Add(dataGridColumn); if (dataGridColumn.Header != null) { listHeaders.Add(dataGridColumn.Header.ToString()); } worksheet.Cells[rowCount, colCount] = dataGridColumn.Header; colCount++; } } foreach (object data in currentGrid.ItemsSource) { listColumns.Clear(); colCount = 1; rowCount++; foreach (DataGridColumn dataGridColumn in listVisibleDataGridColumns) { string strValue = string.Empty; Binding objBinding = null; DataGridBoundColumn dataGridBoundColumn = dataGridColumn as DataGridBoundColumn; if (dataGridBoundColumn != null) { objBinding = dataGridBoundColumn.Binding as Binding; } DataGridTemplateColumn dataGridTemplateColumn = dataGridColumn as DataGridTemplateColumn; if (dataGridTemplateColumn != null) { DependencyObject dependencyObject = dataGridTemplateColumn.CellTemplate.LoadContent(); FrameworkElement frameworkElement = dependencyObject as FrameworkElement; if (frameworkElement != null) { FieldInfo fieldInfo = frameworkElement.GetType().GetField("ContentProperty", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); if (fieldInfo == null) { if (frameworkElement is System.Windows.Controls.TextBox || frameworkElement is TextBlock || frameworkElement is ComboBox) { fieldInfo = frameworkElement.GetType().GetField("TextProperty"); } else if (frameworkElement is DatePicker) { fieldInfo = frameworkElement.GetType().GetField("SelectedDateProperty"); } } if (fieldInfo != null) { DependencyProperty dependencyProperty = fieldInfo.GetValue(null) as DependencyProperty; if (dependencyProperty != null) { BindingExpression bindingExpression = frameworkElement.GetBindingExpression(dependencyProperty); if (bindingExpression != null) { objBinding = bindingExpression.ParentBinding; } } } } } if (objBinding != null) { if (!String.IsNullOrEmpty(objBinding.Path.Path)) { PropertyInfo pi = data.GetType().GetProperty(objBinding.Path.Path); if (pi != null) { object propValue = pi.GetValue(data, null); strValue = propValue != null ? Convert.ToString(propValue) : string.Empty; } } if (objBinding.Converter != null) { strValue = !String.IsNullOrEmpty(strValue) ? objBinding.Converter.Convert(strValue, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString() : objBinding.Converter.Convert(data, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString(); } } listColumns.Add(strValue); worksheet.Cells[rowCount, colCount] = strValue; colCount++; } } } catch (System.Runtime.InteropServices.COMException) { // 可添加异常日志逻辑 } finally { workbook?.Close(); application?.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(application); } } } } }
关键注意事项
- Ensure the target machine has Office 2019/365 installed (or the Microsoft Office Compatibility Pack if you only need basic Excel file support).
- When switching libraries, clean your project and rebuild to avoid assembly conflicts.
内容的提问来源于stack exchange,提问作者Ole M




