Click here to Skip to main content
Click here to Skip to main content

Simple .NET PDF Merger

By , 31 Jul 2008
 

Introduction

There are a couple of PDF mergers available on the Internet. But, either they are commercial products or don't support printing of the header and/or footer text, which is particularly interesting, e.g., to print the page number.

Background

The presented PDF merger uses the open source PDF library iTextSharp to process PDF files. The sample solution also includes a tiny Windows Forms application to demonstrate the functionality.

Using the code

For the merge process, the PDF library takes advantage of the PDF page events of the iTextSharp.text.pdf.PdfWriter object. During the initialization of the PdfPageEvent instance (which inherits from iTextSharp.text.pdf.IPdfPageEvent), necessary information for the header/footer text could be passed in to the constructor call:

writer.PageEvent = new PdfPageEvents(/*Any type of information goes here*/);

It is important that the header and the footer text, both, are rendered in the 'public void OnEndPage(PdfWriter writer, Document document)' method. The 'public void OnStartPage(PdfWriter writer, Document document)' is not accurate.

Even though the shown sample is very basic, it generally gives a good overview of how the header and the footer can be populated, e.g., with picture(s), text(s)...

The source code

using System;
using System.Collections.Generic;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace SmartSoft.PdfLibrary
{
    public static class PdfMerger
    {
        /// <summary>
        /// Merge pdf files.
        /// </summary>
        /// <param name="sourceFiles">PDF files being merged.</param>
        /// <returns></returns>
        public static byte[] MergeFiles(List<byte[]> sourceFiles)
        {
            Document document = new Document();
            MemoryStream output = new MemoryStream();

            try
            {
                // Initialize pdf writer
                PdfWriter writer = PdfWriter.GetInstance(document, output);
                writer.PageEvent = new PdfPageEvents();
                
                // Open document to write
                document.Open();
                PdfContentByte content = writer.DirectContent;

                // Iterate through all pdf documents
                for (int fileCounter = 0; fileCounter < sourceFiles.Count; fileCounter++)
                {
                    // Create pdf reader
                    PdfReader reader = new PdfReader(sourceFiles[fileCounter]);
                    int numberOfPages = reader.NumberOfPages;

                    // Iterate through all pages
                    for (int currentPageIndex = 1; currentPageIndex <= 
                                       numberOfPages; currentPageIndex++)
                    {
                        // Determine page size for the current page
                        document.SetPageSize(
                           reader.GetPageSizeWithRotation(currentPageIndex));
                        
                        // Create page
                        document.NewPage();
                        PdfImportedPage importedPage = 
                          writer.GetImportedPage(reader, currentPageIndex);

                        
                        // Determine page orientation
                        int pageOrientation = reader.GetPageRotation(currentPageIndex);
                        if ((pageOrientation == 90) || (pageOrientation == 270))
                        {
                            content.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
                               reader.GetPageSizeWithRotation(currentPageIndex).Height);
                        }
                        else
                        {
                            content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                throw new Exception("There has an unexpected exception" + 
                      " occured during the pdf merging process.", exception);
            }
            finally
            {
                document.Close();
            }
            return output.GetBuffer();
        }
    }



    /// <summary>
    /// Implements custom page events.
    /// </summary>
    internal class PdfPageEvents : IPdfPageEvent
    {
        #region members
        private BaseFont _baseFont = null;
        private PdfContentByte _content;
        #endregion

        #region IPdfPageEvent Members
        public void OnOpenDocument(PdfWriter writer, Document document)
        {
            _baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, 
                             BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            _content = writer.DirectContent;
        }

        public void OnStartPage(PdfWriter writer, Document document)
        {}

        public void OnEndPage(PdfWriter writer, Document document)
        {
            // Write header text
            string headerText = "PDF Merger by Smart-Soft";
            _content.BeginText();
            _content.SetFontAndSize(_baseFont, 8);
            _content.SetTextMatrix(GetCenterTextPosition(headerText, 
                                   writer), writer.PageSize.Height - 10);
            _content.ShowText(headerText);
            _content.EndText();

            // Write footer text (page numbers)
            string text = "Page " + writer.PageNumber;
            _content.BeginText();
            _content.SetFontAndSize(_baseFont, 8);
            _content.SetTextMatrix(GetCenterTextPosition(text, writer), 10);
            _content.ShowText(text);
            _content.EndText();
        }

        public void OnCloseDocument(PdfWriter writer, Document document)
        {}

        public void OnParagraph(PdfWriter writer, 
                    Document document, float paragraphPosition)
        {}

        public void OnParagraphEnd(PdfWriter writer, 
                    Document document, float paragraphPosition)
        {}

        public void OnChapter(PdfWriter writer, Document document, 
                              float paragraphPosition, Paragraph title)
        {}

        public void OnChapterEnd(PdfWriter writer, 
                    Document document, float paragraphPosition)
        {}

        public void OnSection(PdfWriter writer, Document document, 
                    float paragraphPosition, int depth, Paragraph title)
        {}

        public void OnSectionEnd(PdfWriter writer, 
                    Document document, float paragraphPosition)
        {}

        public void OnGenericTag(PdfWriter writer, Document document, 
                                 Rectangle rect, string text)
        {}
        #endregion

        private float GetCenterTextPosition(string text, PdfWriter writer)
        {
            return writer.PageSize.Width / 2 - _baseFont.GetWidthPoint(text, 8) / 2;
        }
    }
}

History

  • 01.08.2008 - Article created.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

Michael Ulmann
Architect Helvetic Solutions
Australia Australia
Member
MCAD, MCPD Web Developer 2.0, MCPD Enterprise Developer 3.5
My company: www.helveticsolutions.com
Hopp Schwiiz Smile | :)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCrop/RotatememberCorbin de Bruin25 Apr '13 - 6:45 
Questionneed help for securitymemberHanieef12 Mar '13 - 15:17 
GeneralUpvoted -memberJohn Atten26 Jan '13 - 3:07 
GeneralMy vote of 5memberjafarkofahi5 Sep '12 - 5:52 
QuestionGreat!memberAleBrozzo20 Mar '12 - 18:51 
QuestionTHANK YOU!memberMember 340683825 Jan '12 - 5:04 
AnswerRe: THANK YOU!memberMichael Ulmann18 Mar '12 - 13:06 
GeneralMy vote of 5memberjuniorsebr22 Jul '10 - 2:37 
GeneralPdfContentByte has a method called ShowTextAlignedmemberRubyPdf25 May '10 - 13:28 
GeneralInformative articlemembersuraj mehare2 Mar '10 - 7:06 
GeneralRe: Informative articlememberMichael Ulmann2 Mar '10 - 19:02 
QuestionHow to bookmark by each PDF creation timememberorlandito2030 Apr '09 - 22:08 
QuestionHow to bookmark by each PDF file namememberSaam_cse27 Nov '08 - 22:49 
AnswerRe: How to bookmark by each PDF file namememberMichael Ulmann1 Dec '08 - 11:25 
GeneralRe: How to bookmark by each PDF file namememberSaam_cse1 Dec '08 - 23:23 
GeneralRe: How to bookmark by each PDF file namememberfriendmastor25 Aug '09 - 15:24 
QuestionMerge Large Amount of filesmemberastaykov7 Aug '08 - 1:02 
AnswerRe: Merge Large Amount of filesmemberMichael Ulmann7 Aug '08 - 12:52 
QuestionHow to pass argumentsmemberVäinölä Harri1 Aug '08 - 3:10 
AnswerRe: How to pass argumentsmemberMichael Ulmann1 Aug '08 - 14:38 
GeneralRe: How to pass argumentsmemberVäinölä Harri3 Aug '08 - 20:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 31 Jul 2008
Article Copyright 2008 by Michael Ulmann
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid