Creating a multiple pages pdf with iTextSharp - c#

I'm trying the create a multiple-page pdf using iTextSharp, but I'm having some issue creating a loop to have more than a single page.
My code below is working well for one page; however, my content will not fit into a single page. Thanks.
How can I write a loop to write contents on the first pdf page and the remaining to the second, third, etc...So far, I'm only seeing one page. Thank you.
int height = 600;
int totalPage = 1;
int oldPage = 1;
bool cons = false;
bool st = false;
foreach (string al in combo)
foreach (string al in combo) //my loop to write on the pdf but "combo" has 100 lines, which would fit into a single page.
{
string[] word = al.Split(',');
int strIndex = combo.IndexOf(al);
if (al.Length != 0)
{
if (word[0].ToString().ToUpper().Contains("(REV")==true && cons == false)
{
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 11);
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "CONSTRUCTION PRINTS", 80, height, 0);
cb.EndText();
height = height - 20;
cons = true;
}
if (word[0].ToString().ToUpper().Contains("(REV")==false && st == false)
{
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 11);
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "SAG & TENSION CHARTS", 80, height, 0);
cb.EndText();
height = height - 20;
st = true;
}
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 11);
totalPage = totalPage + oldPage;
// write the text in the pdf content
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, word[0].ToString().ToUpper(), 80, height, 0);
cb.EndText();
// write the text in the pdf content
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "......................................................................................", 335, height, 0);
cb.EndText();
// write the text in the pdf content
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, totalPage.ToString(), 500, height, 0);
cb.EndText();
oldPage = Convert.ToInt32(word[1]);
}
height = height - 20;
}
//// create the new page and add it to the pdf
// reader = new PdfReader(oldFile);//old file
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
//// close the streams and voilá the file should be changed :)
document.Close();
reader.Close();
fs.Close();
writer.Close();

Please go to the official documentation and click Q&A to go to the most frequently asked questions. Pick the Getting started category. The first thing you'll see, is the most popular iText example (which I am porting to C# for your convenience):
// step 1
Document document = new Document();
// step 2
FileStream fs = new FileStream("hello.pdf", FileMode.Create);
PdfWriter.GetInstance(document, fs);
// step 3
document.Open();
// step 4
document.Add(new Paragraph("Hello World!"));
// step 5
document.Close();
In your code, you are adding text at absolute positions by introducing PDF syntax, such as BeginText() (BT) / EndText() (ET) / SetFontAndSize() (Tf). This is creating PDF the hard way. If is very easy to make mistakes, as shown in this question: What is causing syntax errors in a page created with iText?
If you don't know the PDF reference (ISO 32000-1) by heart, you should avoid code like this. Instead you can use objects such as Paragraph, List, PdfPTable... The beauty of adding these objects to a Document using the Add() method, is that a new page gets triggered automagically as soon as a page is full. You can also trigger a new page yourself using:
document.NewPage();
If you want to add text at absolute positions, iText offers convenience methods and objects such as ColumnText. See my answer to Adding footer to existing PDF
You can define a Rectangle and add objects such as Paragraph, List, PdfPTable... Take a look at the answer to the question How to continue an ordered list on a second page? for inspiration:
ColumnText ct = new ColumnText(cb);
ct.AddElement(list);
Rectangle rect = new Rectangle(36, 36, 559, 806);
ct.SetSimpleColumn(rect);
int status = ct.Go();
while (ColumnText.HasMoreText(status)) {
document.NewPage();
ct.SetSimpleColumn(rect);
ct.Go();
}
The while loop is the loop you are looking for.

Related

Adding text as watermark using itext7 C#

