2016-05-18 28 views
1

我想將多個文檔合併成一個文檔,然後打開結果文檔並進一步處理它。使用AltChunks的合併文檔的空格爲空

「ChunkId」是每次調用此方法以增加唯一標識時增加的屬性。我遵循this site的例子。 這是用於合併多個文件(使用altchunks)代碼: `

private void MergeDocument(string mergePath, bool appendPageBreak) 
    { 
     if (!File.Exists(mergePath)) 
     { 
      Log.Warn(string.Format("Document: \"{0}\" was not found.", mergePath)); 
      return; 
     } 

     ChunkId++; 
     var altChunkId = "AltChunkId" + ChunkId; 

     var mainDocPart = DestinationDocument.MainDocumentPart; 
     if (mainDocPart == null) 
     { 
      DestinationDocument.AddMainDocumentPart(); 
      mainDocPart = DestinationDocument.MainDocumentPart; 
      if (mainDocPart.Document == null) 
       mainDocPart.Document = new Document { Body = new Body() }; 
     } 

     try 
     { 
      var chunk = mainDocPart.AddAlternativeFormatImportPart(
       AlternativeFormatImportPartType.WordprocessingML, altChunkId); 
      if (chunk != null) 
       using (var ms = new FileStream(mergePath, FileMode.Open)) 
       { 
        chunk.FeedData(ms); 
       } 
      else 
      { 
       Log.Error(string.Format("Merge - Failed to create chunk document based on \"{0}\".", mergePath)); 
       return; // failed to create chunk document, return from merge method 

      } 
     } 
     catch (Exception e) 
     { 
      Log.Error(string.Format("Merge - Failed to insert chunk document based on \"{0}\".", mergePath)); 
      return; // failed to create chunk document, return from merge method 

     } 

     var altChunk = new AltChunk { Id = altChunkId }; 

     //append the page break 
     if (appendPageBreak) 
      try 
      { 
       AppendPageBreak(mainDocPart); 
       Log.Info(string.Format("Successfully appended page break.")); 
      } 
      catch (Exception ex) 
      { 
       Log.Error(string.Format("Eror appending page break. Message: \"{0}\".", ex.Message)); 
       return; // return if page break insertion failed 
      } 

     // insert the document 
     var last = mainDocPart.Document 
     .Body 
     .Elements() 
     .LastOrDefault(e => e is Paragraph || e is AltChunk); 
     try 
     { 
      if (last == null) 
       mainDocPart.Document.Body.InsertAt(altChunk, 0); 
      else 
       last.InsertAfterSelf(altChunk); 
      Log.Info(string.Format("Successfully inserted new doc \"{0}\" into destination.", mergePath)); 
     } 
     catch (Exception ex) 
     { 
      Log.Error(string.Format("Error merging document \"{0}\". Message: \"{1}\".", mergePath, ex.Message)); 
      return; // return if the merge was not successfull 
     } 

     try 
     { 
      mainDocPart.Document.Save(); 
     } 
     catch (Exception ex) 
     { 
      Log.Error(string.Format("Error saving document \"{0}\". Message: \"{1}\".", mergePath, ex.Message)); 
     } 
    }` 

如果我打開合併文檔與Word我可以看到它的內容(表格,文字,段落..),但如果我如果從代碼再次打開它說內部文本是「」(空字符串)。我需要內部文本來反映文檔包含的內容,因爲我必須用另一個文本替換一些佔位符,如「@@ name @@」,如果內部文本爲空,我不能。

這是合併文檔的innerxml,

enter image description here

我這是怎麼打開的合併文檔:

DestinationDocument = WordprocessingDocument.Open(Path.GetFullPath(destinationPath), true);

我如何可以讀取文檔的內部文本?或者我怎樣才能將這些文件合併成一個文件,以避免這個問題再發生?

回答

1

當文檔與AltChunk合併時,它就像嵌入的附件到原始單詞文檔。客戶端(MS Word)處理altchunk部分的渲染。因此,生成的文檔將不具有合併文檔的openxml標記。

如果您想使用生成的文檔進行進一步的編程後處理,請使用Openxml Power Tools。 pelase參考我的答案here

OpenXML的電動工具 - https://github.com/OfficeDev/Open-Xml-PowerTools

+0

謝謝你,工作就像一個魅力。要解決的唯一問題是如果可以在使用DocumentBuilder的文檔之後插入分頁符。好先生@Flowerking,再次感謝您:D – Simonca

+0

您知道一種將.rtf文件轉換爲.docx文件的方式嗎?我需要將.rtf文檔與.docx合併,並且DocumentBuilder需要.docx文件。 – Simonca

0

的問題是,這些文件是不是真的合併(本身),該altChunk元素只定義了替代內容應放在一個地方該文件及其對該替代內容的參考。
當你在MS Word中打開這個文檔時,它會自動爲你自動合併所有這些替代內容。因此,當您使用MS Word重新保存該文檔時,將不再有altChunk元素。

不過你可以做實際上是與那些altChunk docx文件(孩子DOCX文檔)就像你與主要 DOCX文件(父文件)做處理。

例如:

string destinationPath = "Sample.docx"; 
string search = "@@[email protected]@"; 
string replace ="John Doe"; 

using (var parent = WordprocessingDocument.Open(Path.GetFullPath(destinationPath), true)) 
{ 
    foreach (var altChunk in parent.MainDocumentPart.GetPartsOfType<AlternativeFormatImportPart>()) 
    { 
     if (Path.GetExtension(altChunk.Uri.OriginalString) != ".docx") 
      continue; 

     using (var child = WordprocessingDocument.Open(altChunk.GetStream(), true)) 
     { 
      var foundText = child.MainDocumentPart.Document.Body 
       .Descendants<Text>() 
       .Where(t => t.Text.Contains(search)) 
       .FirstOrDefault(); 

      if (foundText != null) 
      { 
       foundText.Text = foundText.Text.Replace(search, replace); 
       break; 
      } 
     } 
    } 
} 

或者你需要使用一些方法來合併這些文件真實的。 Flowerking提到了一種解決方案,您可以嘗試的另一種解決方案是使用GemBox.Document庫。它會在加載時爲你合併這些替代內容(就像MS Word打開時那樣)。

例如:

string destinationPath = "Sample.docx"; 
string search = "@@[email protected]@"; 
string replace = "John Doe"; 

DocumentModel document = DocumentModel.Load(destinationPath); 

ContentRange foundText = document.Content.Find(search).FirstOrDefault(); 
if (foundText != null) 
    foundText.LoadText(replace); 

document.Save(destinationPath); 
+0

謝謝你的回答,這也有幫助,但是我不能使用GemBox.Document庫,因爲它被限制爲20段作爲免費版本 – Simonca

+0

是的,自由模式有大小限制。不過,我希望第一個建議(打開altChunk DOCX)對您有用。 –