Development with Open XML
1. 准备开发环境
1.1 Open XML SDK
现在最新的 OpenXML SDK 版本是 2.12.1 (2021/1),需要通过 NuGet 下载。NuGet: https://www.nuget.org/packages/DocumentFormat.OpenXml/
微软官方的文档有的是 2.5,有的是 2.7,还没有统一到最新的版本上来,看微软文档的时候要注意。
这是微软官方 docs 的地址: https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk
API 文档:Open XML SDK 2.5 class library reference
微软官方提供了一系列的示例,演示了多种场景下,如何使用 OpenXML SDK 进行处理:
How do I...(OpenXML SDK)
通常找到的微软官方 OpenXML SDK 下载是 2.5 版本的,比较老了。不建议使用它。
Open XML SDK 2.5 for Microsoft Office: https://www.microsoft.com/en-us/download/details.aspx?id=30425
微软已经将 OpenXML SDK 的源码发布到 GitHub 上,GitHub: https://github.com/OfficeDev/Open-XML-SDK/
1.2 Open XML SDK Tools
微软同时提供了一个 OpenXML SDK 的图形界面工具,可以直接打开文档,并提供生成对应内容的 C# 代码。
Open XML SDK 2.5 for Microsoft Office
https://www.microsoft.com/en-us/download/details.aspx?id=30425
1.3 Open Xml Power Tools
原来微软还维护一个 OpenXML 的开发工具集 Open XML Power Tools,现在从微软的分支中转移到一个独立的分支。
它使用 LINQ to XML 技术来提供性能,提供了各种高级场景的开发工具和示例。在 NuGet 上提供了开发包 OpenXmlPowerTools,可以直接安装使用,NuGet 地址:https://www.nuget.org/packages/OpenXmlPowerTools/
源代码可以在 GitHub 上找到:https://github.com/EricWhiteDev/Open-Xml-PowerTools
该库的维护者 Eric 同时创建了一个网站 Open XML Power Tools Developer Center 来提供支持。在这里,Eric 发布了博客和视频来帮助你使用该库。
不过,有一个问题,该库在 .NET Core 下会出现问题。目前只能在 .NET Framework 下使用。
由于 OpenXML SDK 在打开文档之后,实际上在内存中构建了一个 XML DOM 树,而 Power Tools 没有直接操作该 DOM 树,而是使用了 Linq to XML 重新构建数据结构进行操作,在完成之后,直接替换原来的 XML DOM 树。由于 .NET Core 对于 XML 处理的问题,导致该异常。
异常内容
Unhandled exception. System.IO.IOException: Entries cannot be opened multiple times in Update mode.
at System.IO.Compression.ZipArchiveEntry.OpenInUpdateMode()
at System.IO.Compression.ZipArchiveEntry.Open()
at System.IO.Packaging.ZipStreamManager.Open(ZipArchiveEntry zipArchiveEntry, FileMode streamFileMode, FileAccess streamFileAccess)
at System.IO.Packaging.ZipPackagePart.GetStreamCore(FileMode streamFileMode, FileAccess streamFileAccess)
at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
at System.IO.Packaging.PackagePart.GetStream(FileMode mode)
at DocumentFormat.OpenXml.Packaging.OpenXmlPart.GetStream(FileMode mode)
at DocumentFormat.OpenXml.OpenXmlPartRootElement.SaveToPart(OpenXmlPart openXmlPart)
at DocumentFormat.OpenXml.OpenXmlPartRootElement.Save()
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContent(OpenXmlPart part)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.TrySavePartContent(OpenXmlPart part)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContents(Boolean save)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Save()
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Clone(String path, Boolean isEditable, OpenSettings openSettings)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Clone(String path)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SaveAs(String path)
关于该问题的 Issues: