2014-08-28 133 views
1

我在Word模板中有一个富文本框contentControl。我试图将RTF数据插入ContentControl并生成一个Word文档。正如所述,我尝试了AltChunk。这将与SdtBlock一起使用。由于SdtBlock的父亲为Body,因此我们可以直接将AltChunk插入身体。如果word文档具有多个富文本框contentControls,则word将该控件保存为SdtRunSdtRun的父亲是Paragraph,它的父母是Body。如果我们试图做类似使用OpenXML将RTF和HTML插入到富文本框内容控件

SdtRun contentControl = (SdtRun)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<SdtRun>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox")); 

contentControl.Parent.Parent.InsertAfter(altChunk, contentControl); //contentControl.Parent.Parent - Returns body of document 

抛出异常 操作无效由于对象的当前状态

所以我试图用Paragraph

Paragraph contentControl = (Paragraph)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<Paragraph>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox")); 
contentControl.Parent.InsertAfter(altChunk, contentControl); //contentControl.Parent - Returns body of document 

此代码以RTF格式插入数据。但问题是我无法插入到Rich TextControl的正确位置,因为我们正在对Paragraph进行操作。

完整的代码下面贴

string templatePath = @"Template1.docx"; 
string newFile = @"Template1_Processed.docx"; 

System.IO.File.Copy(templatePath, newFile, true); 

using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(newFile, true)) 
    { 
     Paragraph sdtElement = (Paragraph)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<Paragraph>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox")); 
     string innerText = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}{\colortbl ;\red139\green0\blue0;}\viewkind4\uc1\pard\cf1\f0\fs24 test\par}"; 
     string altChunkId = "myId"; 
     MainDocumentPart mainDocPart = wordprocessingDocument.MainDocumentPart; 
     MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(innerText)); 

     // Create alternative format import part. 
     AlternativeFormatImportPart formatImportPart = 
      mainDocPart.AddAlternativeFormatImportPart(
       AlternativeFormatImportPartType.Rtf, altChunkId); 

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

     sdtElement.Parent.InsertAfter<AltChunk>(altChunk, sdtElement); 
     SdtElement contentControl = (SdtElement)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<SdtElement>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox")); 
     contentControl.Remove(); 
     wordprocessingDocument.MainDocumentPart.CreateRelationshipToPart(formatImportPart); 

     sdtElement = (Paragraph)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<Paragraph>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox1")); 
     if (sdtElement != null) 
     { 
      innerText = @"<html><head></head><body><h1>HELLO</h1></body></html>"; 
      altChunkId = "myId1"; 
      ms = new MemoryStream(Encoding.UTF8.GetBytes(innerText)); 

      // Create alternative format import part. 
      formatImportPart = 
       mainDocPart.AddAlternativeFormatImportPart(
        AlternativeFormatImportPartType.Html, altChunkId); 

      // Feed HTML data into format import part (chunk). 
      formatImportPart.FeedData(ms); 
      altChunk = new AltChunk(); 
      altChunk.Id = altChunkId; 
      sdtElement.Parent.InsertAfter(altChunk, sdtElement); 
      contentControl = (SdtElement)wordprocessingDocument.MainDocumentPart.RootElement.Descendants<SdtElement>().FirstOrDefault(x => x.Descendants<Tag>().Any(y => y.Val == "richtextbox1")); 
      contentControl.Remove(); 

      wordprocessingDocument.MainDocumentPart.CreateRelationshipToPart(formatImportPart); 

      wordprocessingDocument.MainDocumentPart.Document.Save(); 
      wordprocessingDocument.Close(); 
     } 
    } 

附加模板 enter image description here的屏幕截图,并生成word文档 enter image description here

由于我们是后插入到Paragraph,这是越来越插入非常旁Paragraph。所以我们不能将数据插入文档中富文本数据的正确位置。

任何人都可以帮我解决这个问题/建议任何替代方法来实现相同的?

+0

其实,你可以有一个的docx文件的多个数据块级的富文本内容控件(通过Word或其他方式创建)。 – JasonPlutext 2014-08-29 10:08:24

回答

0

docx4j为内容控制数据绑定实现了一些名为“OpenDoPE”的约定。 (我负责这个名字,等等..)

OpenXML允许您通过XPath表达式将内容控件绑定到XML元素(在您的CustomXML数据部分中)。

使用OpenDoPE,该XML元素可以包含转义的XHTML,并且docx4j会自动将该XHTML转换为真正的Word内容。

还有就是docx4j for .NET on Nuget

+0

嗨,你可以帮我一些代码绑定到XPath表达式的XML元素的内容控制。 – mlg 2014-09-01 12:28:30

+0

在C#中,https://github.com/plutext/docx4j.NET/blob/master/docx4j.NET/src/samples/c_sharp/Docx4NET/ContentControlBind.cs – JasonPlutext 2014-09-03 08:29:32

+0

谢谢。将退房! – mlg 2014-09-11 14:54:52

0

版本你正在尝试做的是不是altChunk的一个特征。 altChunk只能在块级别插入内容,而不能在运行级别插入。此外,你可以做很少的事情来影响altChunk内容的处理。 Word(或Word Automation Services)完成它的功能,而且您无法更改。

是您导入RTF的唯一选择吗?你有任何其他可能的格式,如XHTML或?

我想到了一个非常奇怪的想法 - 如果在想要导入RTF的位置插入文本框,该怎么办?我非常肯定你可以在文本框中导入 - 事实上,你会在块级导入内容。您可以创建一个随文本一起移动的内嵌文本框。虽然不是非常简单,但也可以影响文本框相对于文本的显示位置。根据你的实际情况,这可能是可能的。

如果您要导入HTML,可以在适当的位置将HTML转换为WordprocessingML。这是更可行的。我不知道有任何工具,将RTF转换为WordprocessingML中(虽然这听起来像一个有趣的项目!)

-Eric

+0

我只需要导入RTF。我试着保持文本框与Rich文本控件相邻。但是文本框也被插入为“SdtRun”。所以我们不能在这里插入一个altChunk。你可以请检查http://openxmldeveloper.org/discussions/development_tools/f/17/t/5449.aspx – mlg 2014-09-01 09:21:32

+0

你可以检查评论吗?正如你在上面的帖子中所说的,你能告诉我如何以编程方式插入RTF的运行级内容吗?我没有要插入的图像。我只是有丰富的格式化文本。 – mlg 2014-09-01 10:51:12

+0

如果您不能使用OpenXML,那么富文本内容控件的重点是什么? – Gary 2016-08-16 20:48:57