2009-04-30 41 views
38

Bối cảnh: Tôi cần cung cấp gói báo cáo hàng tuần cho nhân viên bán hàng của mình. Gói này chứa một số báo cáo tinh thể (5-10).Kết hợp hai (hoặc nhiều) PDF

Sự cố: Tôi muốn cho phép người dùng chạy tất cả báo cáo và cũng chỉ chạy một báo cáo. Tôi đã suy nghĩ tôi có thể làm điều này bằng cách tạo ra các báo cáo và sau đó thực hiện:

List<ReportClass> reports = new List<ReportClass>(); 
reports.Add(new WeeklyReport1()); 
reports.Add(new WeeklyReport2()); 
reports.Add(new WeeklyReport3()); 
<snip> 

foreach (ReportClass report in reports) 
{ 
    report.ExportToDisk(ExportFormatType.PortableDocFormat, @"c:\reports\" + report.ResourceName + ".pdf"); 
} 

Điều này sẽ cung cấp cho tôi một thư mục đầy đủ các báo cáo, nhưng tôi muốn gửi email cho tất cả mọi người một PDF duy nhất với tất cả các báo cáo hàng tuần. Vì vậy, tôi cần phải kết hợp chúng.

Có cách nào dễ dàng để thực hiện việc này mà không cần cài đặt thêm bất kỳ kiểm soát của bên thứ ba nào khác không? Tôi đã có DevExpress & CrystalReports và tôi không muốn thêm quá nhiều nữa.

Tốt nhất là nên kết hợp chúng trong vòng lặp foreach hoặc trong một vòng lặp riêng biệt? (Hoặc một cách thay thế)

Cảm ơn

+0

Dường như tôi sẽ cần một số thư viện của bên thứ ba, cảm ơn tất cả sự trợ giúp. –

Trả lời

54

Tôi đã phải giải quyết một vấn đề tương tự và những gì tôi đã kết thúc làm là tạo ra một tiện ích pdfmerge nhỏ sử dụng dự án PDFSharp mà về cơ bản là MIT được cấp phép.

Mã này đã chết đơn giản, tôi cần một tiện ích cmdline vì vậy tôi có nhiều mã dành riêng cho phân tích các lý lẽ hơn tôi làm cho việc sáp nhập PDF:

using (PdfDocument one = PdfReader.Open("file1.pdf", PdfDocumentOpenMode.Import)) 
using (PdfDocument two = PdfReader.Open("file2.pdf", PdfDocumentOpenMode.Import)) 
using (PdfDocument outPdf = new PdfDocument()) 
{     
    CopyPages(one, outPdf); 
    CopyPages(two, outPdf); 

    outPdf.Save("file1and2.pdf"); 
} 

void CopyPages(PdfDocument from, PdfDocument to) 
{ 
    for (int i = 0; i < from.PageCount; i++) 
    { 
     to.AddPage(from.Pages[i]); 
    } 
} 
+0

Ah trông giống như Martin đánh bại tôi với nó, tôi nói rằng đó là bởi vì tôi đã đào lên mẫu mã của tôi :) –

+0

Hi andrew bạn sẽ xin hãy xem này .... pls http://stackoverflow.com/ Câu hỏi/6953471/system-crashing-when-the-print-button-is-clicked – user682417

+0

Có ai khác nhận được "Một tham chiếu đối tượng là cần thiết cho trường không tĩnh, phương pháp, hoặc tài sản ..." lỗi cho điều này, xung quanh CopyPages (một, outDocument); CopyPages (hai, outDocument); – user001

4

PDFsharp dường như cho phép sáp nhập nhiều tài liệu PDF thành một.

Và điều tương tự cũng có thể xảy ra với ITextSharp.

0

tôi đã làm điều này với PDFBox. Tôi cho rằng nó hoạt động tương tự như iTextSharp.

1

Tôi biết rất nhiều người đã đề nghị PDF Sharp, tuy nhiên nó không giống như dự án đã được cập nhật kể từ tháng sáu năm 2008. Hơn nữa, nguồn không có sẵn.

Cá nhân, tôi đã chơi với iTextSharp vốn khá dễ làm việc.

+1

