【问题标题】:Word can't open document after adding CustomXmlPart添加 CustomXmlPart 后 Word 无法打开文档
【发布时间】:2019-12-05 18:21:42
【问题描述】:

我正在尝试将 customxmlPart 添加到文档文件中,但没有成功。 显然文件太大(超过 10mb)无法包含在包中。

如果 xml 文件大小小于 7 mb,则可以成功打开文档。

有什么想法吗?

感谢您的帮助。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open("doc.docm", true))
{
    MainDocumentPart mainPart = wordDoc.MainDocumentPart;

    if (wordDoc.MainDocumentPart.CustomXmlParts != null)
    {
        wordDoc.MainDocumentPart.DeleteParts<CustomXmlPart>(wordDoc.MainDocumentPart.CustomXmlParts);
    }

    CustomXmlPart myXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);

    using (FileStream stream = new FileStream("10mbfile.xml", FileMode.Open))
    {
        myXmlPart.FeedData(stream);
    }

    wordDoc.Package.Flush();
}

编辑:我发现了问题,xml 文件包含很多回车 + 换行。删除它们后,我可以将文件嵌入为 CustomXmlPart。

【问题讨论】:

  • 将其分解为多个自定义 XML 部分。
  • 我正在考虑这个解决方案,但该文件将由 vsto 插件使用,一个文件对我来说更容易。如果无法存储一个唯一文件,我会将其拆分为多个文件
  • 如果文件是指自定义 XML 部分,我认为您没有选择余地,因为当前的设计似乎达到了 Word 应用程序/文档规范的大小限制。 (您没有明确说明触发了什么错误消息,也没有明确说明触发它的操作,所以我们只能猜测。)
  • 尝试打开文档时没有错误消息。 Word 卡在加载屏幕上。
  • @yokki VBA 中有一个限制,我无法检索变量,该值被截断。只返回 65535 个字符。

标签: c# ms-word openxml


【解决方案1】:

以下单元测试演示了您可以向 Word 文档添加非常大的自定义 XML 部分(示例中最大为 30MB):

using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using Xunit;

namespace CodeSnippets.Tests.OpenXml.Wordprocessing
{
    public class LargeCustomXmlPartsTests
    {
        public static readonly XNamespace W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

        [Theory]
        [InlineData(5)]
        [InlineData(10)]
        [InlineData(15)]
        [InlineData(20)]
        [InlineData(30)]
        public void CanCreateLargeCustomXmlParts(int size)
        {
            int desiredStreamLength = size * 1024 * 1024;
            string path = $"Document_{size:D2}MB.docm";

            // Create a macro-enabled Word document with a custom XML part having
            // at least the desired size in MB.
            CreateMacroEnabledWordDocument(path, size);

            // Assert that the document does have a custom XML part with at least
            // the desired size.
            using WordprocessingDocument wordDocument = WordprocessingDocument.Open(path, false);
            CustomXmlPart customXmlPart = wordDocument.MainDocumentPart.CustomXmlParts.First();
            using Stream stream = customXmlPart.GetStream(FileMode.Open, FileAccess.Read);
            Assert.True(stream.Length > desiredStreamLength);
        }

        private static void CreateMacroEnabledWordDocument(string path, int size)
        {
            const WordprocessingDocumentType type = WordprocessingDocumentType.MacroEnabledDocument;
            using WordprocessingDocument wordDocument = WordprocessingDocument.Create(path, type);

            // Create a main document part with an empty document.
            MainDocumentPart mainDocumentPart = wordDocument.AddMainDocumentPart();
            WriteRootElement(mainDocumentPart,
                new XElement(W + "document",
                    new XElement(W + "body",
                        new XElement(W + "p"))));

            // Create a custom XML part with the desired size in MB.
            CustomXmlPart customXmlPart = mainDocumentPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
            WriteRootElement(customXmlPart, CreatePartRootElement(size));
        }

        private static void WriteRootElement(OpenXmlPart part, XElement partRootElement)
        {
            using Stream stream = part.GetStream(FileMode.Create, FileAccess.Write);
            using XmlWriter writer = XmlWriter.Create(stream);

            partRootElement.WriteTo(writer);
        }

        private static XElement CreatePartRootElement(int size)
        {
            var random = new Random();

            return new XElement("root",
                Enumerable.Range(0, size).Select(paragraphIndex =>
                    new XElement("p",
                        new XAttribute("i", paragraphIndex),
                        Enumerable.Range(0, 1000).Select(runIndex =>
                            new XElement("r",
                                new XAttribute("i", runIndex),
                                new XElement("t", CreateRandomString(random)))))));
        }

        private static string CreateRandomString(Random random)
        {
            char[] value = Enumerable
                .Range(0, 930)
                .Select(i => Convert.ToChar(random.Next(33, 125)))
                .ToArray();

            return new string(value);
        }
    }
}

在我的 Windows 10 笔记本上,Microsoft Word for Office 365 使用 30MB 自定义 XML 部分打开文档,没有任何问题。因此,我想说,您的问题一定是由其他因素或多种因素共同引起的,包括评论中提到的 VSTO 加载项对自定义 XML 部分执行的任何处理。

【讨论】:

  • 用我的docm文件测试你的代码后,我发现我的xml是问题所在。谢谢
【解决方案2】:

我发现了问题,xml 文件包含很多回车 + 换行。删除它们后,我可以将文件嵌入为 CustomXmlPart。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多