I am using the below code to add watermark to my pdf.
private void Merge(List<string> src, string dest)
{
iTextKernel.PdfWriter writer = new iTextKernel.PdfWriter(dest);
iTextKernel.PdfDocument pdfDocument1 = new iTextKernel.PdfDocument(new iTextKernel.PdfReader(src[0]), writer);
pdfDocument1.AddEventHandler(PdfDocumentEvent.END_PAGE, new WatermarkingEventHandler());
for (int i = 1, max = src.Count; i < max; i++)
{
iTextKernel.PdfDocument pdfDocument2 = new iTextKernel.PdfDocument(new iTextKernel.PdfReader(src[i]));
var pagesCount = pdfDocument2.GetNumberOfPages();
pdfDocument2.CopyPagesTo(1, pagesCount, pdfDocument1);
pdfDocument2.Close();
}
pdfDocument1.Close();
protected class WatermarkingEventHandler : IEventHandler {
public void HandleEvent(Event e) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) e;
iTextKernel.PdfDocument pdfDoc = docEvent.GetDocument();
iTextKernel.PdfPage page = docEvent.GetPage();
iText.Kernel.Font.PdfFont font = null;
try {
font = PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD);
} catch (IOException ex) {
//_log.Error(ex);
}
PdfCanvas canvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
new Canvas(canvas, pdfDoc, page.GetPageSize())
.SetFontColor(iText.Kernel.Colors.DeviceGray.LIGHT_GRAY)
.SetFontSize(60)
.SetFont(font)
.ShowTextAligned(new Paragraph("FOR YOUR RECORDS ONLY: DO NOT SUBMIT"), 298, 421, pdfDoc.GetPageNumber(page),
TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
}
But am getting the watermark only in the last page that too hidden under the contents. Could you please modify this code so that i could get the watermark on all the pages and shown over the contents.
Please take a look at the iText 7 for C# jump-start tutorial, more specifically Chapter 5: Manipulating an existing PDF document. Scroll to the part where it says: "Adding a header, footer, and watermark" and look at the example:
PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
Document document = new Document(pdfDoc);
Rectangle pageSize;
PdfCanvas canvas;
int n = pdfDoc.GetNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = pdfDoc.GetPage(i);
pageSize = page.GetPageSize();
canvas = new PdfCanvas(page);
//Draw header text
}
pdfDoc.close();
As you can see, we only need one PdfDocument instance, but instead of passing only a PdfWriter, we also pass a PdfReader instance. We will read the file with path src and we will write to a file with path dest.
You want to add content to each page. This means that you have to loop over each page (from 1 to n). Get the PdfPage object for each page i and replace the line //Draw header text with whatever it is you want to do.
In your case, you add an image underneath the existing content. That is the normal thing to do, but you say that the watermark is covered by the existing content. That happens for instance when the actual content consists of images (e.g. scanned pages). If you add a watermark under the pages of a PDF that consists of scanned pages, you will never see the watermark.
In that case, you have to add the content on top of the existing content, but it is best to make the watermark transparent:
Paragraph p = new Paragraph("FOR YOUR RECORDS ONLY: DO NOT SUBMIT").SetFontSize(60);
canvas.SaveState();
PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.2f);
canvas.SetExtGState(gs1);
document.ShowTextAligned(p, pageSize.GetWidth() / 2, pageSize.GetHeight() / 2, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
canvas.RestoreState();
Note that in the tutorial, we are using pageSize.GetWidth() / 2 and pageSize.GetHeight() / 2 as coordinates, which means that we assume that the lower-left corner of the page has the coordinate (0, 0). That may not be the case. You may have to add the x-offset and the y-offset to that value.

Divide pdf exact equal half using ItextSharp [duplicate]

This question already has an answer here:
Tile PDF pages vertically with iTextSharp
(1 answer)
Closed 8 years ago.
I am trying to divide a PDF into exactly 2 equal halves, saving them as "LeftPDF.pdf" and "RightPDF.pdf".
I tried the code below but it doesn't work:
PdfReader reader = new PdfReader(filepath);
int n = reader.NumberOfPages;
iTextSharp.text.Rectangle psize = reader.GetPageSize(1);
float width = psize.Width/2;
float height = psize.Height;
Document document = new Document(psize);
// target.pdf is A5 Portrait format
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(splitpath, FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
document.NewPage();
PdfImportedPage page1 =writer.GetImportedPage(reader, 1);
cb.AddTemplate(page1, 1, 0, 0, 1, 0, 0);
document.Close();
How can I do this?
As I indicated in my comment, your question has been posted and answered before. This is yet another duplicate of your question: Divide one page PDF file in two pages PDF file
Take a closer look at the TileInTwo example:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
// step 1
Rectangle mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(1)));
Document document = new Document(mediabox);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte content = writer.getDirectContent();
PdfImportedPage page;
int i = 1;
while (true) {
page = writer.getImportedPage(reader, i);
content.addTemplate(page, 0, -mediabox.getHeight());
document.newPage();
content.addTemplate(page, 0, 0);
if (++i > n)
break;
mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(i)));
document.setPageSize(mediabox);
document.newPage();
}
// step 5
document.close();
reader.close();
}
public Rectangle getHalfPageSize(Rectangle pagesize) {
float width = pagesize.getWidth();
float height = pagesize.getHeight();
return new Rectangle(width, height / 2);
}
In this example, we ask the PdfReader instance for the page size of the first page and we create a new rectangle with the same width and only half the height.
We then import each page in the document, and we add it twice on different pages:
once on the odd pages with a negative y value to show the upper half of the original page,
once on the even pages with y = 0 to show the lower half of the original page.
As every page in the original document can have a different size, we may need to change the page size for every new couple of pages.
This example cuts a page in two with an upper part and a lower part. Use simple math and you can adapt the example to cut it in two with a left and a right part. This is done in the example TileInTwo2:
For instance:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
// step 1
Rectangle mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(1)));
Document document = new Document(mediabox);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte content = writer.getDirectContent();
PdfImportedPage page;
int i = 1;
while (true) {
page = writer.getImportedPage(reader, i);
content.addTemplate(page, 0, 0);
document.newPage();
content.addTemplate(page, -mediabox.getWidth(), 0);
if (++i > n)
break;
mediabox = new Rectangle(getHalfPageSize(reader.getPageSizeWithRotation(i)));
document.setPageSize(mediabox);
document.newPage();
}
// step 5
document.close();
reader.close();
}
public Rectangle getHalfPageSize(Rectangle pagesize) {
float width = pagesize.getWidth();
float height = pagesize.getHeight();
return new Rectangle(width / 2, height);
}
You should have no problem to adapt this example so that different PDF documents are created instead of the one containing the left and right part. If that is problematic for you, please post another question.

