2013-08-21 64 views
18

Tôi có khoảng 10 tài liệu từ mà tôi tạo bằng cách sử dụng xml mở và các nội dung khác. Bây giờ tôi muốn tạo một tài liệu từ khác và từng tài liệu một, tôi muốn kết hợp chúng vào tài liệu mới được tạo này. Tôi muốn sử dụng xml mở, bất kỳ gợi ý nào cũng sẽ được đánh giá cao. Dưới đây là mã của tôi:Hợp nhất nhiều tài liệu từ thành một Mở Xml

private void CreateSampleWordDocument() 
    { 
     //string sourceFile = Path.Combine("D:\\GeneralLetter.dot"); 
     //string destinationFile = Path.Combine("D:\\New.doc"); 
     string sourceFile = Path.Combine("D:\\GeneralWelcomeLetter.docx"); 
     string destinationFile = Path.Combine("D:\\New.docx"); 
     try 
     { 
      // Create a copy of the template file and open the copy 
      //File.Copy(sourceFile, destinationFile, true); 
      using (WordprocessingDocument document = WordprocessingDocument.Open(destinationFile, true)) 
      { 
       // Change the document type to Document 
       document.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document); 
       //Get the Main Part of the document 
       MainDocumentPart mainPart = document.MainDocumentPart; 
       mainPart.Document.Save(); 
      } 
     } 
     catch 
     { 
     } 
    } 

Cập nhật (sử dụng AltChunks):

using (WordprocessingDocument myDoc = WordprocessingDocument.Open("D:\\Test.docx", true)) 
     { 
      string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2) ; 
      MainDocumentPart mainPart = myDoc.MainDocumentPart; 
      AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(
       AlternativeFormatImportPartType.WordprocessingML, altChunkId); 
      using (FileStream fileStream = File.Open("D:\\Test1.docx", FileMode.Open)) 
       chunk.FeedData(fileStream); 
      AltChunk altChunk = new AltChunk(); 
      altChunk.Id = altChunkId; 
      mainPart.Document 
       .Body 
       .InsertAfter(altChunk, mainPart.Document.Body.Elements<Paragraph>().Last()); 
      mainPart.Document.Save(); 
     } 

Tại sao mã này ghi đè nội dung của các tập tin cuối cùng khi tôi sử dụng nhiều file? Cập nhật 2:

using (WordprocessingDocument myDoc = WordprocessingDocument.Open("D:\\Test.docx", true)) 
     { 

      MainDocumentPart mainPart = myDoc.MainDocumentPart; 
      string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 3); 
      AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId); 
      using (FileStream fileStream = File.Open("d:\\Test1.docx", FileMode.Open)) 
      { 
       chunk.FeedData(fileStream); 
       AltChunk altChunk = new AltChunk(); 
       altChunk.Id = altChunkId; 
       mainPart.Document 
        .Body 
        .InsertAfter(altChunk, mainPart.Document.Body 
        .Elements<Paragraph>().Last()); 
       mainPart.Document.Save(); 
      } 
      using (FileStream fileStream = File.Open("d:\\Test2.docx", FileMode.Open)) 
      { 
       chunk.FeedData(fileStream); 
       AltChunk altChunk = new AltChunk(); 
       altChunk.Id = altChunkId; 
       mainPart.Document 
        .Body 
        .InsertAfter(altChunk, mainPart.Document.Body 
        .Elements<Paragraph>().Last()); 
      } 
      using (FileStream fileStream = File.Open("d:\\Test3.docx", FileMode.Open)) 
      { 
       chunk.FeedData(fileStream); 
       AltChunk altChunk = new AltChunk(); 
       altChunk.Id = altChunkId; 
       mainPart.Document 
        .Body 
        .InsertAfter(altChunk, mainPart.Document.Body 
        .Elements<Paragraph>().Last()); 
      } 
     } 

Mã này được gắn thêm các dữ liệu Test2 hai lần, ở vị trí của dữ liệu Test1 là tốt. Phương tôi nhận được:

Test 
Test2 
Test2 

thay vì:

Test 
Test1 
Test2 
+2

Giống như chirs chỉ ra , bạn đang sử dụng cùng một Id cho tất cả các AltChunk's. Chúng phải là duy nhất. – Flowerking

+1

Ok, đã xong, Cảm ơn bạn đã kiên nhẫn với tôi. –