[PDFsharp 1,32 incl. nguồn] (http://sourceforge.net/projects/pdfsharp/files/pdfsharp/PDFsharp%201.32/) (2012-03-07) – CodeFox

2

Có một số câu trả lời hay ở đây rồi, nhưng tôi nghĩ tôi có thể đề cập rằng pdftk có thể hữu ích cho tác vụ này. Thay vì tạo ra một PDF trực tiếp, bạn có thể tạo ra mỗi PDF bạn cần và sau đó kết hợp chúng lại với nhau như một quá trình sau với pdftk. Điều này thậm chí có thể được thực hiện từ bên trong chương trình của bạn bằng cách sử dụng một cuộc gọi system() hoặc ShellExecute().

14

Đây là một chức năng duy nhất mà sẽ hợp nhất số tiền X của PDF bằng PDFSharp

public static void MergePDFs(string targetPath, params string[] pdfs) { 
    using(PdfDocument targetDoc = new PdfDocument()){ 
     foreach (string pdf in pdfs) { 
      using (PdfDocument pdfDoc = PdfReader.Open(pdf, PdfDocumentOpenMode.Import)) { 
       for (int i = 0; i < pdfDoc.PageCount; i++) { 
        targetDoc.AddPage(pdfDoc.Pages[i]); 
       } 
      } 
     } 
     targetDoc.Save(targetPath); 
    } 
} 
1

tôi đã sử dụng iTextSharp với C# để kết hợp các file pdf. Đây là mã tôi đã sử dụng.

string[] lstFiles=new string[3]; 
    lstFiles[0][email protected]"C:/pdf/1.pdf"; 
    lstFiles[1][email protected]"C:/pdf/2.pdf"; 
    lstFiles[2][email protected]"C:/pdf/3.pdf"; 

    PdfReader reader = null; 
    Document sourceDocument = null; 
    PdfCopy pdfCopyProvider = null; 
    PdfImportedPage importedPage; 
    string [email protected]"C:/pdf/new.pdf"; 


    sourceDocument = new Document(); 
    pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPdfPath, System.IO.FileMode.Create)); 

    //Open the output file 
    sourceDocument.Open(); 

    try 
    { 
     //Loop through the files list 
     for (int f = 0; f < lstFiles.Length-1; f++) 
     { 
      int pages =get_pageCcount(lstFiles[f]); 

      reader = new PdfReader(lstFiles[f]); 
      //Add pages of current file 
      for (int i = 1; i <= pages; i++) 
      { 
       importedPage = pdfCopyProvider.GetImportedPage(reader, i); 
       pdfCopyProvider.AddPage(importedPage); 
      } 

      reader.Close(); 
     } 
     //At the end save the output file 
     sourceDocument.Close(); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 


private int get_pageCcount(string file) 
{ 
    using (StreamReader sr = new StreamReader(File.OpenRead(file))) 
    { 
     Regex regex = new Regex(@"/Type\s*/Page[^s]"); 
     MatchCollection matches = regex.Matches(sr.ReadToEnd()); 

     return matches.Count; 
    } 
} 
1

Kết hợp hai byte[] sử dụng iTextSharp lên đến phiên bản 5.x:

internal static MemoryStream mergePdfs(byte[] pdf1, byte[] pdf2) 
{ 
    MemoryStream outStream = new MemoryStream(); 
    using (Document document = new Document()) 
    using (PdfCopy copy = new PdfCopy(document, outStream)) 
    { 
     document.Open(); 
     copy.AddDocument(new PdfReader(pdf1)); 
     copy.AddDocument(new PdfReader(pdf2)); 
    } 
    return outStream; 
} 

Thay vì byte[] 's nó có thể vượt qua cũng Stream' s

+0

Tôi đã thêm thông tin vào thư viện bên ngoài mà mã của bạn yêu cầu. Vui lòng luôn thêm tất cả thông tin cần thiết để sử dụng câu trả lời của bạn. – mkl

3

Đây là điều mà tôi đã tìm và muốn chia sẻ với bạn.

public static byte[] MergePdf(List<byte[]> pdfs) 
    { 
     List<PdfSharp.Pdf.PdfDocument> lstDocuments = new List<PdfSharp.Pdf.PdfDocument>(); 
     foreach (var pdf in pdfs) 
     { 
      lstDocuments.Add(PdfReader.Open(new MemoryStream(pdf), PdfDocumentOpenMode.Import)); 
     } 

     using (PdfSharp.Pdf.PdfDocument outPdf = new PdfSharp.Pdf.PdfDocument()) 
     { 
      for(int i = 1; i<= lstDocuments.Count; i++) 
      { 
       foreach(PdfSharp.Pdf.PdfPage page in lstDocuments[i-1].Pages) 
       { 
        outPdf.AddPage(page); 
       } 
      } 

      MemoryStream stream = new MemoryStream(); 
      outPdf.Save(stream, false); 
      byte[] bytes = stream.ToArray(); 

      return bytes; 
     }   
    } 
1

tôi kết hợp hai ở trên, vì tôi cần phải hợp nhất 3 pdfbytes và trả về một byte

internal static byte[] mergePdfs(byte[] pdf1, byte[] pdf2,byte[] pdf3) 
     { 
      MemoryStream outStream = new MemoryStream(); 
      using (Document document = new Document()) 
      using (PdfCopy copy = new PdfCopy(document, outStream)) 
      { 
       document.Open(); 
       copy.AddDocument(new PdfReader(pdf1)); 
       copy.AddDocument(new PdfReader(pdf2)); 
       copy.AddDocument(new PdfReader(pdf3)); 
      } 
      return outStream.ToArray(); 
     } 
0

Tiếp theo phương pháp được một mảng List của byte đó là PDF byte mảng và sau đó trả về một mảng byte .

using ...; 
using PdfSharp.Pdf; 
using PdfSharp.Pdf.IO; 

public static class PdfHelper 
{ 
    public static byte[] PdfConcat(List<byte[]> lstPdfBytes) 
    { 
     byte[] res; 

     using (var outPdf = new PdfDocument()) 
     { 
      foreach (var pdf in lstPdfBytes) 
      { 
       using (var pdfStream = new MemoryStream(pdf)) 
       using (var pdfDoc = PdfReader.Open(pdfStream, PdfDocumentOpenMode.Import)) 
        for (var i = 0; i < pdfDoc.PageCount; i++) 
         outPdf.AddPage(pdfDoc.Pages[i]); 
      } 

      using (var memoryStreamOut = new MemoryStream()) 
      { 
       outPdf.Save(memoryStreamOut, false); 

       res = Stream2Bytes(memoryStreamOut); 
      } 
     } 

     return res; 
    } 

    public static void DownloadAsPdfFile(string fileName, byte[] content) 
    { 
     var ms = new MemoryStream(content); 

     HttpContext.Current.Response.Clear(); 
     HttpContext.Current.Response.ContentType = "application/pdf"; 
     HttpContext.Current.Response.AddHeader("content-disposition", $"attachment;filename={fileName}.pdf"); 
     HttpContext.Current.Response.Buffer = true; 
     ms.WriteTo(HttpContext.Current.Response.OutputStream); 
     HttpContext.Current.Response.End(); 
    } 

    private static byte[] Stream2Bytes(Stream input) 
    { 
     var buffer = new byte[input.Length]; 
     using (var ms = new MemoryStream()) 
     { 
      int read; 
      while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
       ms.Write(buffer, 0, read); 

      return ms.ToArray(); 
     } 
    } 
} 

Vì vậy, kết quả của PdfHelper.PdfConcat phương pháp được thông qua với PdfHelper.DownloadAsPdfFile phương pháp.

PS: Gói NuGet có tên [PdfSharp][1] cần được cài đặt. Vì vậy, trong các loại Package Manage Console cửa sổ:

Install-Package PdfSharp

0

Dưới đây là một ví dụ sử dụng iTextSharp

public static void MergePdf(Stream outputPdfStream, IEnumerable<string> pdfFilePaths) 
{ 
    using (var document = new Document()) 
    using (var pdfCopy = new PdfCopy(document, outputPdfStream)) 
    { 
     pdfCopy.CloseStream = false; 
     try 
     { 
      document.Open(); 
      foreach (var pdfFilePath in pdfFilePaths) 
      { 
       using (var pdfReader = new PdfReader(pdfFilePath)) 
       { 
        pdfCopy.AddDocument(pdfReader); 
        pdfReader.Close(); 
       } 
      } 
     } 
     finally 
     { 
      document?.Close(); 
     } 
    } 
} 

Các constructor PdfReader có nhiều quá tải. Có thể thay thế loại thông số IEnumerable<string> bằng IEnumerable<Stream> và nó cũng sẽ hoạt động. Xin lưu ý rằng phương thức này không đóng OutputStream, nó ủy nhiệm nhiệm vụ đó cho người tạo luồng.

Các vấn đề liên quan