Blank PDF generate when WriteCompatiblePdf method call of ITextSharp

Hi i am using below code. When i upload some of PDF's which contain some content and after uploading, their is no content on uploaded PDF. Uploaded PDf is blank. I am using below method of ItextSharp for change the version of Orginial PDF to Defined Version.
private int WriteCompatiblePdf(string fileName, FileUpload filePath)
{
string sNewPdf = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["InterfaxPath"]) + fileName;
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(filePath.FileBytes);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
// step 1: creation of a document-object
iTextSharp.text.Document document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, new FileStream(sNewPdf, FileMode.Create, FileAccess.ReadWrite));
//write pdf that pdfsharp can understand
writer.SetPdfVersion(iTextSharp.text.pdf.PdfWriter.PDF_VERSION_1_4);
// step 3: we open the document
document.Open();
iTextSharp.text.pdf.PdfContentByte cb = writer.DirectContent;
iTextSharp.text.pdf.PdfImportedPage page;
int rotation;
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
// step 5: we close the document
document.Close();
return n;
}
Any recommendations?
The OP provided a sample "blank" file.
As it turns out, this "blank" file does contain the desired content, it merely is way off-page.
Details
The pages of the document have this media box definition:
/MediaBox[0 7072 612 7864]
Thus, the visible area has x coordinates in 0..612 and y coordinates in 7072..7864. When adding the imported page contents, though, the OP explicitly anchors them explicitly at the coordinates 0,0:
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
The contents of the former page, therefore, are added in the area with y coordinates 0..792. So, they are not visible.
Resolutions
There are different ways to resolve this issue:
add the contents at the position with the correct coordinates, i.e. use
cb.AddTemplate(page, 1f, 0, 0, 1f, x, y);
where x and y are Left and Bottom of reader.GetPageSizeWithRotation(1) (a Rectangle); or
normalize the page size rectangle for the Document constructor to be based in 0,0; or
use a PdfStamper with the PdfReader instead of the PdfWriter and use it to select the desired version.
it's because you're not set any text to be written in the PDF. this is a simple example how to write text
string newFile = #"C:\the path\file.pdf";
Document doc = new Document(iTextSharp.text.PageSize.A4, 10, 10, 42, 35);
PdfWriter write = PdfWriter.GetInstance(doc, new FileStream(newFile,
FileMode.Create));
doc.Open(); // open the connection
Paragraph p1 = new Paragraph("text to be displayed in the first paragraph");
doc.Add(p1); // close the connection
this link will tell you the proper way to write from iTextSharp more advanced

iText - new lines in ColumnText