+1

Tôi rất vui khi thấy rằng cuối cùng bạn đã giải quyết được vấn đề của mình :) Đúng vậy, nó liên quan đến Altchunkid. Tôi đã chỉnh sửa câu trả lời của tôi vì nó có thể không rõ ràng lắm. – Chris

Trả lời

17

Chỉ sử dụng SDK OpenXML, bạn có thể sử dụng phần tử AltChunk để hợp nhất nhiều tài liệu thành một.

Liên kết này the-easy-way-to-assemble-multiple-word-documents và trang này How to Use altChunk for Document Assembly cung cấp một số mẫu.

EDIT 1

Dựa trên mã của bạn có sử dụng altchunk trong cập nhật câu hỏi (cập nhật # 1), đây là VB.đang ròng tôi đã thử nghiệm và hoạt động như một nét duyên dáng cho tôi:

Using myDoc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open("D:\\Test.docx", True) 
     Dim altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2) 
     Dim mainPart = myDoc.MainDocumentPart 
     Dim chunk = mainPart.AddAlternativeFormatImportPart(
      DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML, altChunkId) 
     Using fileStream As IO.FileStream = IO.File.Open("D:\\Test1.docx", IO.FileMode.Open) 
      chunk.FeedData(fileStream) 
     End Using 
     Dim altChunk = New DocumentFormat.OpenXml.Wordprocessing.AltChunk() 
     altChunk.Id = altChunkId 
     mainPart.Document.Body.InsertAfter(altChunk, mainPart.Document.Body.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph).Last()) 
     mainPart.Document.Save() 
End Using 

EDIT 2

Vấn đề thứ hai (cập nhật # 2)

Mã này được gắn thêm các Dữ liệu Test2 hai lần, thay cho dữ liệu Test1 là .

liên quan đến altchunkid.

Đối với mỗi tài liệu mà bạn muốn kết hợp trong tài liệu chính, bạn cần phải:

  1. thêm một AlternativeFormatImportPart trong mainDocumentPart với một Idmà phải là duy nhất. Phần tử này chứa dữ liệu Đã chèn
  2. thêm vào phần thân Altchunk trong đó bạn đặt id để tham chiếu AlternativeFormatImportPart trước đó.

Trong mã của bạn, bạn đang sử dụng cùng một Id cho tất cả các AltChunks. Đó là lý do tại sao bạn thấy nhiều thời gian cùng một văn bản.

Tôi không chắc chắn những altchunkid sẽ là duy nhất với mã của bạn: string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2);

Nếu bạn không cần phải thiết lập một giá trị cụ thể, tôi khuyên bạn nên không được thiết lập một cách rõ ràng AltChunkId khi bạn thêm AlternativeFormatImportPart. Thay vào đó, bạn nhận được một tạo ra bởi SDK như thế này:

VB.Net

Dim chunk As AlternativeFormatImportPart = mainPart.AddAlternativeFormatImportPart(DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML) 
Dim altchunkid As String = mainPart.GetIdOfPart(chunk) 

C#

AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML); 
string altchunkid = mainPart.GetIdOfPart(chunk); 
+0

Điều đó không thực hiện những gì tôi muốn làm cũng không có ngoại lệ sắp tới. Tôi đang gửi mã cập nhật của tôi với Altchunks. –

+0

Tôi có cần phải làm gì đó trong tệp docx không, như thêm loại dấu trang hành động khác? –

+1

@ItiTyagi Không, trong bài kiểm tra của tôi, tôi vừa tạo hai tệp với một văn bản đơn giản (Text1 và Text2). Và sau khi chạy mã này, tệp Test.docx chứa hai đoạn văn khi tôi mở nó. – Chris

7

Có một wrapper API đẹp (Document Builder 2.2) xung quanh xml mở được thiết kế đặc biệt để nhập văn bản, với sự linh hoạt của việc lựa chọn các đoạn sáp nhập v.v. Bạn có thể tải xuống từ here.

Tài liệu và màn hình phôi về cách sử dụng nó là here.

Cập nhật: Mã mẫu

