如何使用OpenXML SDK 2.5从word文档复制公式?

时间:2023-01-24 09:09:22

I have to use OpenXML SDK 2.5 with C# to copy formulas from one word document then append them to another word document. I tried the below code, it ran successfully but when I tried to open the file, it said there's something wrong with the content. I opened it ignoring the warning but those formulas were not displayed. They are just blank blocks.

我必须使用带有C#的OpenXML SDK 2.5来复制一个word文档中的公式,然后将它们附加到另一个word文档中。我尝试了下面的代码,它运行成功但是当我试图打开文件时,它说内容有问题。我打开它忽略警告,但没有显示那些公式。它们只是空白块。

My code:

private void CreateNewWordDocument(string document, Exercise[] exercices)
        {
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(document, WordprocessingDocumentType.Document))
            {
                // Set the content of the document so that Word can open it.
                MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();

                SetMainDocumentContent(mainPart);
                foreach (Exercise ex in exercices)
                {
                    wordDoc.MainDocumentPart.Document.Body.AppendChild(ex.toParagraph().CloneNode(true));
                }
                wordDoc.MainDocumentPart.Document.Save();
            }
        }

        // Set content of MainDocumentPart.
        private void SetMainDocumentContent(MainDocumentPart part)
        {
            string docXml =
         @"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?> 
 <w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
     <w:body><w:p><w:r><w:t>Exercise list!</w:t></w:r></w:p></w:body>
 </w:document>";

            using (Stream stream = part.GetStream())
            {
                byte[] buf = (new UTF8Encoding()).GetBytes(docXml);
                stream.Write(buf, 0, buf.Length);
            }

        }

1 个解决方案

#1


4  

This happens because not everything that can be referenced in the paragraph is copied when you clone the paragraph. The Word XML format consists of multiple files some of which reference each other. If you copy the paragraph from one document to another you need to also copy any relationships that may exist.

发生这种情况是因为克隆段落时不会复制段落中可引用的所有内容。 Word XML格式由多个文件组成,其中一些文件相互引用。如果将段落从一个文档复制到另一个文档,则还需要复制可能存在的任何关系。

The OpenXML Productivity Tool is useful for diagnosing errors like these. You can open a document with the tool and ask it to validate the document.

OpenXML Productivity Tool可用于诊断这些错误。您可以使用该工具打开文档并要求其验证文档。

I created a test document that just contained a hyperlink and ran your code to copy the contents to another document. I too got an error when I attempted to load it using Word so I opened it in the Productivity Tool and saw the following output:

我创建了一个测试文档,其中只包含一个超链接并运行您的代码以将内容复制到另一个文档。当我尝试使用Word加载它时,我也遇到了错误,因此我在Productivity Tool中打开它并看到以下输出:

如何使用OpenXML SDK 2.5从word文档复制公式?

This shows that the hyperlink is stored as a relationship rather than inline in the paragraph and my new file references a relationship that doesn't exist. Unzipping the original file and the new file and comparing the two shows what is going on: document.xml from original: 如何使用OpenXML SDK 2.5从word文档复制公式?

这表明超链接存储为段落中的关系而不是内联,我的新文件引用了不存在的关系。解压缩原始文件和新文件并比较两者显示正在发生的事情:来自original的document.xml:

.rels of original 如何使用OpenXML SDK 2.5从word文档复制公式?

原始的.rels

document.xml of generated file 如何使用OpenXML SDK 2.5从word文档复制公式?

生成文件的document.xml

.rels of generated file 如何使用OpenXML SDK 2.5从word文档复制公式?

.rels生成的文件

Note that in the generated file the hyperlink references relationship rId5 but that doesn't exist in the generated documents relationship file.

请注意,在生成的文件中,超链接引用了关系rId5,但在生成的文档关系文件中不存在。

It's worth noting that for simple source documents the code worked without issue as there are no relationships that require copying.

值得注意的是,对于简单的源文档,代码没有问题,因为没有需要复制的关系。

There are two ways that you can solve this. The easiest way is to only copy the text of the paragraph (you'll lose all styles, images, hyperlinks etc) but it is very simple. All you need to do is change

有两种方法可以解决这个问题。最简单的方法是只复制段落的文本(你将失去所有的样式,图像,超链接等),但它非常简单。你需要做的就是改变

wordDoc.MainDocumentPart.Document.Body.AppendChild(ex.toParagraph().CloneNode(true));

for

Paragraph para = wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph());
Run run = para.AppendChild(new Run());
run.AppendChild(new Text(ex.toParagraph().InnerText));

