59

Well i'm trying to merge multiple PDFs in to one.

I gives no errors while compiling. I tried to merge the docs first but that went wrong because I'm working with tables.

This is the asp.net code-behind

if (Button.Equals("PreviewWord")) {

        String eventTemplate = Server.MapPath("/ERAS/Badges/Template/EventTemp" + EventName + ".doc");

        String SinglePreview = Server.MapPath("/ERAS/Badges/Template/PreviewSingle" + EventName + ".doc");

        String PDFPreview = Server.MapPath("/ERAS/Badges/Template/PDFPreviewSingle" + EventName + ".pdf");

        String previewPDFs = Server.MapPath("/ERAS/Badges/Template/PreviewPDFs" + EventName + ".pdf");

        if (System.IO.File.Exists((String)eventTemplate))
        {

            if (vulGegevensIn == true)
            {
              //This creates a Worddocument and fills in names etc from database
                CreateWordDocument(vulGegevensIn, eventTemplate, SinglePreview, false);
                //This saves the SinglePreview.doc as a PDF @param place of PDFPreview
                CreatePDF(SinglePreview, PDFPreview);


                //Trying to merge
                String[] previewsSmall=new String[1];
                previewsSmall[0] = PDFPreview;
                PDFMergenITextSharp.MergeFiles(previewPDFs, previewsSmall);
            }


            // merge PDFs here...........................;
            //here
            //no here//
            //...


    } }

This is the PDFMergenITextSharpClass

public static class PDFMergenITextSharp {

public static void MergeFiles(string destinationFile, string[] sourceFiles)
{

    try
    {
        int f = 0;
        // we create a reader for a certain document
        PdfReader reader = new PdfReader(sourceFiles[f]);
        // we retrieve the total number of pages
        int n = reader.NumberOfPages;
        //Console.WriteLine("There are " + n + " pages in the original file.");
        // step 1: creation of a document-object
        Document document = new Document(reader.GetPageSizeWithRotation(1));
        // step 2: we create a writer that listens to the document
        PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
        // step 3: we open the document
        document.Open();
        PdfContentByte cb = writer.DirectContent;
        PdfImportedPage page;
        int rotation;
        // step 4: we add content
        while (f < sourceFiles.Length)
        {
            int i = 0;
            while (i < n)
            {
                i++;
                document.SetPageSize(reader.GetPageSizeWithRotation(i));
                document.NewPage();
                page = writer.GetImportedPage(reader, i);
                rotation = reader.GetPageRotation(i);
                if (rotation == 90 || rotation == 270)
                {
                    cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
                }
                else
                {
                    cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
                }
                //Console.WriteLine("Processed page " + i);
            }
            f++;
            if (f < sourceFiles.Length)
            {
                reader = new PdfReader(sourceFiles[f]);
                // we retrieve the total number of pages
                n = reader.NumberOfPages;
                //Console.WriteLine("There are " + n + " pages in the original file.");
            }
        }
        // step 5: we close the document
        document.Close();
    }
    catch (Exception e)
    {
        string strOb = e.Message;
    }
}

public static int CountPageNo(string strFileName)
{
    // we create a reader for a certain document
    PdfReader reader = new PdfReader(strFileName);
    // we retrieve the total number of pages
    return reader.NumberOfPages;
}
}
Liquid
  • 1,871
  • 1
  • 17
  • 32
  • 4
    Use PdfCopy instead of PdfWriter. There should be several samples & related questions floating around. – Mark Storer May 17 '11 at 21:31
  • 1
    @Liquid -- CreatePDF(SinglePreview, PDFPreview); Can you please share how you created a pdf from doc. It will be very helpful if you provide some details about how u converted. I hope you are using iTextSharp for doing the doc to pdf converstion. – kbvishnu Aug 23 '14 at 14:00

7 Answers7

73

I found the answer:

Instead of the 2nd Method, add more files to the first array of input files.

public static void CombineMultiplePDFs(string[] fileNames, string outFile)
{
    // step 1: creation of a document-object
    Document document = new Document();
    //create newFileStream object which will be disposed at the end
    using (FileStream newFileStream = new FileStream(outFile, FileMode.Create))
    {
       // step 2: we create a writer that listens to the document
       PdfCopy writer = new PdfCopy(document, newFileStream);

       // step 3: we open the document
       document.Open();

       foreach (string fileName in fileNames)
       {
           // we create a reader for a certain document
           PdfReader reader = new PdfReader(fileName);
           reader.ConsolidateNamedDestinations();

           // step 4: we add content
           for (int i = 1; i <= reader.NumberOfPages; i++)
           {
               PdfImportedPage page = writer.GetImportedPage(reader, i);
               writer.AddPage(page);
           }

           PRAcroForm form = reader.AcroForm;
           if (form != null)
           {
               writer.CopyAcroForm(reader);
           }

           reader.Close();
       }

       // step 5: we close the document and writer
       writer.Close();
       document.Close();
   }//disposes the newFileStream object
}
    
