0

I am going to be using iTextSharp to insert data to a PDF that the Graphics department has created. Most of this data is simple data-to-field mapping, but some data is a list of items that needs to be added (e.g. product data; users can have any number of products and the data needs to be displayed for all of them).

Is it possible to do this with iTextSharp? The PDF template cannot, obviously, be created with a certain number of fields as there is no way of knowing how many fields there will be - it could be 1, or 10, or even 100; what I need to be able to do is "re-use" a section of the PDF and repeat that section for each item within a loop.

Is that doable?

Wayne Molina
  • 19,158
  • 26
  • 98
  • 163

1 Answers1

1

In the past I needed to do something similar. I needed to create a PDF with an unknown number of images + content. In my case an 'Entry' was defined by an image and a set of fields.

What I did is I had a doc. that served as a 'Entry' template. I then generated a temp. pdf file for each 'Entry', and stored the generated file names in a List. After all 'Entries' were processed I then merged all temporary pdf docs, into one final document.

Here is some code to give you a better idea (it's not compilable, just serves as a ref, as I took certain parts from my older project).

        List<string> files = new List<string>(); // list of files to merge
        foreach (string pageId in pages)
        {

            // create an intermediate page
            string intermediatePdf = Path.Combine(_tempPath, System.Guid.NewGuid() + ".pdf");
            files.Add(intermediatePdf);

            string pdfTemplate = Path.Combine(_templatePath, _template);


            CreatePage(pdfTemplate, intermediatePdf, pc, pageValues, imageMap, tmd);


        }

        // merge into resulting pdf file
        string outputFolder = "~/Output/";
        if (preview)
        {
            outputFolder = "~/temp/";
        }
        string pdfResult = Path.Combine(HttpContext.Current.Server.MapPath(outputFolder), Guid.NewGuid().ToString() + ".pdf");
        PdfMerge.MergeFiles(pdfResult, files);

        //////////////////////////////////////////////////////////////////////////
        // delete temporary files...
        foreach (string fd in files)
        {
            File.Delete(fd);
        }

        return pdfResult;

Here is the code to merge the templates:

 public class PdfMerge
    {
        public static void MergeFiles(string destinationFile, List<string> sourceFiles)
        {
            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;
            // 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.Count)
            {
                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);
                    }
                }
                f++;
                if (f < sourceFiles.Count)
                {
                    reader = new PdfReader(sourceFiles[f]);
                    // we retrieve the total number of pages
                    n = reader.NumberOfPages;
                }
            }
            // step 5: we close the document
            document.Close();
        }
    }

Hope it helps!

santiagoIT
  • 9,411
  • 6
  • 46
  • 57
  • It cannot be done normally then without creating what amounts to partial PDF templates then? I suppose if I need to have sections with information that does NOT need to be looped over, I'd have to have separate docs for each of those and then merge them all together? – Wayne Molina Feb 07 '11 at 15:23
  • @Wayne, it should be possible. I am no expert with iTextSharp but I am sure you can query the doc. I know allows you to insert content. Below are some links that shows how to read/add content from/to an existing pdf. http://www.mikesdotnetting.com/Article/82/iTextSharp-Adding-Text-with-Chunks-Phrases-and-Paragraphs http://stackoverflow.com/questions/3992617/itextsharp-insert-text-to-an-existing-pdf – santiagoIT Feb 07 '11 at 15:41