在不使用 COM Interop 的情况下创建内存 Excel 文件并在 Excel 中打开它

Create in-memory Excel file and open it in Excel without using COM Interop

我目前在 .NET 中使用 COM Interop 将 DataTable 的内容导出到 Excel。这是我多年来一直使用的方法,但问题是 COM 不够完善,会抛出随机的、间歇性的、无法追踪的异常。这并不是一个大问题,因为它一直只是专门用于此目的的机器上的代码,而且例外情况非常罕见,但最近我为数据仓库编写了一个前端,并且我有 200 多个用户它,并且问题已经(如您所料)成倍增长。

问题是找到一种方法来完成 COM 所做的事情,而不会出现 COM 带来的问题。即,在内存中创建一个 Excel 文件(不写入磁盘),这是一个新的工作簿,这样当用户第一次点击 "Save" 时,它会询问他们要保存到哪里文件以及他们想给它起什么名字。

我知道我可以使用 OpenXML 将 DataTable 导出到 Excel 文件:Export DataTable to Excel with Open Xml SDK in c#

而且我知道我可以在内存中创建一个 OpenXML Excel 对象而无需写入磁盘上的文件:

问题是最后一步:在 Excel(不使用 COM)中打开内存中的文件

让它工作将是我的理想选择。

现在,我宁愿不写入文件,但如果没有其他选择,这也不是问题,因此作为备份选项,我还考虑过使用 OpenXML 创建一个 Excel 模板,然后打开模板(使用 Process.Start)。

该方法的问题是一些用户报告说模板有时会默认在编辑模式下打开为 xltx 文件,而不是打开为新的 xlsx 文件:https://answers.microsoft.com/en-us/office/forum/office_2007-customize/is-there-a-way-to-get-my-excel-template-xltx-file/ab36cd4d-f6b0-46e0-8f15-533a4acb357f?page=1

这将是一个比我使用 COM 时遇到的随机错误更大的问题。

欢迎任何想法。

编辑 - 这些是我得到的 COM 错误:


无法创建 ActiveX 组件。

COM 目标未实现 IDispatch。

HRESULT 异常:0x800AC472

Select 范围 class 方法失败

操作不可用(HRESULT 异常:0x800401E3 (MK_E_UNAVAILABLE))

消息过滤器表明应用程序正忙。 (HRESULT 异常:0x8001010A(RPC_E_SERVERCALL_RETRYLATER))

远程过程调用失败。 (HRESULT 异常:0x800706BE)

无法将类型 'System.__ComObject' 的 COM 对象转换为接口类型 'System.Collections.IEnumerable'。此操作失败,因为 IID 为“{496B0ABE-CDEE-11D3-88E8-00902754C43A}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:'The requested object does not exist. (Exception from HRESULT: 0x80010114)' 并且 COM 组件不支持 IDispatch::Invoke 要求 DISPID_NEWENUM.

无法获取工作簿 class

的添加 属性

工作簿的激活方法class失败


我在几个月的时间里收到了 107 个错误,但最近我收到了更多错误,因为我更新了该功能以附加到用户可能已经打开的 Excel 的任何现有实例而不是创建一个新的。以前,当我总是每次都创建一个新的 Excel 实例时,错误要少得多(并且在我做幕后工作时通过使 Excel 不可见来解决)。

这是一个建议,而不是一个答案。考虑尝试将文件保存到临时位置,并在文件系统中将其设置为只读。这将迫使您的用户执行另存为而不是保存。然后使用 Excel 命令行选项(显然 /n 最好)像打开模板一样打开 XLSX 文件。

这些命令行选项位于此处:Excel Command Line Options