Gh61
  • 9,222
  • 4
  • 28
  • 39
Liquid
  • 1,871
  • 1
  • 17
  • 32
  • 2
    @liquid - sorry, can you state what references you used for this to work? – cgraham720 Apr 02 '16 at 19:15
  • @cgraham720 trail and error? I think the reference at that time should have been my professor at school I think. – Liquid May 22 '16 at 12:31
  • 34
    "PdfCopy does not contain a definition for CopyAcroForm" – Christine Jun 24 '16 at 17:00
  • I'd also take a look at this answer: https://stackoverflow.com/questions/38339151/c-sharp-itextsharp-merge-multiple-pdf-via-byte-array – Ricardo Appleton May 26 '17 at 10:39
  • 2
    Had to change the line `PRAcroForm form = reader.AcroForm;` to `PrAcroForm form = reader.AcroForm;` (small 'r' instead of capital, otherwise I got an error - however the edit was not taken into consideration for this part...) – misanthrop Jul 18 '18 at 06:38
  • 1
    @misanthrop the edit wasn't taken into consideration because the class name of that object is with a capital R "PRAcroForm". But I don't know which iTextsharp version you are using. But I'm still glad that this helped you on your way – Liquid Jul 18 '18 at 13:05
  • 3
    We are using iTextSharp.LGPLv2.Core which indeed is an unofficial port of iTextSharp(v4.1.6), maybe it has something to do with this... maybe this comment helps also someone else as well =) – misanthrop Jul 19 '18 at 11:44
  • Thanks @misanthrop. This helped me :). Thanks for the answer guys! If it helps anyone else, you can also write the PDF to a MemoryStream and use `FileContentResult(memoryStream.ToArray(), "application/pdf")` if you need to serve the file to a front-end application that will handle the client download. Appreciate it guys! – tfarmer4 Apr 30 '20 at 15:35
48

I found a very nice solution on this site : http://weblogs.sqlteam.com/mladenp/archive/2014/01/10/simple-merging-of-pdf-documents-with-itextsharp-5-4-5.aspx

I update the method in this mode :

public static bool MergePdfs(IEnumerable<string> fileNames, string targetFileName)
{
    bool success = true;
    using (FileStream stream = new(targetFileName, FileMode.Create))
    {
        Document document = new();
        PdfCopy pdf = new(document, stream);
        PdfReader? reader = null;

        try
        {
            document.Open();
            foreach (string file in fileNames)
            {
                reader = new PdfReader(file);
                pdf.AddDocument(reader);
                reader.Close();
            }
        }
        catch (Exception)
        {
            success = false;
            reader?.Close();
        }
        finally
        {
            document?.Close();
        }
    }

    return success;
}
91378246
  • 367
  • 2
  • 5
  • 21
Alexei Bondarev
  • 812
  • 7
  • 9
  • 7
    I prefer this solution, since it does not involve the deprecated `CopyAcroForm` functionality, that is no longer available in the latest version of `itextsharp`. – Matze Mar 27 '16 at 19:20
  • Works perfectly for me with a few documents and last version of itextsharp available on nuget :) – AFract May 30 '17 at 08:45
  • As far as I can tell, there's virtually no reason not to use PdfSmartCopy over PdfCopy. At least for me, the size saving on the PDF was very significant. – Bacon Bits Nov 21 '18 at 16:14
14

Code For Merging PDF's in Itextsharp

public static void Merge(List<String> InFiles, String OutFile)
{
    using (FileStream stream = new FileStream(OutFile, FileMode.Create))
    using (Document doc = new Document())
    using (PdfCopy pdf = new PdfCopy(doc, stream))
    {
        doc.Open();

        PdfReader reader = null;
        PdfImportedPage page = null;

        //fixed typo
        InFiles.ForEach(file =>
        {
            reader = new PdfReader(file);

            for (int i = 0; i < reader.NumberOfPages; i++)
            {
                page = pdf.GetImportedPage(reader, i + 1);
                pdf.AddPage(page);
            }

            pdf.FreeReader(reader);
            reader.Close();
            File.Delete(file);
        });
    }
}
Jim G.
  • 15,141
  • 22
  • 103
  • 166
vivekBhardwaj
  • 149
  • 1
  • 3
  • 29
    A person copying&pasting your code without seriously reading it might get into quite some trouble: Not in every merging use case the source files are to be deleted! – mkl Aug 19 '16 at 08:50
  • This still worked. Make sure you understand what File.Delete(file); do. – Nandostyle Mar 24 '22 at 18:17
