23

我正在尝试使用 Microsoft 的 OpenXML 2.5 库来创建 OpenXML 文档。一切都很好,直到我尝试将 HTML 字符串插入到我的文档中。我已经搜索了网络,这是我到目前为止提出的内容(截断到我遇到问题的部分):

Paragraph paragraph = new Paragraph();
Run run = new Run();

string altChunkId = "id1";
AlternativeFormatImportPart chunk =
       document.MainDocumentPart.AddAlternativeFormatImportPart(
           AlternativeFormatImportPartType.Html, altChunkId);
chunk.FeedData(new MemoryStream(Encoding.UTF8.GetBytes(ioi.Text)));
AltChunk altChunk = new AltChunk { Id = altChunkId };

run.AppendChild(new Break());

paragraph.AppendChild(run);
body.AppendChild(paragraph);

显然,我实际上并没有在这个例子中添加 altChunk,但我已经尝试将它附加到任何地方 - 运行、段落、正文等。在任何情况下,我都无法在 Word 2010 中打开 docx 文件。

这让我有点疯狂,因为它看起来应该很简单(我承认我没有完全理解 AltChunk “东西”)。将不胜感激任何帮助。

旁注:我确实发现一件事很有趣,我不知道这是否真的是一个问题,这个响应说 AltChunk 在从 MemoryStream 工作时损坏了文件。任何人都可以确认这是/不是真的吗?

4

2 回答 2

27

通过使用不完整的 HTML 文档作为替代格式导入部分的内容,我可以重现错误“...内容有问题” 。例如,如果您使用以下 HTML 片段,<h1>HELLO</h1> MS Word 将无法打开该文档。

下面的代码显示了如何向AlternativeFormatImportPartword 文档添加一个。(我已经用 MS Word 2013 测试了代码)。

using (WordprocessingDocument doc = WordprocessingDocument.Open(@"test.docx", true))
{
  string altChunkId = "myId";
  MainDocumentPart mainDocPart = doc.MainDocumentPart;

  var run = new Run(new Text("test"));
  var p = new Paragraph(new ParagraphProperties(
       new Justification() { Val = JustificationValues.Center }),
                     run);

  var body = mainDocPart.Document.Body;
  body.Append(p);        

  MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<html><head></head><body><h1>HELLO</h1></body></html>"));

  // Uncomment the following line to create an invalid word document.
  // MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<h1>HELLO</h1>"));

  // Create alternative format import part.
  AlternativeFormatImportPart formatImportPart =
     mainDocPart.AddAlternativeFormatImportPart(
        AlternativeFormatImportPartType.Html, altChunkId);
  //ms.Seek(0, SeekOrigin.Begin);

  // Feed HTML data into format import part (chunk).
  formatImportPart.FeedData(ms);
  AltChunk altChunk = new AltChunk();
  altChunk.Id = altChunkId;

  mainDocPart.Document.Body.Append(altChunk);
}

根据 Office OpenXML 规范,元素的有效父元素 w:altChunkbody, comment, docPartBody, endnote, footnote, ftr, hdr and tc. 所以,我已将 加入w:altChunk到 body 元素中。

有关该w:altChunk元素的更多信息,请参阅此MSDN链接。

编辑

正如@user2945722 所指出的,要确保 OpenXml 库正确地将字节数组解释为 UTF-8,您应该添加 UTF-8 前导码。这可以通过以下方式完成:

MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(htmlEncodedString)).ToArray()

这将防止您的 é 被呈现为 é,您的 ä 被呈现为 ä 等。

于 2013-08-09T17:26:34.600 回答
2

这里有同样的问题,但完全不同的原因。如果接受的解决方案没有帮助,值得一试。保存后尝试关闭文件。就我而言,它恰好是损坏的 docx 文件和干净的 docx 文件之间的区别。奇怪的是,大多数其他操作仅使用 Save() 和程序退出。

String cid = "chunkid";
WordprocessingDocument document = WordprocessingDocument.Open("somefile.docx", true);
Body body = document.MainDocumentPart.Document.Body;
MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("<html><head></head><body>hi</body></html>"));
AlternativeFormatImportPart formatImportPart = document.MainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, cid);
formatImportPart.FeedData(ms);
AltChunk altChunk = new AltChunk();
altChunk.Id = cid;
document.MainDocumentPart.Document.Body.Append(altChunk);
document.MainDocumentPart.Document.Save();
// here's the magic!
document.Close();
于 2015-01-15T22:11:16.907 回答