1

I have a scenario where I need to generate certificate for student based on the course they joined.If a student joins for a single course single certificate is issued,if student joins for a multiple course,single pdf with multiple pages(each page will have individual certificates for each course) needs to be generated.

The below code helps me to generate a pdf for single course.How can I generate pdf for multiple courses. If multiple courses are there then the next page should also use the same template placed at path:

Server.MapPath("~/Template/CertificateTemplate.pdf");

I am using itextsharp library to create documents. Below is the code used to generate pdf.

 string formFile = Server.MapPath("~/Template/CertificateTemplate.pdf")                                        
 string newFile = Server.MapPath("~/Certificates/" + _dbRegistration.RegistrationNumber + ".pdf");

 PdfReader reader = new PdfReader(formFile);
 PdfStamper stamper = new PdfStamper(reader, new FileStream(
                        newFile, FileMode.Create));

 var pdfContentBuffer = stamper.GetOverContent(1);

 AcroFields fields = stamper.AcroFields;
 fields.SetField("ID", _dbRegistration.RegistrationNumber);
 fields.SetField("Course", _dbRegistration.Course.FirstOrDefault().Name);
 ...
 stamper.FormFlattening = true;
 stamper.Close();

I want to append pdf on the below condition

for(int i=0;i<course.count;i++)
{
     AcroFields fields = stamper.AcroFields;
     fields.SetField("ID", _dbRegistration.RegistrationNumber);
     fields.SetField("Course",   _dbRegistration.Course[i].Name);
     ...
}
ksg
  • 3,927
  • 7
  • 51
  • 97

2 Answers2

2

Allow me to update your code. Read the parts added as comments for more info about what I changed.

string formFile = Server.MapPath("~/Template/CertificateTemplate.pdf")                                        
string newFile = Server.MapPath("~/Certificates/"
_dbRegistration.RegistrationNumber + ".pdf");

PdfReader reader = new PdfReader(formFile);
PdfStamper stamper = new PdfStamper(reader, new FileStream(
                        newFile, FileMode.Create));

// You don't need this function here!
// var pdfContentBuffer = stamper.GetOverContent(1);

AcroFields fields = stamper.AcroFields;
fields.SetField("ID", _dbRegistration.RegistrationNumber);
...
...
stamper.FormFlattening = true;

// You can't reuse a PdfReader object when you're using PdfStamper,
// so let's create a new instance:
PdfReader reader2 = new PdfReader(formFile);
// Let's assume that your document only has one page,
// and add a second page that has the same size as the first page:
stamper.InsertPage(2, reader2.GetPageSize(1));
// Now we get the PdfContentByte of that second page:
var cb = stamper.GetOverContent(2);
// And we add the content of the first page at position 0, 0
cb.AddTemplate(stamper.GetImportedPage(reader2, 1), 0, 0);

stamper.Close();
// Don't forget to close the PdfReader instances!
reader.Close();
reader2.Close();

Now you will have a PDF where the first page consists of the template to which the fields were added; the second page will be the same template without the fields, which is exactly what you were looking for (in version 1 of your question).

Update:

In a second version of your question, you now say that you want to create a PDF that consists of several pages in which the same form is repeated using different data sets for the fields.

How to do this is explained in great detail in the following video tutorial: https://www.youtube.com/watch?v=6YwDME0Fl1c

The examples for this tutorial can be found here: Using forms for reporting. If you browse these examples, you understand that there are different ways to achieve this.

First concatenate the form, then fill out the fields

It's not the most elegant way, but you could concatenate the form with itself so that it has two page. This isn't elegant and it's easy to make a mistake. That's what is explained in this question: http://developers.itextpdf.com/question/how-merge-forms-different-files-one-pdf

The first hurdle is that you need to inform PdfCopy that you are merging a document that contains form fields (if you don't do that, fields get lost). The second hurdle is that you must rename the fields, because two widget annotations that correspond with a field with only one name can only have one value.

I wouldn't recommend using this approach.

Fill and flatten first, then concatenate

That's explained in the second part of my answer to the question How to merge forms from different files into one PDF?. It's also answered here: iTextSharp filling forms and creating multiple pages or, if you don't understand Java code and prefer C# code: Multipage PDF document from predefined template

Community
  • 1
  • 1
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • Thanks for the reply mate.I think you misunderstood my question slightly.Secondpage will have the same template `with fields , but will be of different value as compared to the first one` . I will update my question so you will have clear understanding. – ksg Mar 08 '16 at 13:55
  • Updated the question.Hope you understood it?If you need any clarification feel free to ask. – ksg Mar 08 '16 at 14:10
  • @ksg The first version of your question was different from what you really want to do. What you really want to do has been answered many times before on StackOverflow and it's quite well documented on the [official web site](http://developers.itextpdf.com/question/how-merge-forms-different-files-one-pdf). – Bruno Lowagie Mar 08 '16 at 14:14
-3

The following function creates pages and insert more pages so that output pdf has pages with multiple of 4

itextsharp dll is used here

var tempFileLocation = Path.GetTempFileName();
string sourcePdfPath =" pdf file path here";    
var bytes = File.ReadAllBytes(sourcePdfPath);

using (var reader = new PdfReader(bytes))
{
    var numberofPages = reader.NumberOfPages;
    var modPages = (numberofPages % 4);
    var pages = modPages == 0 ? 0 : 4 - modPages;

    if (pages == 0)
        return;

    using (var fileStream = new FileStream(tempFileLocation, FileMode.Create, FileAccess.Write))
    {
        using (var stamper = new PdfStamper(reader, fileStream))
        {
            var rectangle = reader.GetPageSize(1);
            for (var i = 1; i <= pages; i++)
                stamper.InsertPage(numberofPages + i, rectangle);
        }
    }
}

File.Delete(sourcePdfPath);
File.Move(tempFileLocation, sourcePdfPath);
}
  • 1
    This answer is strange. It looks as if you didn't really read the question but just found some code, copy/pasted it here, and thought: *close enough, let's hope I get some upvotes.* The OP should indeed use the `InsertPage()` method, but you don't show how to add the template to that inserted page anywhere. – Bruno Lowagie Mar 08 '16 at 13:34
  • Aha, you just copy/pasted this answer: http://stackoverflow.com/a/28882185/1622493 Why did you do that? How does this copy/pasted code snippet help the OP? – Bruno Lowagie Mar 08 '16 at 13:49