7

Using iTextSharp.dll

protected void Page_Load(object sender, EventArgs e)
{
    String[] files = @"C:\ENROLLDOCS\A1.pdf,C:\ENROLLDOCS\A2.pdf".Split(',');
    MergeFiles(@"C:\ENROLLDOCS\New1.pdf", files);
}
public void MergeFiles(string destinationFile, string[] sourceFiles)
{
    if (System.IO.File.Exists(destinationFile))
        System.IO.File.Delete(destinationFile);

    string[] sSrcFile;
    sSrcFile = new string[2];

    string[] arr = new string[2];
    for (int i = 0; i <= sourceFiles.Length - 1; i++)
    {
        if (sourceFiles[i] != null)
        {
            if (sourceFiles[i].Trim() != "")
                arr[i] = sourceFiles[i].ToString();
        }
    }

    if (arr != null)
    {
        sSrcFile = new string[2];

        for (int ic = 0; ic <= arr.Length - 1; ic++)
        {
            sSrcFile[ic] = arr[ic].ToString();
        }
    }
    try
    {
        int f = 0;

        PdfReader reader = new PdfReader(sSrcFile[f]);
        int n = reader.NumberOfPages;
        Response.Write("There are " + n + " pages in the original file.");
        Document document = new Document(PageSize.A4);

        PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));

        document.Open();
        PdfContentByte cb = writer.DirectContent;
        PdfImportedPage page;

        int rotation;
        while (f < sSrcFile.Length)
        {
            int i = 0;
            while (i < n)
            {
                i++;

                document.SetPageSize(PageSize.A4);
                document.NewPage();
                page = writer.GetImportedPage(reader, i);

                rotation = reader.GetPageRotation(i);
                if (rotation == 90 || rotation == 270)
                {
                    cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
                }
                else
                {
                    cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
                }
                Response.Write("\n Processed page " + i);
            }

            f++;
            if (f < sSrcFile.Length)
            {
                reader = new PdfReader(sSrcFile[f]);
                n = reader.NumberOfPages;
                Response.Write("There are " + n + " pages in the original file.");
            }
        }
        Response.Write("Success");
        document.Close();
    }
    catch (Exception e)
    {
        Response.Write(e.Message);
    }


}
Syed Mohamed
  • 1,339
  • 1
  • 15
  • 23
4

Merge byte arrays of multiple PDF files:

    public static byte[] MergePDFs(List<byte[]> pdfFiles)
    {  
        if (pdfFiles.Count > 1)
        {
            PdfReader finalPdf;
            Document pdfContainer;
            PdfWriter pdfCopy;
            MemoryStream msFinalPdf = new MemoryStream();

            finalPdf = new PdfReader(pdfFiles[0]);
            pdfContainer = new Document();
            pdfCopy = new PdfSmartCopy(pdfContainer, msFinalPdf);

            pdfContainer.Open();

            for (int k = 0; k < pdfFiles.Count; k++)
            {
                finalPdf = new PdfReader(pdfFiles[k]);
                for (int i = 1; i < finalPdf.NumberOfPages + 1; i++)
                {
                    ((PdfSmartCopy)pdfCopy).AddPage(pdfCopy.GetImportedPage(finalPdf, i));
                }
                pdfCopy.FreeReader(finalPdf);

            }
            finalPdf.Close();
            pdfCopy.Close();
            pdfContainer.Close();

            return msFinalPdf.ToArray();
        }
        else if (pdfFiles.Count == 1)
        {
            return pdfFiles[0];
        }
        return null;
    }
emert117
  • 1,268
  • 2
  • 20
  • 38
1

I don't see this solution anywhere and supposedly ... according to one person, the proper way to do it is with copyPagesTo(). This does work I tested it. Your mileage may vary between city and open road driving. Goo luck.

    public static bool MergePDFs(List<string> lststrInputFiles, string OutputFile, out int iPageCount, out string strError)
    {
        strError = string.Empty;

        PdfWriter pdfWriter = new PdfWriter(OutputFile);
        PdfDocument pdfDocumentOut = new PdfDocument(pdfWriter);

        PdfReader pdfReader0 = new PdfReader(lststrInputFiles[0]);
        PdfDocument pdfDocument0 = new PdfDocument(pdfReader0);
        int iFirstPdfPageCount0 = pdfDocument0.GetNumberOfPages();
        pdfDocument0.CopyPagesTo(1, iFirstPdfPageCount0, pdfDocumentOut);
        iPageCount = pdfDocumentOut.GetNumberOfPages();

        for (int ii = 1; ii < lststrInputFiles.Count; ii++)
        {
            PdfReader pdfReader1 = new PdfReader(lststrInputFiles[ii]);
            PdfDocument pdfDocument1 = new PdfDocument(pdfReader1);
            int iFirstPdfPageCount1 = pdfDocument1.GetNumberOfPages();
            iPageCount += iFirstPdfPageCount1;
            pdfDocument1.CopyPagesTo(1, iFirstPdfPageCount1, pdfDocumentOut);
            int iFirstPdfPageCount00 = pdfDocumentOut.GetNumberOfPages();
        }

        pdfDocumentOut.Close();

        return true;
    }
