2014-08-28 135 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