The more complex (and perhaps proper) way of achieving it is to find the relationships and copy them to the new document as well. The code for doing that is probably beyond the scope of what I can write here but there is an interesting article on the subject here http://blogs.msdn.com/b/ericwhite/archive/2009/02/05/move-insert-delete-paragraphs-in-word-processing-documents-using-the-open-xml-sdk.aspx.

实现它的更复杂(也许是正确的)方法是找到关系并将它们复制到新文档中。这样做的代码可能超出了我在这里写的范围,但是这里有一篇关于这个主题的有趣文章http://blogs.msdn.com/b/ericwhite/archive/2009/02/05/move-嵌件删除段落功能于文字处理的文档,使用最开放的XML-sdk.aspx。

Essentially the author of that blog post is using the Powertools for OpenXML to find relationships and copy them from one document to another.

本博客文章的作者基本上是使用Powertools for OpenXML来查找关系并将它们从一个文档复制到另一个文档。

#1


4  

This happens because not everything that can be referenced in the paragraph is copied when you clone the paragraph. The Word XML format consists of multiple files some of which reference each other. If you copy the paragraph from one document to another you need to also copy any relationships that may exist.

发生这种情况是因为克隆段落时不会复制段落中可引用的所有内容。 Word XML格式由多个文件组成,其中一些文件相互引用。如果将段落从一个文档复制到另一个文档,则还需要复制可能存在的任何关系。

The OpenXML Productivity Tool is useful for diagnosing errors like these. You can open a document with the tool and ask it to validate the document.

OpenXML Productivity Tool可用于诊断这些错误。您可以使用该工具打开文档并要求其验证文档。

I created a test document that just contained a hyperlink and ran your code to copy the contents to another document. I too got an error when I attempted to load it using Word so I opened it in the Productivity Tool and saw the following output:

我创建了一个测试文档,其中只包含一个超链接并运行您的代码以将内容复制到另一个文档。当我尝试使用Word加载它时,我也遇到了错误,因此我在Productivity Tool中打开它并看到以下输出:

如何使用OpenXML SDK 2.5从word文档复制公式?

This shows that the hyperlink is stored as a relationship rather than inline in the paragraph and my new file references a relationship that doesn't exist. Unzipping the original file and the new file and comparing the two shows what is going on: document.xml from original: 如何使用OpenXML SDK 2.5从word文档复制公式?

这表明超链接存储为段落中的关系而不是内联,我的新文件引用了不存在的关系。解压缩原始文件和新文件并比较两者显示正在发生的事情:来自original的document.xml:

.rels of original 如何使用OpenXML SDK 2.5从word文档复制公式?

原始的.rels

document.xml of generated file 如何使用OpenXML SDK 2.5从word文档复制公式?

生成文件的document.xml

.rels of generated file 如何使用OpenXML SDK 2.5从word文档复制公式?

.rels生成的文件

Note that in the generated file the hyperlink references relationship rId5 but that doesn't exist in the generated documents relationship file.

请注意,在生成的文件中,超链接引用了关系rId5,但在生成的文档关系文件中不存在。

It's worth noting that for simple source documents the code worked without issue as there are no relationships that require copying.

值得注意的是,对于简单的源文档,代码没有问题,因为没有需要复制的关系。

There are two ways that you can solve this. The easiest way is to only copy the text of the paragraph (you'll lose all styles, images, hyperlinks etc) but it is very simple. All you need to do is change

有两种方法可以解决这个问题。最简单的方法是只复制段落的文本(你将失去所有的样式,图像,超链接等),但它非常简单。你需要做的就是改变

wordDoc.MainDocumentPart.Document.Body.AppendChild(ex.toParagraph().CloneNode(true));

for

Paragraph para = wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph());
Run run = para.AppendChild(new Run());
run.AppendChild(new Text(ex.toParagraph().InnerText));

The more complex (and perhaps proper) way of achieving it is to find the relationships and copy them to the new document as well. The code for doing that is probably beyond the scope of what I can write here but there is an interesting article on the subject here http://blogs.msdn.com/b/ericwhite/archive/2009/02/05/move-insert-delete-paragraphs-in-word-processing-documents-using-the-open-xml-sdk.aspx.

实现它的更复杂(也许是正确的)方法是找到关系并将它们复制到新文档中。这样做的代码可能超出了我在这里写的范围,但是这里有一篇关于这个主题的有趣文章http://blogs.msdn.com/b/ericwhite/archive/2009/02/05/move-嵌件删除段落功能于文字处理的文档,使用最开放的XML-sdk.aspx。

Essentially the author of that blog post is using the Powertools for OpenXML to find relationships and copy them from one document to another.

本博客文章的作者基本上是使用Powertools for OpenXML来查找关系并将它们从一个文档复制到另一个文档。