Miguelito
  • 302
  • 3
  • 11
  • 2
    Your solution is appropriate for iText 7 while the question and the other answers focus on iText 5. – mkl Jul 20 '20 at 14:13
  • 1
    That is correct and why I posted it. Pretty much all other answers I found were obsolete but I should have pointed out the difference. Every answer I found was for iText 5 so I figured posting one for the current iText 7 was a good idea. – Miguelito Jul 22 '20 at 00:16
0

Please also visit and read this article where I explained everything in detail about How to Merge Multiple PDF Files Into Single PDF Using Itextsharp in C#

Implementation:

try
{
    string FPath = "";
    // Create For loop for get/create muliple report on single click based on row of gridview control
    for (int j = 0; j < Gridview1.Rows.Count; j++)
    {
        // Return datatable for data
        DataTable dtDetail = new My_GlobalClass().GetDataTable(Convert.ToInt32(Gridview1.Rows[0]["JobId"]));
 
        int i = Convert.ToInt32(Gridview1.Rows[0]["JobId"]);
        if (dtDetail.Rows.Count > 0)
        {
            // Create Object of ReportDocument
            ReportDocument cryRpt = new ReportDocument();
            //Store path of .rpt file
            string StrPath = Application.StartupPath + "\\RPT";
            StrPath = StrPath + "\\";
            StrPath = StrPath + "rptCodingvila_Articles_Report.rpt";
            cryRpt.Load(StrPath);
            // Assign Report Datasource
            cryRpt.SetDataSource(dtDetail);
            // Assign Reportsource to Report viewer
            CryViewer.ReportSource = cryRpt;
            CryViewer.Refresh();
            // Store path/name of pdf file one by one 
            string StrPathN = Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report" + i.ToString() + ".Pdf";
            FPath = FPath == "" ? StrPathN : FPath + "," + StrPathN;
            // Export Report in PDF
            cryRpt.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, StrPathN);
        }
    }
    if (FPath != "")
    {
        // Check for File Existing or Not
        if (System.IO.File.Exists(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf"))
            System.IO.File.Delete(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
        // Split and store pdf input file
        string[] files = FPath.Split(',');
        //  Marge Multiple PDF File
        MargeMultiplePDF(files, Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
        // Open Created/Marged PDF Output File
        Process.Start(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
        // Check and Delete Input file
        foreach (string item in files)
        {
            if (System.IO.File.Exists(item.ToString()))
                System.IO.File.Delete(item.ToString());
        }
 
    }
}
catch (Exception ex)
{
    XtraMessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Create Function for Marge PDF

public static void MargeMultiplePDF(string[] PDFfileNames, string OutputFile)
{
    iTextSharp.text.Document PDFdoc = new iTextSharp.text.Document();
    using (System.IO.FileStream MyFileStream = new System.IO.FileStream(OutputFile, System.IO.FileMode.Create))
    {
        iTextSharp.text.pdf.PdfCopy PDFwriter = new iTextSharp.text.pdf.PdfCopy(PDFdoc, MyFileStream);
        if (PDFwriter == null)
        {
            return;
        }
        PDFdoc.Open();
        foreach (string fileName in PDFfileNames)
        {
            iTextSharp.text.pdf.PdfReader PDFreader = new iTextSharp.text.pdf.PdfReader(fileName);
            PDFreader.ConsolidateNamedDestinations();
            for (int i = 1; i <= PDFreader.NumberOfPages; i++)
            {
                iTextSharp.text.pdf.PdfImportedPage page = PDFwriter.GetImportedPage(PDFreader, i);
                PDFwriter.AddPage(page);
            }
            iTextSharp.text.pdf.PRAcroForm form = PDFreader.AcroForm;
            if (form != null)
            {
                PDFwriter.CopyAcroForm(PDFreader);
            }
            PDFreader.Close();
        }
        PDFwriter.Close();
        PDFdoc.Close();
    }
}
Nikunj Satasiya
  • 831
  • 9
  • 25
  • 1
    For merging with iText(Sharp) 2.x, 4.x and 5.x using `PdfCopy` based solutions usually is better than using `PdfWriter` based ones like yours. – mkl Dec 06 '21 at 16:58