2016-05-18 6 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)); 
     } 
    }` 

Если открыть объединенный документ с словом я могу видеть его содержание (таблицы, текст, пункты ..), но если я open, если из кода снова сказано, что внутренний текст - «" (пустая строка). Мне нужен этот внутренний текст, чтобы отразить то, что содержит документ, потому что мне нужно заменить некоторые заполнители, такие как «@@ 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) будет полезно вам. –