var sources = new List<Source>(); 
//Document Streams (File Streams) of the documents to be merged. 
foreach (var stream in documentstreams) 
{ 
     var tempms = new MemoryStream(); 
     stream.CopyTo(tempms); 
     sources.Add(new Source(new WmlDocument(stream.Length.ToString(), tempms), true)); 
} 

    var mergedDoc = DocumentBuilder.BuildDocument(sources); 
    mergedDoc.SaveAs(@"C:\TargetFilePath"); 

loại SourceWmlDocument là từ tài liệu Builder API.

Bạn thậm chí có thể thêm các đường dẫn tập tin trực tiếp nếu bạn chọn như:

sources.Add(new Source(new WmlDocument(@"C:\FileToBeMerged1.docx")); 
sources.Add(new Source(new WmlDocument(@"C:\FileToBeMerged2.docx")); 

Tìm thấy Nice Comparison này giữa AltChunkDocument Builder cách tiếp cận để hợp nhất các tài liệu - hữu ích để lựa chọn dựa trên những yêu cầu này.

Bạn cũng có thể sử dụng thư viện DocX để hợp nhất tài liệu nhưng tôi thích Trình tạo tài liệu hơn điều này để hợp nhất tài liệu.

Hy vọng điều này sẽ hữu ích.

+0

Có cách nào trong mở xml thông qua mã hóa vì tác vụ này thực sự đang ăn tôi, và tôi không thể sử dụng bất kỳ công cụ nào khác, v.v. –

+1

Các thư viện này là các trình bao bọc mã mở xung quanh OpenXml. Trình tạo tài liệu đang sử dụng SDK Xml mở để thực hiện quá trình hợp nhất và không có phụ thuộc cứng. Việc hợp nhất các tài liệu không phải là một nhiệm vụ đơn giản, cùng với nội dung bạn phải di chuyển các kiểu + các phần xml mở khác mà không mất các mối quan hệ! Và điều này trở thành một cơn ác mộng khi bạn có hình ảnh trong tài liệu. Mã nguồn của Trình tạo tài liệu Api sẽ cung cấp cho bạn một ý tưởng giống nhau. – Flowerking

+0

Tôi chỉ cần thêm nội dung, dưới dạng trang, để tôi có thể in một lần. –

3

Dễ dàng sử dụng trong C#:

using System; 
using System.IO; 
using System.Linq; 
using DocumentFormat.OpenXml.Packaging; 
using DocumentFormat.OpenXml.Wordprocessing; 

namespace WordMergeProject 
{ 
    public class Program 
    { 
     private static void Main(string[] args) 
     { 
      byte[] word1 = File.ReadAllBytes(@"..\..\word1.docx"); 
      byte[] word2 = File.ReadAllBytes(@"..\..\word2.docx"); 

      byte[] result = Merge(word1, word2); 

      File.WriteAllBytes(@"..\..\word3.docx", result); 
     } 

     private static byte[] Merge(byte[] dest, byte[] src) 
     { 
      string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString(); 

      var memoryStreamDest = new MemoryStream(); 
      memoryStreamDest.Write(dest, 0, dest.Length); 
      memoryStreamDest.Seek(0, SeekOrigin.Begin); 
      var memoryStreamSrc = new MemoryStream(src); 

      using (WordprocessingDocument doc = WordprocessingDocument.Open(memoryStreamDest, true)) 
      { 
       MainDocumentPart mainPart = doc.MainDocumentPart; 
       AlternativeFormatImportPart altPart = 
        mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId); 
       altPart.FeedData(memoryStreamSrc); 
       var altChunk = new AltChunk(); 
       altChunk.Id = altChunkId; 
           OpenXmlElement lastElem = mainPart.Document.Body.Elements<AltChunk>().LastOrDefault(); 
      if(lastElem == null) 
      { 
       lastElem = mainPart.Document.Body.Elements<Paragraph>().Last(); 
      } 


      //Page Brake einfügen 
      Paragraph pageBreakP = new Paragraph(); 
      Run pageBreakR = new Run(); 
      Break pageBreakBr = new Break() { Type = BreakValues.Page }; 

      pageBreakP.Append(pageBreakR); 
      pageBreakR.Append(pageBreakBr);     

      return memoryStreamDest.ToArray(); 
     } 
    } 
} 
+0

Có điều gì đó thiếu trong mã trong câu trả lời này. – Boric

+0

Bạn đang làm gì với lastElem? Nó dường như được thiết lập nhưng sau đó không được sử dụng. – Rendition