I'm working on program that insert some kind of watermark on existing pdf document. The watermark isn't image but text generated during program's work. I need to rotate the text, send it to center of page, and those things are done, but the text has many lines. So I put new line character "\n" in Phrase but PDF prints only characters before first use of "\n". How could I overlay some text on pdf document (mainly scanned docs) and rotate it?
My source code (simplified):
PdfContentByte canvas = stamper.GetOverContent(1);
String message = "some\n multiline \n expression";
Phrase text = new Phrase(text);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_MIDDLE, text, size.Width / 2, size.Height / 2, 30);
That is documented: the ShowTextAligned() method is for single lines only. If you want multiple lines, you need to use a ColumnText object, define a Rectangle using the SetSimpleColumn() method and draw the content using the Go() method.
If you want to rotate such a Rectangle, you need to create a PdfTemplate first. Render the ColumnText to this PdfTemplate and add the template to the document.
Adding the template to the document can be done with the AddTemplate() method. In this case, you need some algebra to rotate the template. This is the algebra you'll need for the parameters:
a = cosine(angle);
b = sine(angle);
c = -sine(angle);
d = cosine(angle);
e = x;
f = y;
If you can't get the algebra working, you can wrap the template inside an Image object:
Image img = Image.getInstance(template);
Now you have different methods to introduce a rotation, including a simple one that merely requires an angle in degrees.
P.S.: wrapping a template inside an image doesn't "rasterize" the text. It creates a Form XObject (as opposed to an Image XObject).
I solved the problem in another way:
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
PdfContentByte canvas = stamper.GetOverContent(1);
String message = String.Format("mutli\nline\text");
}
PdfGState gState = new PdfGState();
gState.FillOpacity = 0.3f;
canvas.SetGState(gState);
using (StringReader stringReader = new StringReader(message))
{
string line;
float y = size.Height / 2 + 200;
while ((line = stringReader.ReadLine()) != null)
{
Phrase p = new Phrase(line,FontFactory.GetFont(FontFactory.HELVETICA, 35));
ColumnText.ShowTextAligned(canvas, Element.ALIGN_CENTER, p, 300, y, 30);
y = y - 70;
}
}
}

document looks cut after using itextsharp.text.pdf to merge several itextsharp.text.pdf.PdfReader objects

I am using iTextSharp to create a List<PdfReader> _documents with several PDF documents.
After using merge on this list to create single paged document and send it to the client I see that the PDF looks cut in Adobe Reader.
When I highlight the picture like this I can see it's there :
and if I save it it will be complete.
If I save one of PdfReader in list as single PDF document - without merge - it looks good.
The merge function is :
public void Merge(Stream outputStream)
{
Document newDocument = null;
try
{
newDocument = new Document();
// Set margins and page size for the document
newDocument.SetMargins(50, 50, 50, 50);
// There are a huge number of possible page sizes, including such sizes as
// EXECUTIVE, LEGAL, LETTER_LANDSCAPE, and NOTE
newDocument.SetPageSize(PageSize.A3 );
PdfWriter pdfWriter = PdfWriter.GetInstance(newDocument, outputStream);
newDocument.Open();
PdfContentByte pdfContentByte = pdfWriter.DirectContent;
if (EnablePagination)
{
_documents.ForEach(delegate(PdfReader doc)
{
_totalPages += doc.NumberOfPages;
});
}
int currentPage = 1;
foreach (PdfReader pdfReader in _documents)
{
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
newDocument.NewPage();
PdfImportedPage importedPage = pdfWriter.GetImportedPage(pdfReader, page);
pdfContentByte.AddTemplate(importedPage, 0, 0);
if (EnablePagination)
{
pdfContentByte.BeginText();
pdfContentByte.SetFontAndSize(_baseFont, 9);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
string.Format("{0} of {1}", currentPage++, _totalPages), 520, 5, 0);
pdfContentByte.EndText();
}
}
}
}
finally
{
outputStream.Flush();
if (newDocument != null)
newDocument.Close();
outputStream.Close();
}
}
I suspect it has something to do with newDocument.SetPageSize(PageSize.A3);
but I am not sure and so far I can't find the solution.
Just a couple of ideas to try. The problem could be related to scaling or sizing. Compare the Horizontal scaling of both documents. Also, the importedPage.PdfDocument.PageSize needs to be compared to the pdfContentByte.PdfDocument.PageSize, and probably scaled down.

Categories

Resources