iTextSharp PdfPCell align image to bottom of cell - c#

I'm trying to align an image to the bottom-right of a cell.
I'm basically creating a table with two cells for each row. The cell contains text and an image, which I want to be aligned to the right bottom of the cells. Please refer to image
This is my code
PdfPTable table = new PdfPTable(2);
table.TotalWidth = 400f;
table.LockedWidth = true;
float[] widths = new float[] { 1.5f, 1.5f };
table.SetWidths(widths);
table.HorizontalAlignment = 0;
table.SpacingBefore = 50f;
table.SpacingAfter = 30f;
iTextSharp.text.Image logoImage = iTextSharp.text.Image.GetInstance(HttpContext.Current.Server.MapPath("~/Images/MyImage.png"));
logoImage.ScaleAbsolute(40, 40);
logoImage.Alignment = iTextSharp.text.Image.ALIGN_BOTTOM;
logoImage.Alignment = iTextSharp.text.Image.RIGHT_ALIGN;
foreach (EmployeeModel employee in employees)
{
PdfPCell cell = new PdfPCell();
cell.FixedHeight = 140f;
cell.PaddingLeft = 30f;
cell.PaddingRight = 10f;
cell.PaddingTop = 20f;
cell.PaddingBottom = 5f;
Paragraph p = new Paragraph(GetLabelCellText(Employee), NormalFont);
p.Alignment = Element.ALIGN_LEFT;
p.Alignment = Element.ALIGN_TOP;
cell.AddElement(p);
cell.AddElement(logoImage);
table.AddCell(cell);
}
How do I place the image at the bottom right of each cell (without affecting the position of the text of course).

The question is a bit ambiguous because you create a Table with two columns, but add cells without verifying the employees collection has an even number of elements, which will throw if not....
Assuming you really do want both the text and the image in a single cell, probably the simplest way to get the layout you want is to implement IPdfPCellEvent:
public class BottomRightImage : IPdfPCellEvent
{
public Image Image { get; set; }
public void CellLayout(
PdfPCell cell,
Rectangle position,
PdfContentByte[] canvases)
{
if (Image == null) throw new InvalidOperationException("image is null");
PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
Image.SetAbsolutePosition(
position.Right - Image.ScaledWidth - cell.PaddingRight,
position.Bottom + cell.PaddingBottom
);
canvas.AddImage(Image);
}
}
Then set the CellEvent property on the PdfPCell. Here's a simple working example:
using (var stream = new MemoryStream())
{
using (var document = new Document())
{
PdfWriter.GetInstance(document, stream);
document.Open();
var table = new PdfPTable(2)
{
HorizontalAlignment = Element.ALIGN_LEFT,
TotalWidth = 400f,
LockedWidth = true
};
var image = Image.GetInstance(imagePath);
image.ScaleAbsolute(40, 40);
var cellEvent = new BottomRightImage() { Image = image };
var testString =
#"first name: {0}
last name: {0}
ID no: {0}";
for (int i = 0; i < 2; ++i)
{
var cell = new PdfPCell()
{
FixedHeight = 140f,
PaddingLeft = 30f,
PaddingRight = 10f,
PaddingTop = 20f,
PaddingBottom = 5f
};
cell.CellEvent = cellEvent;
var p = new Paragraph(string.Format(testString, i))
{
Alignment = Element.ALIGN_TOP | Element.ALIGN_LEFT
};
cell.AddElement(p);
table.AddCell(cell);
}
document.Add(table);
}
File.WriteAllBytes(outputFile, stream.ToArray());
}
And PDF output:
An all-black square image is used to show the PdfPCell padding is taken into account.

Related

Itextsharp Header spacing with multiple column

I have created pdf file with itextsharp and I create Header ok but when I create table with two column. I don't have spacing from Header to my two column
The code
PdfPTable table1 = new PdfPTable(2);
table1.DefaultCell.Border = Rectangle.NO_BORDER;
table1.WidthPercentage = 100;
PdfPCell cell11 = new PdfPCell();
Paragraph UniName = new Paragraph(#"TRƯỜNG ĐẠI HỌC CÔNG NGHỆ ĐỒNG NAI", fontBold);
UniName.Alignment = Element.ALIGN_CENTER;
Paragraph paragraph = new Paragraph(#"PHÒNG ĐÀO TẠO", times);
paragraph.Alignment = Element.ALIGN_CENTER;
cell11.AddElement(UniName);
cell11.AddElement(paragraph);
cell11.BorderColor = BaseColor.WHITE;
PdfPCell cell12 = new PdfPCell();
Paragraph QH1 = new Paragraph(#"CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM", fontBold);
QH1.Alignment = Element.ALIGN_CENTER;
Paragraph QH = new Paragraph(#"Độc lập - Tự do - Hạnh phúc", fontBold);
QH.Alignment = Element.ALIGN_CENTER;
Paragraph Symbol = new Paragraph(#"----------oOo----------", fontBold);
Symbol.Alignment = Element.ALIGN_CENTER;
cell12.AddElement(QH1);
cell12.AddElement(QH);
cell12.AddElement(Symbol);
cell12.BorderColor = BaseColor.WHITE;
table1.AddCell(cell11);
table1.AddCell(cell12);
Paragraph TitleReport = new Paragraph(#"TỔNG HỢP COI CHẤM THI", titleFont);
TitleReport.Alignment = Element.ALIGN_CENTER;
Paragraph Info = new Paragraph(string.Format(#"Từ ngày: {0} đến ngày: {1} Đơn vị: {2}", DateTime.Now.AddDays(-2).ToString("dd/MM/yyyy"), DateTime.Now.ToString("dd/MM/yyyy"), "Trung tâm quản lý chất lượng"), normalFont);
Info.Alignment = Element.ALIGN_LEFT;
Info.SpacingBefore = 20;
Info.SpacingAfter = 200;
PdfContentByte canvas = writer.DirectContent;
ColumnText ct = new ColumnText(canvas);
int side_of_the_page = 0;
ct.SetSimpleColumn(COLUMNS[side_of_the_page]);
int paragraphs = 0;
while (paragraphs < 28)
{
PdfPTable table = new PdfPTable(5);
table.AddCell("STT");
table.AddCell("Số Phách");
table.AddCell("Điểm bằng số");
table.AddCell("Điểm bằng chữ");
table.AddCell("Ghi chú");
for (int i = 0; i < 33; i++)
{
table.AddCell((i + 1).ToString());
table.AddCell("209292");
table.AddCell("4");
table.AddCell("Điểm bằng chữ");
table.AddCell("");
++paragraphs;
}
table.HeaderRows = 1;
//table.LockedWidth = true;
ct.AddElement(table);
//ct.AddElement(new Paragraph(String.Format("Paragraph {0}: {1}", , TEXT)));
while (ColumnText.HasMoreText(ct.Go()))
{
if (side_of_the_page == 0)
{
side_of_the_page = 1;
canvas.MoveTo(297.5f, 36);
canvas.LineTo(297.5f, 806);
canvas.Stroke();
}
else
{
side_of_the_page = 0;
doc.NewPage();
}
ct.SetSimpleColumn(COLUMNS[side_of_the_page]);
}
}
doc.Add(table1);
doc.Add(TitleReport);
doc.Add(Info);
(Also here)
The cause of the issue is that you mix automatic layout by iText (when you add the document header and title using doc.Add) and manual layout (when you add the content using a ColumnText).
The automatic layout by iText does not take any content added by manual layout into account. Thus, you have to take the content added via automatic layout into account for your manual layout (probably it would even be easier to use manual layout for everything).
Furthermore it is a bit surprising that you add the document title after all the content. Given enough content this pushes your title onto a page beyond the first!
And your while (paragraphs < 28) does not make any sense as in the first run through the while body you immediately push that variable beyond 28 in the inner loop for (int i = 0; i < 33; i++) { ...; ++paragraphs; }.
As in your code you add the header (table1, TitleReport, Info) only once, I assume you want to use this header on the first page only.
I changed your code by:
adding the header to the Document first,
requesting the current y position from the PdfWriter,
float afterHeaderY = writer.GetVerticalPosition(true);
assuming the PdfWriter being named writer,
using this y position as the top y coordinate of the columns and the center line on the first page reverting to the hard coded 806 on later pages, and
removing the while loop and code in comments.
The new code:
PdfPTable table1 = new PdfPTable(2);
table1.DefaultCell.Border = Rectangle.NO_BORDER;
table1.WidthPercentage = 100;
PdfPCell cell11 = new PdfPCell();
Paragraph UniName = new Paragraph(#"TRƯỜNG ĐẠI HỌC CÔNG NGHỆ ĐỒNG NAI", fontBold);
UniName.Alignment = Element.ALIGN_CENTER;
Paragraph paragraph = new Paragraph(#"PHÒNG ĐÀO TẠO", times);
paragraph.Alignment = Element.ALIGN_CENTER;
cell11.AddElement(UniName);
cell11.AddElement(paragraph);
cell11.BorderColor = BaseColor.WHITE;
PdfPCell cell12 = new PdfPCell();
Paragraph QH1 = new Paragraph(#"CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM", fontBold);
QH1.Alignment = Element.ALIGN_CENTER;
Paragraph QH = new Paragraph(#"Độc lập - Tự do - Hạnh phúc", fontBold);
QH.Alignment = Element.ALIGN_CENTER;
Paragraph Symbol = new Paragraph(#"----------oOo----------", fontBold);
Symbol.Alignment = Element.ALIGN_CENTER;
cell12.AddElement(QH1);
cell12.AddElement(QH);
cell12.AddElement(Symbol);
cell12.BorderColor = BaseColor.WHITE;
table1.AddCell(cell11);
table1.AddCell(cell12);
Paragraph TitleReport = new Paragraph(#"TỔNG HỢP COI CHẤM THI", titleFont);
TitleReport.Alignment = Element.ALIGN_CENTER;
Paragraph Info = new Paragraph(string.Format(#"Từ ngày: {0} đến ngày: {1} Đơn vị: {2}", DateTime.Now.AddDays(-2).ToString("dd/MM/yyyy"), DateTime.Now.ToString("dd/MM/yyyy"), "Trung tâm quản lý chất lượng"), normalFont);
Info.Alignment = Element.ALIGN_LEFT;
Info.SpacingBefore = 20;
Info.SpacingAfter = 200;
doc.Add(table1);
doc.Add(TitleReport);
doc.Add(Info);
float afterHeaderY = writer.GetVerticalPosition(true);
Rectangle[] COLUMNS = new Rectangle[] {
new Rectangle(36, 36, 290, afterHeaderY),
new Rectangle(305, 36, 559, afterHeaderY)
};
PdfContentByte canvas = writer.DirectContent;
ColumnText ct = new ColumnText(canvas);
int side_of_the_page = 0;
ct.SetSimpleColumn(COLUMNS[side_of_the_page]);
PdfPTable table = new PdfPTable(5);
table.AddCell("STT");
table.AddCell("Số Phách");
table.AddCell("Điểm bằng số");
table.AddCell("Điểm bằng chữ");
table.AddCell("Ghi chú");
for (int i = 0; i < 33; i++)
{
table.AddCell((i + 1).ToString());
table.AddCell("209292");
table.AddCell("4");
table.AddCell("Điểm bằng chữ");
table.AddCell("");
}
table.HeaderRows = 1;
ct.AddElement(table);
while (ColumnText.HasMoreText(ct.Go()))
{
if (side_of_the_page == 0)
{
side_of_the_page = 1;
canvas.MoveTo(297.5f, 36);
canvas.LineTo(297.5f, afterHeaderY);
canvas.Stroke();
}
else
{
side_of_the_page = 0;
doc.NewPage();
COLUMNS = new Rectangle[] {
new Rectangle(36, 36, 290, 806),
new Rectangle(305, 36, 559, 806)
};
afterHeaderY = 806;
}
ct.SetSimpleColumn(COLUMNS[side_of_the_page]);
}
The result:
The big gap between header and content is due to your setting
Info.SpacingAfter = 200;
If you don't want that gap, reduce the value accordingly.

How to print the details in landscape in pdf using itextsharp?

My requirement is to print the details in landscape,not the page rotation.i need content printed in landscape.
Document doc = new Document(iTextSharp.text.PageSize.A4, (float)MarginLeft, (float)MarginRight, (float)MarginTop, (float)MarginBottom);
//210 mm width * 297 mm height
PaperWidthAvailable = iTextSharp.text.Utilities.MillimetersToPoints(210f) - ((float)MarginLeft + (float)MarginRight);
PaperHeightAvailable = iTextSharp.text.Utilities.MillimetersToPoints(297f) - ((float)MarginTop + (float)MarginBottom);
wdtOFcell = (float)BarcodeWidth + (float)BarcodeSpaceHorizontal;
colNo = (int)Math.Floor(PaperWidthAvailable / wdtOFcell);
TableWidth = wdtOFcell * colNo;
htOFcell = (float)BarcodeHeight + (float)BarcodeSpaceVertical;
PdfWriter writer = PdfWriter.GetInstance(doc, memStream);
doc.Open();
int noOfColumns = colNo;
// int additionalRow = imageBarcodeLists.Count % noOfColumns;
int i = 1;
PdfPTable table = new PdfPTable(noOfColumns);
table.DefaultCell.Border = iTextSharp.text.Rectangle.NO_BORDER;
table.HorizontalAlignment = 0;
table.TotalWidth = TableWidth;
table.LockedWidth = true;
float[] widths = new float[colNo];
for (int j = 0; j < colNo; j++)
{
widths[j] = wdtOFcell;
}
table.SetWidths(widths);
iTextSharp.text.Image itextBarcodeImage = null;
foreach (System.Drawing.Image barcodeImage in imageBarcodeLists)
{
var imageCompressor = new ImageCompressionUtility();
System.Drawing.Image barcodeImages = imageCompressor.TrimImageWhiteSpacesFromImage(barcodeImage);
itextBarcodeImage = iTextSharp.text.Image.GetInstance(barcodeImages, BaseColor.BLUE);
itextBarcodeImage.ScaleAbsolute((float)BarcodeWidth, (float)BarcodeHeight);
PdfPCell cells = new PdfPCell(itextBarcodeImage);
cells.Border = iTextSharp.text.Rectangle.NO_BORDER;
cells.PaddingTop = 0f;
cells.PaddingRight = 0f;
cells.PaddingBottom = 0f;
cells.PaddingLeft = 0f;
cells.UseAscender = true;
cells.FixedHeight = htOFcell;
cells.BackgroundColor = BaseColor.WHITE;
cells.Border = iTextSharp.text.Rectangle.NO_BORDER;
table.AddCell(cells);
i++;
}
doc.Add(table);
doc.Close();
The constant iTextSharp.text.PageSize.A4 is actually a Rectangle that is created like this:
public static readonly Rectangle A4 = new Rectangle(595,842);
If you want to rotate the page, you can use the Rotate() method as explained in my answer to this question: How to print custom page size as portrait in itextsharp
However, based on your comment "it rotates only the paper not the content written", you may be looking for a page size that is created like this:
Rectangle myA4 = new Rectangle(842,595);
Document doc = new Document(myA4);
If that doesn't work, please take a look at my answer to the question iText - Rotate page content while creating PDF
In that answer, I introduce a page rotation using a page event:
public class MyPdfPageEvent : iTextSharp.text.pdf.PdfPageEventHelper
{
public override void OnEndPage(PdfWriter writer, Document document)
{
writer.AddPageDictEntry(PdfName.ROTATE, PdfPage.SEASCAPE);
}
}
If none of the above has the effect you desire, you should improve your question (or it will be closed as "unclear what is asked").

cell background image with text itextsharp

Thanks in advance , I know that you're busy .. so I edited this based on the code you gave me ...
first I want you to see what I got when I tried you code ..
and the picture I used as a background is :
as you see I got several problems :
1- the image is not a background to the cells and I want it to be stretched .
2- I tried to put the text in different positions but I failed .
3 - also i got a missing cell that not showed.
the code I used is :
1- the ImageEvent class :
class ImageEvent : IPdfPCellEvent
{
protected Image img;
public ImageEvent(Image img) {
this.img = img;
}
void IPdfPCellEvent.CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
{
img.ScaleToFit(position.Width, position.Height);
img.SetAbsolutePosition(position.Left + (position.Width - img.Width) / 2,
position.Bottom + (position.Height - img.ScaledHeight / 2));
PdfContentByte canvas = canvases[PdfPTable.BACKGROUNDCANVAS];
try {
canvas.AddImage(img);
} catch (DocumentException ex) {
// do nothing
}
}
}
2- The position class :
class PositionEvent : IPdfPCellEvent
{
protected Phrase content;
protected string pos;
public PositionEvent(Phrase content, string pos)
{
this.content = content;
this.pos = pos;
}
void IPdfPCellEvent.CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
{
PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
float x = 0;
float y = 0;
int alignment = 0;
switch (pos)
{
case "TOP_LEFT":
x = position.GetLeft(3);
y = position.GetTop(content.Leading);
alignment = Element.ALIGN_LEFT;
break;
case "TOP_RIGHT":
x = position.GetRight(3);
y = position.GetTop(content.Leading);
alignment = Element.ALIGN_RIGHT;
break;
case "BOTTOM_LEFT":
x = position.GetLeft(3);
y = position.GetBottom(3);
alignment = Element.ALIGN_LEFT;
break;
case "BOTTOM_RIGHT":
x = position.GetRight(3);
y = position.GetBottom(3);
alignment = Element.ALIGN_RIGHT;
break;
case "CENTER_TOP":
x = position.GetRight(3) + position.GetLeft(3) / 2;
y = position.GetTop(3);
alignment = Element.ALIGN_RIGHT;
break;
case "CENTER_BOTTOM":
x = position.GetRight(3) + position.GetLeft(3) / 2;
y = position.GetBottom(3);
alignment = Element.ALIGN_RIGHT;
break;
case "CENTER_MIDDLE":
x = position.GetRight(3) + position.GetLeft(3) / 2;
y = x;
alignment = Element.ALIGN_RIGHT;
break;
}
ColumnText.ShowTextAligned(canvas, alignment, content, x, y, 0);
}
}
3- The method :
public void createPdf(string dest)
{
// 1. Create a Document which contains a table:
Document document = new Document();
PdfWriter.GetInstance(document, new FileStream(dest, FileMode.Create));
document.Open();
PdfPTable table = new PdfPTable(3);
table.WidthPercentage = 100f;
PdfPCell cell1 = new PdfPCell();
PdfPCell cell2 = new PdfPCell();
PdfPCell cell3 = new PdfPCell();
PdfPCell cell4 = new PdfPCell();
PdfPCell cell5 = new PdfPCell();
PdfPCell cell6 = new PdfPCell();
PdfPCell cell7 = new PdfPCell();
// 2. Inside that table, make each cell with specific height:
cell1.FixedHeight=50;
cell2.FixedHeight = 50;
cell3.FixedHeight = 50;
cell4.FixedHeight = 50;
cell5.FixedHeight = 50;
cell6.FixedHeight = 50;
cell7.FixedHeight = 50;
// 3. Each cell has the same background image
string path = string.Concat(this.openFileDialog_pic.FileName);
string imageFilePath = string.Concat(Environment.GetEnvironmentVariable("."), path);
iTextSharp.text.Image IMG = iTextSharp.text.Image.GetInstance(imageFilePath);
ImageEvent imgEvent = new ImageEvent(iTextSharp.text.Image.GetInstance(IMG));
cell1.CellEvent=imgEvent;
cell2.CellEvent = imgEvent;
cell3.CellEvent = imgEvent;
cell4.CellEvent = imgEvent;
cell5.CellEvent = imgEvent;
cell6.CellEvent = imgEvent;
cell7.CellEvent = imgEvent;
// 4. Add text in front of the image at specific position
cell1.CellEvent= new PositionEvent(new Phrase("Top left"), "TOP_LEFT");
cell2.CellEvent=new PositionEvent(new Phrase("Top right"), "TOP_RIGHT");
cell3.CellEvent=new PositionEvent(new Phrase("Bottom left"), "BOTTOM_LEFT");
cell4.CellEvent=new PositionEvent(new Phrase("Bottom right"), "BOTTOM_RIGHT");
cell5.CellEvent = new PositionEvent(new Phrase("Center Top"), "CENTER_TOP");
cell6.CellEvent = new PositionEvent(new Phrase("Center Bottom"), "CENTER_BOTTOM");
cell7.CellEvent = new PositionEvent(new Phrase("Center Middle"), "CENTER_MIDDLE");
// Wrap it all up!
table.AddCell(cell1);
table.AddCell(cell2);
table.AddCell(cell3);
table.AddCell(cell4);
table.AddCell(cell5);
table.AddCell(cell6);
table.AddCell(cell7);
document.Add(table);
document.Close();
}
In an additional comment, you clarify your requirements:
I want to create a document which contains one table. Inside that table, cells
I want to make each cell with specific height
each cell have the same background image
I want to put a text in front the image in the position I want inside the cell. For example: top left of the cell, bottom right of the cell
In other words: you want something like this: position_content_in_cell.pdf
There is more than one way to do this. I don't understand the code sample you use in your question. It uses nested tables and I don't understand why you'd need nested tables.
In the PositionContentInCell example, I used a method that allows you to really fine-tune the exact position of the text. I created an ImageEvent to scale and center the image:
class ImageEvent implements PdfPCellEvent {
protected Image img;
public ImageEvent(Image img) {
this.img = img;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
img.scaleToFit(position.getWidth(), position.getHeight());
img.setAbsolutePosition(position.getLeft() + (position.getWidth() - img.getScaledWidth()) / 2,
position.getBottom() + (position.getHeight() - img.getScaledHeight()) / 2);
PdfContentByte canvas = canvases[PdfPTable.BACKGROUNDCANVAS];
try {
canvas.addImage(img);
} catch (DocumentException ex) {
// do nothing
}
}
}
I created a PositionEvent to add the text inside the cell:
class PositionEvent implements PdfPCellEvent {
protected Phrase content;
protected POSITION pos;
public PositionEvent(Phrase content, POSITION pos) {
this.content = content;
this.pos = pos;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
float x = 0;
float y = 0;
int alignment = 0;
switch (pos) {
case TOP_LEFT:
x = position.getLeft(3);
y = position.getTop(content.getLeading());
alignment = Element.ALIGN_LEFT;
break;
case TOP_RIGHT:
x = position.getRight(3);
y = position.getTop(content.getLeading());
alignment = Element.ALIGN_RIGHT;
break;
case BOTTOM_LEFT:
x = position.getLeft(3);
y = position.getBottom(3);
alignment = Element.ALIGN_LEFT;
break;
case BOTTOM_RIGHT:
x = position.getRight(3);
y = position.getBottom(3);
alignment = Element.ALIGN_RIGHT;
break;
}
ColumnText.showTextAligned(canvas, alignment, content, x, y, 0);
}
}
This is how I use these events:
public void createPdf(String dest) throws IOException, DocumentException {
// 1. Create a Document which contains a table:
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
PdfPTable table = new PdfPTable(2);
PdfPCell cell1 = new PdfPCell();
PdfPCell cell2 = new PdfPCell();
PdfPCell cell3 = new PdfPCell();
PdfPCell cell4 = new PdfPCell();
// 2. Inside that table, make each cell with specific height:
cell1.setFixedHeight(50);
cell2.setFixedHeight(50);
cell3.setFixedHeight(50);
cell4.setFixedHeight(50);
// 3. Each cell has the same background image
ImageEvent imgEvent = new ImageEvent(Image.getInstance(IMG));
cell1.setCellEvent(imgEvent);
cell2.setCellEvent(imgEvent);
cell3.setCellEvent(imgEvent);
cell4.setCellEvent(imgEvent);
// 4. Add text in front of the image at specific position
cell1.setCellEvent(new PositionEvent(new Phrase("Top left"), POSITION.TOP_LEFT));
cell2.setCellEvent(new PositionEvent(new Phrase("Top right"), POSITION.TOP_RIGHT));
cell3.setCellEvent(new PositionEvent(new Phrase("Bottom left"), POSITION.BOTTOM_LEFT));
cell4.setCellEvent(new PositionEvent(new Phrase("Bottom right"), POSITION.BOTTOM_RIGHT));
// Wrap it all up!
table.addCell(cell1);
table.addCell(cell2);
table.addCell(cell3);
table.addCell(cell4);
document.add(table);
document.close();
}
Normally, I would write this code in a more efficient way, but I order the code lines in a way so that they reflect your requirements 1, 2, 3 and 4 literally.
Update:
In the comments, you asked several additional questions. For instance: how to stretch the image:
You were able to answer most of these questions, for instance based on my hint to use ScaleAbsolute:
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
img.scaleAbsolute(position.getWidth(), position.getHeight());
img.setAbsolutePosition(position.getLeft(), position.getBottom());
PdfContentByte canvas = canvases[PdfPTable.BACKGROUNDCANVAS];
try {
canvas.addImage(img);
} catch (DocumentException ex) {
// do nothing
}
}
You had one more question that required an extra example (it was hard to explain it in a comment box). I named that example PositionContentInCell2
Instead of using the POSITION enumeration, you asked if it was possible to pass x and y values. You could do that, but you probably won't always know the width and the height of the cells, so why not define percentages such as wPct and hPct, along with an alignment:
class PositionEvent implements PdfPCellEvent {
protected Phrase content;
protected float wPct;
protected float hPct;
protected int alignment;
public PositionEvent(Phrase content, float wPct, float hPct, int alignment) {
this.content = content;
this.wPct = wPct;
this.hPct = hPct;
this.alignment = alignment;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
float x = position.getLeft() + wPct * position.getWidth();
float y = position.getBottom() + hPct * (position.getHeight() - content.getLeading());
ColumnText.showTextAligned(canvas, alignment, content, x, y, 0);
}
}
Now you can add these events like this:
cell1.setCellEvent(new PositionEvent(new Phrase(14, "Top left"), 0, 1, Element.ALIGN_LEFT));
cell2.setCellEvent(new PositionEvent(new Phrase(14, "Top right"), 1, 1, Element.ALIGN_RIGHT));
cell3.setCellEvent(new PositionEvent(new Phrase(14, "Top center"), 0.5f, 1, Element.ALIGN_CENTER));
cell4.setCellEvent(new PositionEvent(new Phrase(14, "Bottom center"), 0.5f, 0, Element.ALIGN_CENTER));
cell5.setCellEvent(new PositionEvent(new Phrase(14, "Middle center"), 0.5f, 0.5f, Element.ALIGN_CENTER));
cell6.setCellEvent(new PositionEvent(new Phrase(14, "Middle center"), 0.5f, 0.5f, Element.ALIGN_CENTER));
cell7.setCellEvent(new PositionEvent(new Phrase(14, "Bottom left"), 0, 0, Element.ALIGN_LEFT));
cell8.setCellEvent(new PositionEvent(new Phrase(14, "Bottom right"), 1, 0, Element.ALIGN_RIGHT));
Of course, if you prefer passing x and y (after all: you do know the height, because you are defining a fixed height, the code can be made even simpler: you don't multiple the variables with position.getWidth and position.getHeight().

draw table with filled cells in a PDF using iText for .NET

I want to draw a schedule, based on a table (including borders), where some of the cells are (partly) filled with a color. This color is based on PdfTemplate which is added as an image to the cell.
I've create a test project for it, and attached placed the output at: PDF output
In the example, I expect it to draw the filled line, everytime 2 blocks larger. As you can see, it is a bit more than the 2 blocks.
The template I create, should be the exact the size of the table cells. So I don't understand, why it keeps getting bigger every iteration.
Any ideas how to fix this?
public Test()
{
int cellWidth = 23;
int usernameCellWith = 86;
float[] scheduleTableColumnWidths = new float[33];
scheduleTableColumnWidths[0] = usernameCellWith;
for (int i = 1; i <= 32; i++)
scheduleTableColumnWidths[i] = cellWidth;
using (MemoryStream stream = new MemoryStream())
{
Rectangle rect = PageSize.GetRectangle("A4");
rect = new Rectangle(rect.Height, rect.Width, 90);
using (Document document = new Document(rect, 10f, 10f, 10f, 10f))
{
PdfWriter writer = PdfWriter.GetInstance(document, stream);
if (!document.IsOpen())
{
document.NewPage();
document.Open();
}
PdfPTable containerTable = new PdfPTable(1);
containerTable.DefaultCell.Border = Rectangle.NO_BORDER;
containerTable.WidthPercentage = 100;
PdfPTable scheduleTable = new PdfPTable(scheduleTableColumnWidths);
for (int iRow = 0; iRow <= 23; iRow++)
{
PdfPCell usernameCell = new PdfPCell(new Phrase("user "+ iRow));
usernameCell.FixedHeight = cellWidth;
scheduleTable.AddCell(usernameCell);
for (int iColumn = 1; iColumn <= 32; iColumn++)
{
PdfPCell cell = new PdfPCell();
cell.FixedHeight = cellWidth;
if (iColumn == 1 && iRow % 2 == 0)
{
float width = (float)(iRow + 1) * cellWidth;
PdfTemplate template = writer.DirectContent.CreateTemplate(width, cellWidth);
template.SetColorFill(new BaseColor(System.Drawing.ColorTranslator.FromHtml("#255C8A")));
template.Rectangle(0, 0, width, cellWidth);
template.Fill();
cell = new PdfPCell(Image.GetInstance(template));
}
scheduleTable.AddCell(cell);
}
scheduleTable.CompleteRow();
}
containerTable.AddCell(scheduleTable);
containerTable.CompleteRow();
document.Add(containerTable);
document.CloseDocument();
}
}
}
Do you absolutely need to use a PdfTemplate? Unless you've just posted a simplified version of your code it is screaming to use a colspan instead and then iText will just calculate everything for you.
Below is a modified version of what you posted. I moved some of your "magic numbers" to variables just to help my own mental process. They might not be named ideally but they do the job. Also, when working in a double for loop I recommend always looping over rows and columns and then performing logic. Your code loops over rows, does some logic for a "first cell" and then loops over a subset of the columns and performs more logic. Although absolutely 100% valid I personally find it confusing, especially when having to jump between 1 and 0 as a starting value.
Also, also, I very strongly recommend avoiding CompleteRow(). It exists to solve a certain problem but it also literally means "my logic above might be wrong so iText, could you just fudge the numbers for me?"
I commented most of what I changed so hopefully this is helpful.
public void Test() {
int cellWidth = 23;
int usernameCellWith = 86;
int maxNumberOfColumns = 32;
int maxNumberOfRows = 24;
float[] scheduleTableColumnWidths = new float[maxNumberOfColumns];
scheduleTableColumnWidths[0] = usernameCellWith;
for (int i = 1; i < maxNumberOfColumns; i++)
scheduleTableColumnWidths[i] = cellWidth;
using (MemoryStream stream = new MemoryStream()) {
iTextSharp.text.Rectangle rect = PageSize.GetRectangle("A4");
rect = new iTextSharp.text.Rectangle(rect.Height, rect.Width, 90);
using (Document document = new Document(rect, 10f, 10f, 10f, 10f)) {
PdfWriter writer = PdfWriter.GetInstance(document, stream);
//Unless this code is just a sample, a new document is never open and NewPage() is implied so these four lines could just be document.Open();
if (!document.IsOpen()) {
document.NewPage();
document.Open();
}
PdfPTable containerTable = new PdfPTable(1);
containerTable.DefaultCell.Border = iTextSharp.text.Rectangle.NO_BORDER;
containerTable.WidthPercentage = 100;
PdfPTable scheduleTable = new PdfPTable(scheduleTableColumnWidths);
//Loop through each row
for (int iRow = 0; iRow < maxNumberOfRows; iRow++) {
//Loop through each column
for (int iColumn = 0; iColumn < maxNumberOfColumns; iColumn++) {
//Placeholder variable that will be instantiated within the if statements below
PdfPCell cell;
//On the first column (of every row)
if (0 == iColumn) {
cell = new PdfPCell(new Phrase("user " + iRow));
//On the second column of every other row starting with the first (zeroth) row
} else if ((iColumn == 1) && (iRow % 2 == 0)) {
cell = new PdfPCell();
//Have the cell span based on the current row number
cell.Colspan = iRow + 1;
//Set the color
cell.BackgroundColor = new BaseColor(System.Drawing.ColorTranslator.FromHtml("#255C8A"));
//Tell the inner for loop that we've accounted for some cells already
iColumn += iRow;
//Every other cell
} else {
cell = new PdfPCell();
}
//This is weird
cell.FixedHeight = cellWidth;
//Regardless of the above, add a cell
scheduleTable.AddCell(cell);
}
}
containerTable.AddCell(scheduleTable);
document.Add(containerTable);
document.CloseDocument();
}
}
}

Add Header and Footer for PDF using iTextsharp

How can I add header and footer for each page in the pdf.
Headed will contain just a text
Footer will contain a text and pagination for pdf (Page : 1 of 4)
How is this possible ? I tried to add the below line, but header does not show up in pdf.
document.AddHeader("Header", "Header Text");
This the code I am using for generation PDF :
protected void GeneratePDF_Click(object sender, EventArgs e)
{
DataTable dt = getData();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=Locations.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Document document = new Document();
PdfWriter.GetInstance(document, Response.OutputStream);
document.Open();
iTextSharp.text.Font font5 = iTextSharp.text.FontFactory.GetFont(FontFactory.COURIER , 8);
PdfPTable table = new PdfPTable(dt.Columns.Count);
PdfPRow row = null;
float[] widths = new float[] { 6f, 6f, 2f, 4f, 2f };
table.SetWidths(widths);
table.WidthPercentage = 100;
int iCol = 0;
string colname = "";
PdfPCell cell = new PdfPCell(new Phrase("Locations"));
cell.Colspan = dt.Columns.Count;
foreach (DataColumn c in dt.Columns)
{
table.AddCell(new Phrase(c.ColumnName, font5));
}
foreach (DataRow r in dt.Rows)
{
if (dt.Rows.Count > 0)
{
table.AddCell(new Phrase(r[0].ToString(), font5));
table.AddCell(new Phrase(r[1].ToString(), font5));
table.AddCell(new Phrase(r[2].ToString(), font5));
table.AddCell(new Phrase(r[3].ToString(), font5));
table.AddCell(new Phrase(r[4].ToString(), font5));
}
}
document.Add(table);
document.Close();
Response.Write(document);
Response.End();
}
}
As already answered by #Bruno you need to use pageEvents.
Please check out the sample code below:
private void CreatePDF()
{
string fileName = string.Empty;
DateTime fileCreationDatetime = DateTime.Now;
fileName = string.Format("{0}.pdf", fileCreationDatetime.ToString(#"yyyyMMdd") + "_" + fileCreationDatetime.ToString(#"HHmmss"));
string pdfPath = Server.MapPath(#"~\PDFs\") + fileName;
using (FileStream msReport = new FileStream(pdfPath, FileMode.Create))
{
//step 1
using (Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 140f, 10f))
{
try
{
// step 2
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, msReport);
pdfWriter.PageEvent = new Common.ITextEvents();
//open the stream
pdfDoc.Open();
for (int i = 0; i < 10; i++)
{
Paragraph para = new Paragraph("Hello world. Checking Header Footer", new Font(Font.FontFamily.HELVETICA, 22));
para.Alignment = Element.ALIGN_CENTER;
pdfDoc.Add(para);
pdfDoc.NewPage();
}
pdfDoc.Close();
}
catch (Exception ex)
{
//handle exception
}
finally
{
}
}
}
}
And create one class file named ITextEvents.cs and add following code:
public class ITextEvents : PdfPageEventHelper
{
// This is the contentbyte object of the writer
PdfContentByte cb;
// we will put the final number of pages in a template
PdfTemplate headerTemplate, footerTemplate;
// this is the BaseFont we are going to use for the header / footer
BaseFont bf = null;
// This keeps track of the creation time
DateTime PrintTime = DateTime.Now;
#region Fields
private string _header;
#endregion
#region Properties
public string Header
{
get { return _header; }
set { _header = value; }
}
#endregion
public override void OnOpenDocument(PdfWriter writer, Document document)
{
try
{
PrintTime = DateTime.Now;
bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb = writer.DirectContent;
headerTemplate = cb.CreateTemplate(100, 100);
footerTemplate = cb.CreateTemplate(50, 50);
}
catch (DocumentException de)
{
}
catch (System.IO.IOException ioe)
{
}
}
public override void OnEndPage(iTextSharp.text.pdf.PdfWriter writer, iTextSharp.text.Document document)
{
base.OnEndPage(writer, document);
iTextSharp.text.Font baseFontNormal = new iTextSharp.text.Font(iTextSharp.text.Font.FontFamily.HELVETICA, 12f, iTextSharp.text.Font.NORMAL, iTextSharp.text.BaseColor.BLACK);
iTextSharp.text.Font baseFontBig = new iTextSharp.text.Font(iTextSharp.text.Font.FontFamily.HELVETICA, 12f, iTextSharp.text.Font.BOLD, iTextSharp.text.BaseColor.BLACK);
Phrase p1Header = new Phrase("Sample Header Here", baseFontNormal);
//Create PdfTable object
PdfPTable pdfTab = new PdfPTable(3);
//We will have to create separate cells to include image logo and 2 separate strings
//Row 1
PdfPCell pdfCell1 = new PdfPCell();
PdfPCell pdfCell2 = new PdfPCell(p1Header);
PdfPCell pdfCell3 = new PdfPCell();
String text = "Page " + writer.PageNumber + " of ";
//Add paging to header
{
cb.BeginText();
cb.SetFontAndSize(bf, 12);
cb.SetTextMatrix(document.PageSize.GetRight(200), document.PageSize.GetTop(45));
cb.ShowText(text);
cb.EndText();
float len = bf.GetWidthPoint(text, 12);
//Adds "12" in Page 1 of 12
cb.AddTemplate(headerTemplate, document.PageSize.GetRight(200) + len, document.PageSize.GetTop(45));
}
//Add paging to footer
{
cb.BeginText();
cb.SetFontAndSize(bf, 12);
cb.SetTextMatrix(document.PageSize.GetRight(180), document.PageSize.GetBottom(30));
cb.ShowText(text);
cb.EndText();
float len = bf.GetWidthPoint(text, 12);
cb.AddTemplate(footerTemplate, document.PageSize.GetRight(180) + len, document.PageSize.GetBottom(30));
}
//Row 2
PdfPCell pdfCell4 = new PdfPCell(new Phrase("Sub Header Description", baseFontNormal));
//Row 3
PdfPCell pdfCell5 = new PdfPCell(new Phrase("Date:" + PrintTime.ToShortDateString(), baseFontBig));
PdfPCell pdfCell6 = new PdfPCell();
PdfPCell pdfCell7 = new PdfPCell(new Phrase("TIME:" + string.Format("{0:t}", DateTime.Now), baseFontBig));
//set the alignment of all three cells and set border to 0
pdfCell1.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell2.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell3.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell4.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell5.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell6.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell7.HorizontalAlignment = Element.ALIGN_CENTER;
pdfCell2.VerticalAlignment = Element.ALIGN_BOTTOM;
pdfCell3.VerticalAlignment = Element.ALIGN_MIDDLE;
pdfCell4.VerticalAlignment = Element.ALIGN_TOP;
pdfCell5.VerticalAlignment = Element.ALIGN_MIDDLE;
pdfCell6.VerticalAlignment = Element.ALIGN_MIDDLE;
pdfCell7.VerticalAlignment = Element.ALIGN_MIDDLE;
pdfCell4.Colspan = 3;
pdfCell1.Border = 0;
pdfCell2.Border = 0;
pdfCell3.Border = 0;
pdfCell4.Border = 0;
pdfCell5.Border = 0;
pdfCell6.Border = 0;
pdfCell7.Border = 0;
//add all three cells into PdfTable
pdfTab.AddCell(pdfCell1);
pdfTab.AddCell(pdfCell2);
pdfTab.AddCell(pdfCell3);
pdfTab.AddCell(pdfCell4);
pdfTab.AddCell(pdfCell5);
pdfTab.AddCell(pdfCell6);
pdfTab.AddCell(pdfCell7);
pdfTab.TotalWidth = document.PageSize.Width - 80f;
pdfTab.WidthPercentage = 70;
//pdfTab.HorizontalAlignment = Element.ALIGN_CENTER;
//call WriteSelectedRows of PdfTable. This writes rows from PdfWriter in PdfTable
//first param is start row. -1 indicates there is no end row and all the rows to be included to write
//Third and fourth param is x and y position to start writing
pdfTab.WriteSelectedRows(0, -1, 40, document.PageSize.Height - 30, writer.DirectContent);
//set pdfContent value
//Move the pointer and draw line to separate header section from rest of page
cb.MoveTo(40, document.PageSize.Height - 100);
cb.LineTo(document.PageSize.Width - 40, document.PageSize.Height - 100);
cb.Stroke();
//Move the pointer and draw line to separate footer section from rest of page
cb.MoveTo(40, document.PageSize.GetBottom(50) );
cb.LineTo(document.PageSize.Width - 40, document.PageSize.GetBottom(50));
cb.Stroke();
}
public override void OnCloseDocument(PdfWriter writer, Document document)
{
base.OnCloseDocument(writer, document);
headerTemplate.BeginText();
headerTemplate.SetFontAndSize(bf, 12);
headerTemplate.SetTextMatrix(0, 0);
headerTemplate.ShowText((writer.PageNumber - 1).ToString());
headerTemplate.EndText();
footerTemplate.BeginText();
footerTemplate.SetFontAndSize(bf, 12);
footerTemplate.SetTextMatrix(0, 0);
footerTemplate.ShowText((writer.PageNumber - 1).ToString());
footerTemplate.EndText();
}
}
I hope it helps!
For iTextSharp 4.1.6, the last version of iTextSharp that was licensed as LGPL, the solution provided by Alvaro Patiño is both simple and effective.
Because documentation is somewhat scarse I'd like to extend his answer with this code snippet that can be used to change the appearance of the header and footer. By default they have a rather large font-size and a thick border, which many people will want to change.
// Parameters passed on to the function that creates the PDF
String headerText = "Your header text";
String footerText = "Page";
// Define a font and font-size in points (plus f for float) and pick a color
// This one is for both header and footer but you can also create seperate ones
Font fontHeaderFooter = FontFactory.GetFont("arial", 8f);
fontHeaderFooter.Color = Color.GRAY;
// Apply the font to the headerText and create a Phrase with the result
Chunk chkHeader = new Chunk(headerText, fontHeaderFooter);
Phrase p1 = new Phrase(chkHeader);
// create a HeaderFooter element for the header using the Phrase
// The boolean turns numbering on or off
HeaderFooter header = new HeaderFooter(p1, false);
// Remove the border that is set by default
header.Border = Rectangle.NO_BORDER;
// Align the text: 0 is left, 1 center and 2 right.
header.Alignment = 1;
// add the header to the document
document.Header = header;
// The footer is created in an similar way
// If you want to use numbering like in this example, add a whitespace to the
// text because by default there's no space in between them
if (footerText.Substring(footerText.Length - 1) != " ") footerText += " ";
Chunk chkFooter = new Chunk(footerText, fontHeaderFooter);
Phrase p2 = new Phrase(chkFooter);
// Turn on numbering by setting the boolean to true
HeaderFooter footer = new HeaderFooter(p2, true);
footer.Border = Rectangle.NO_BORDER;
footer.Alignment = 1;
document.Footer = footer;
// Open the Document for writing and continue creating its content
document.Open();
For more info check Creating PDFs with iTextSharp and iTextSharp - Adding Text with Chunks, Phrases and Paragraphs. The source code on GitHub may also be useful.
We don't talk about iTextSharp anymore. You are using iText 5 for .NET. The current version is iText 7 for .NET.
Obsolete answer:
The AddHeader has been deprecated a long time ago and has been removed from iTextSharp. Adding headers and footers is now done using page events. The examples are in Java, but you can find the C# port of the examples here and here (scroll to the bottom of the page for links to the .cs files).
Make sure you read the documentation. A common mistake by many developers have made before you, is adding content in the OnStartPage. You should only add content in the OnEndPage. It's also obvious that you need to add the content at absolute coordinates (for instance using ColumnText) and that you need to reserve sufficient space for the header and footer by defining the margins of your document correctly.
Updated answer:
If you are new to iText, you should use iText 7 and use event handlers to add headers and footers. See chapter 3 of the iText 7 Jump-Start Tutorial for .NET.
When you have a PdfDocument in iText 7, you can add an event handler:
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler());
This is an example of the hard way to add text at an absolute position (using PdfCanvas):
protected internal class MyEventHandler : IEventHandler {
public virtual void HandleEvent(Event #event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent)#event;
PdfDocument pdfDoc = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();
int pageNumber = pdfDoc.GetPageNumber(page);
Rectangle pageSize = page.GetPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
//Add header
pdfCanvas.BeginText()
.SetFontAndSize(C03E03_UFO.helvetica, 9)
.MoveText(pageSize.GetWidth() / 2 - 60, pageSize.GetTop() - 20)
.ShowText("THE TRUTH IS OUT THERE")
.MoveText(60, -pageSize.GetTop() + 30)
.ShowText(pageNumber.ToString())
.EndText();
pdfCanvas.Release();
}
}
This is a slightly higher-level way, using Canvas:
protected internal class MyEventHandler : IEventHandler {
public virtual void HandleEvent(Event #event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent)#event;
PdfDocument pdfDoc = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();
int pageNumber = pdfDoc.GetPageNumber(page);
Rectangle pageSize = page.GetPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
//Add watermark
Canvas canvas = new Canvas(pdfCanvas, pdfDoc, page.getPageSize());
canvas.setFontColor(Color.WHITE);
canvas.setProperty(Property.FONT_SIZE, 60);
canvas.setProperty(Property.FONT, helveticaBold);
canvas.showTextAligned(new Paragraph("CONFIDENTIAL"),
298, 421, pdfDoc.getPageNumber(page),
TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
pdfCanvas.Release();
}
}
There are other ways to add content at absolute positions. They are described in the different iText books.
The answers to this question, while they are correct, are very unnecessarily complicated. It doesn't take that much code for text to show up in the header/footer. Here is a simple example of adding text to the header/footer.
The current version of iTextSharp works by implementing a callback class which is defined by the IPdfPageEvent interface. From what I understand, it's not a good idea to add things during the OnStartPage method, so instead I will be using the OnEndPage page method. The events are triggered depending on what is happening to the PdfWriter
First, create a class which implements IPdfPageEvent. In the:
public void OnEndPage(PdfWriter writer, Document document)
function, obtain the PdfContentByte object by calling
PdfContentByte cb = writer.DirectContent;
Now you can add text very easily:
ColumnText ct = new ColumnText(cb);
cb.BeginText();
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12.0f);
//Note, (0,0) in this case is at the bottom of the document
cb.SetTextMatrix(document.LeftMargin, document.BottomMargin);
cb.ShowText(String.Format("{0} {1}", "Testing Text", "Like this"));
cb.EndText();
So the full for the OnEndPage function will be:
public void OnEndPage(PdfWriter writer, Document document)
{
PdfContentByte cb = writer.DirectContent;
ColumnText ct = new ColumnText(cb);
cb.BeginText();
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12.0f);
cb.SetTextMatrix(document.LeftMargin, document.BottomMargin);
cb.ShowText(String.Format("{0} {1}", "Testing Text", "Like this"));
cb.EndText();
}
This will show up at the bottom of your document. One last thing. Don't forget to assign the IPdfPageEvent like this:
writter.PageEvent = new PDFEvents();
To the PdfWriter writter object
For the header it is very similar. Just flip the SetTextMatrix y coordinate:
cb.SetTextMatrix(document.LeftMargin, document.PageSize.Height - document.TopMargin);
Just add this line before opening the document (must be before):
document.Header = new HeaderFooter(new Phrase("Header Text"), false);
document.Open();
For those just needing headers!!!
All of these answers are way too complicated if you are designing your page via PdfPTables (which is the easiest way IMO)! If you are working with PdfPTables you can literally just define your first x number of table rows as header rows. They will then repeat on every page.
No need to invoke bulky page events.
1 line of code:
myPdfPTable.HeaderRows = myHeaderRowsAmount
Easy codes that work successfully:
protected void Page_Load(object sender, EventArgs e)
{
.
.
using (MemoryStream ms = new MemoryStream())
{
.
.
iTextSharp.text.Document doc = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 36, 36, 54, 54);
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, ms);
writer.PageEvent = new HeaderFooter();
doc.Open();
.
.
// make your document content..
.
.
doc.Close();
writer.Close();
// output
Response.ContentType = "application/pdf;";
Response.AddHeader("Content-Disposition", "attachment; filename=clientfilename.pdf");
byte[] pdf = ms.ToArray();
Response.OutputStream.Write(pdf, 0, pdf.Length);
}
.
.
.
}
class HeaderFooter : PdfPageEventHelper
{
public override void OnEndPage(PdfWriter writer, Document document)
{
// Make your table header using PdfPTable and name that tblHeader
.
.
tblHeader.WriteSelectedRows(0, -1, page.Left + document.LeftMargin, page.Top, writer.DirectContent);
.
.
// Make your table footer using PdfPTable and name that tblFooter
.
.
tblFooter.WriteSelectedRows(0, -1, page.Left + document.LeftMargin, writer.PageSize.GetBottom(document.BottomMargin), writer.DirectContent);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using DataLayer;
namespace DataMngt.MyCode
{
public class HeaderFooter : PdfPageEventHelper
{
#region Startup_Stuff
private string[] _headerLines;
private string _footerLine;
private DefineFont _boldFont;
private DefineFont _normalFont;
private iTextSharp.text.Font fontTxtBold;
private iTextSharp.text.Font fontTxtRegular;
private int _fontPointSize = 0;
private bool hasFooter = false;
private bool hasHeader = false;
private int _headerWidth = 0;
private int _headerHeight = 0;
private int _footerWidth = 0;
private int _footerHeight = 0;
private int _leftMargin = 0;
private int _rightMargin = 0;
private int _topMargin = 0;
private int _bottomMargin = 0;
private PageNumbers NumberSettings;
private DateTime runTime = DateTime.Now;
public enum PageNumbers
{
None,
HeaderPlacement,
FooterPlacement
}
// This is the contentbyte object of the writer
PdfContentByte cb;
PdfTemplate headerTemplate;
PdfTemplate footerTemplate;
public string[] headerLines
{
get
{
return _headerLines;
}
set
{
_headerLines = value;
hasHeader = true;
}
}
public string footerLine
{
get
{
return _footerLine;
}
set
{
_footerLine = value;
hasFooter = true;
}
}
public DefineFont boldFont
{
get
{
return _boldFont;
}
set
{
_boldFont = value;
}
}
public DefineFont normalFont
{
get
{
return _normalFont;
}
set
{
_normalFont = value;
}
}
public int fontPointSize
{
get
{
return _fontPointSize;
}
set
{
_fontPointSize = value;
}
}
public int leftMargin
{
get
{
return _leftMargin;
}
set
{
_leftMargin = value;
}
}
public int rightMargin
{
get
{
return _rightMargin;
}
set
{
_rightMargin = value;
}
}
public int topMargin
{
get
{
return _topMargin;
}
set
{
_topMargin = value;
}
}
public int bottomMargin
{
get
{
return _bottomMargin;
}
set
{
_bottomMargin = value;
}
}
public int headerheight
{
get
{
return _headerHeight;
}
}
public int footerHeight
{
get
{
return _footerHeight;
}
}
public PageNumbers PageNumberSettings
{
get
{
return NumberSettings;
}
set
{
NumberSettings = value;
}
}
#endregion
#region Write_Headers_Footers
public override void OnEndPage(PdfWriter writer, Document document)
{
if (hasHeader)
{
// left side is the string array passed in
// right side is a built in string array (0 = date, 1 = time, 2(optional) = page)
float[] widths = new float[2] { 90f, 10f };
PdfPTable hdrTable = new PdfPTable(2);
hdrTable.TotalWidth = document.PageSize.Width - (_leftMargin + _rightMargin);
hdrTable.WidthPercentage = 95;
hdrTable.SetWidths(widths);
hdrTable.LockedWidth = true;
for (int hdrIdx = 0; hdrIdx < (_headerLines.Length < 2 ? 2 : _headerLines.Length); hdrIdx ++)
{
string leftLine = (hdrIdx < _headerLines.Length ? _headerLines[hdrIdx] : string.Empty);
Paragraph leftPara = new Paragraph(5, leftLine, (hdrIdx == 0 ? fontTxtBold : fontTxtRegular));
switch (hdrIdx)
{
case 0:
{
leftPara.Font.Size = _fontPointSize;
PdfPCell leftCell = new PdfPCell(leftPara);
leftCell.HorizontalAlignment = Element.ALIGN_LEFT;
leftCell.Border = 0;
string rightLine = string.Format(SalesPlanResources.datePara, runTime.ToString(SalesPlanResources.datePrintMask));
Paragraph rightPara = new Paragraph(5, rightLine, (hdrIdx == 0 ? fontTxtBold : fontTxtRegular));
rightPara.Font.Size = _fontPointSize;
PdfPCell rightCell = new PdfPCell(rightPara);
rightCell.HorizontalAlignment = Element.ALIGN_LEFT;
rightCell.Border = 0;
hdrTable.AddCell(leftCell);
hdrTable.AddCell(rightCell);
break;
}
case 1:
{
leftPara.Font.Size = _fontPointSize;
PdfPCell leftCell = new PdfPCell(leftPara);
leftCell.HorizontalAlignment = Element.ALIGN_LEFT;
leftCell.Border = 0;
string rightLine = string.Format(SalesPlanResources.timePara, runTime.ToString(SalesPlanResources.timePrintMask));
Paragraph rightPara = new Paragraph(5, rightLine, (hdrIdx == 0 ? fontTxtBold : fontTxtRegular));
rightPara.Font.Size = _fontPointSize;
PdfPCell rightCell = new PdfPCell(rightPara);
rightCell.HorizontalAlignment = Element.ALIGN_LEFT;
rightCell.Border = 0;
hdrTable.AddCell(leftCell);
hdrTable.AddCell(rightCell);
break;
}
case 2:
{
leftPara.Font.Size = _fontPointSize;
PdfPCell leftCell = new PdfPCell(leftPara);
leftCell.HorizontalAlignment = Element.ALIGN_LEFT;
leftCell.Border = 0;
string rightLine;
if (NumberSettings == PageNumbers.HeaderPlacement)
{
rightLine = string.Concat(SalesPlanResources.pagePara, writer.PageNumber.ToString());
}
else
{
rightLine = string.Empty;
}
Paragraph rightPara = new Paragraph(5, rightLine, fontTxtRegular);
rightPara.Font.Size = _fontPointSize;
PdfPCell rightCell = new PdfPCell(rightPara);
rightCell.HorizontalAlignment = Element.ALIGN_LEFT;
rightCell.Border = 0;
hdrTable.AddCell(leftCell);
hdrTable.AddCell(rightCell);
break;
}
default:
{
leftPara.Font.Size = _fontPointSize;
PdfPCell leftCell = new PdfPCell(leftPara);
leftCell.HorizontalAlignment = Element.ALIGN_LEFT;
leftCell.Border = 0;
leftCell.Colspan = 2;
hdrTable.AddCell(leftCell);
break;
}
}
}
hdrTable.WriteSelectedRows(0, -1, _leftMargin, document.PageSize.Height - _topMargin, writer.DirectContent);
//Move the pointer and draw line to separate header section from rest of page
cb.MoveTo(_leftMargin, document.Top + 10);
cb.LineTo(document.PageSize.Width - _leftMargin, document.Top + 10);
cb.Stroke();
}
if (hasFooter)
{
// footer line is the width of the page so it is centered horizontally
PdfPTable ftrTable = new PdfPTable(1);
float[] widths = new float[1] {100 };
ftrTable.TotalWidth = document.PageSize.Width - 10;
ftrTable.WidthPercentage = 95;
ftrTable.SetWidths(widths);
string OneLine;
if (NumberSettings == PageNumbers.FooterPlacement)
{
OneLine = string.Concat(_footerLine, writer.PageNumber.ToString());
}
else
{
OneLine = _footerLine;
}
Paragraph onePara = new Paragraph(0, OneLine, fontTxtRegular);
onePara.Font.Size = _fontPointSize;
PdfPCell oneCell = new PdfPCell(onePara);
oneCell.HorizontalAlignment = Element.ALIGN_CENTER;
oneCell.Border = 0;
ftrTable.AddCell(oneCell);
ftrTable.WriteSelectedRows(0, -1, _leftMargin, (_footerHeight), writer.DirectContent);
//Move the pointer and draw line to separate footer section from rest of page
cb.MoveTo(_leftMargin, document.PageSize.GetBottom(_footerHeight + 2));
cb.LineTo(document.PageSize.Width - _leftMargin, document.PageSize.GetBottom(_footerHeight + 2));
cb.Stroke();
}
}
#endregion
#region Setup_Headers_Footers_Happens_here
public override void OnOpenDocument(PdfWriter writer, Document document)
{
// create the fonts that are to be used
// first the hightlight or Bold font
fontTxtBold = FontFactory.GetFont(_boldFont.fontFamily, _boldFont.fontSize, _boldFont.foreColor);
if (_boldFont.isBold)
{
fontTxtBold.SetStyle(Font.BOLD);
}
if (_boldFont.isItalic)
{
fontTxtBold.SetStyle(Font.ITALIC);
}
if (_boldFont.isUnderlined)
{
fontTxtBold.SetStyle(Font.UNDERLINE);
}
// next the normal font
fontTxtRegular = FontFactory.GetFont(_normalFont.fontFamily, _normalFont.fontSize, _normalFont.foreColor);
if (_normalFont.isBold)
{
fontTxtRegular.SetStyle(Font.BOLD);
}
if (_normalFont.isItalic)
{
fontTxtRegular.SetStyle(Font.ITALIC);
}
if (_normalFont.isUnderlined)
{
fontTxtRegular.SetStyle(Font.UNDERLINE);
}
// now build the header and footer templates
try
{
float pageHeight = document.PageSize.Height;
float pageWidth = document.PageSize.Width;
_headerWidth = (int)pageWidth - ((int)_rightMargin + (int)_leftMargin);
_footerWidth = _headerWidth;
if (hasHeader)
{
// i basically dummy build the headers so i can trial fit them and see how much space they take.
float[] widths = new float[1] { 90f };
PdfPTable hdrTable = new PdfPTable(1);
hdrTable.TotalWidth = document.PageSize.Width - (_leftMargin + _rightMargin);
hdrTable.WidthPercentage = 95;
hdrTable.SetWidths(widths);
hdrTable.LockedWidth = true;
_headerHeight = 0;
for (int hdrIdx = 0; hdrIdx < (_headerLines.Length < 2 ? 2 : _headerLines.Length); hdrIdx++)
{
Paragraph hdrPara = new Paragraph(5, hdrIdx > _headerLines.Length - 1 ? string.Empty : _headerLines[hdrIdx], (hdrIdx > 0 ? fontTxtRegular : fontTxtBold));
PdfPCell hdrCell = new PdfPCell(hdrPara);
hdrCell.HorizontalAlignment = Element.ALIGN_LEFT;
hdrCell.Border = 0;
hdrTable.AddCell(hdrCell);
_headerHeight = _headerHeight + (int)hdrTable.GetRowHeight(hdrIdx);
}
// iTextSharp underestimates the size of each line so fudge it a little
// this gives me 3 extra lines to play with on the spacing
_headerHeight = _headerHeight + (_fontPointSize * 3);
}
if (hasFooter)
{
_footerHeight = (_fontPointSize * 2);
}
document.SetMargins(_leftMargin, _rightMargin, (_topMargin + _headerHeight), _footerHeight);
cb = writer.DirectContent;
if (hasHeader)
{
headerTemplate = cb.CreateTemplate(_headerWidth, _headerHeight);
}
if (hasFooter)
{
footerTemplate = cb.CreateTemplate(_footerWidth, _footerHeight);
}
}
catch (DocumentException de)
{
}
catch (System.IO.IOException ioe)
{
}
}
#endregion
#region Cleanup_Doc_Processing
public override void OnCloseDocument(PdfWriter writer, Document document)
{
base.OnCloseDocument(writer, document);
if (hasHeader)
{
headerTemplate.BeginText();
headerTemplate.SetTextMatrix(0, 0);
if (NumberSettings == PageNumbers.HeaderPlacement)
{
}
headerTemplate.EndText();
}
if (hasFooter)
{
footerTemplate.BeginText();
footerTemplate.SetTextMatrix(0, 0);
if (NumberSettings == PageNumbers.FooterPlacement)
{
}
footerTemplate.EndText();
}
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace DataMngt.MyCode
{
// used to define the fonts passed into the header and footer class
public struct DefineFont
{
public string fontFamily { get; set; }
public int fontSize { get; set; }
public bool isBold { get; set; }
public bool isItalic { get; set; }
public bool isUnderlined { get; set; }
public BaseColor foreColor { get; set; }
}
}
To Use:
Document pdfDoc = new Document(PageSize.LEGAL.Rotate(), 10, 10, 25, 25);
System.IO.MemoryStream mStream = new System.IO.MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, mStream);
MyCode.HeaderFooter headers = new MyCode.HeaderFooter();
writer.PageEvent = headers;
..
..
Build the string array for the headers
...
DefineFont passFont = new DefineFont();
// always set this to the largest font used
headers.fontPointSize = 8;
// set up the highlight or bold font
passFont.fontFamily = "Helvetica";
passFont.fontSize = 8;
passFont.isBold = true;
passFont.isItalic = false;
passFont.isUnderlined = false;
passFont.foreColor = BaseColor.BLACK;
headers.boldFont = passFont;
// now setup the normal text font
passFont.fontSize = 7;
passFont.isBold = false;
headers.normalFont = passFont;
headers.leftMargin = 10;
headers.bottomMargin = 25;
headers.rightMargin = 10;
headers.topMargin = 25;
headers.PageNumberSettings = HeaderFooter.PageNumbers.FooterPlacement;
headers.footerLine = "Page";
headers.headerLines = parmLines.ToArray();
pdfDoc.SetMargins(headers.leftMargin, headers.rightMargin, headers.topMargin + headers.headerheight, headers.bottomMargin + headers.footerHeight);
pdfDoc.Open();
// the new page is necessary due to a bug in in the current version of itextsharp
pdfDoc.NewPage();
... now your headers and footer will be handled automatically
This link will help you out completely(the Shortest and Most Elegant way):
Header Footer with PageEvent
PdfPTable tbheader = new PdfPTable(3);
tbheader.TotalWidth = document.PageSize.Width - document.LeftMargin - document.RightMargin;
tbheader.DefaultCell.Border = 0;
tbheader.AddCell(new Paragraph());
tbheader.AddCell(new Paragraph());
var _cell2 = new PdfPCell(new Paragraph("This is my header", arial_italic));
_cell2.HorizontalAlignment = Element.ALIGN_RIGHT;
_cell2.Border = 0;
tbheader.AddCell(_cell2);
float[] widths = new float[] { 20f, 20f, 60f };
tbheader.SetWidths(widths);
tbheader.WriteSelectedRows(0, -1, document.LeftMargin, writer.PageSize.GetTop(document.TopMargin), writer.DirectContent);
PdfPTable tbfooter = new PdfPTable(3);
tbfooter.TotalWidth = document.PageSize.Width - document.LeftMargin - document.RightMargin;
tbfooter.DefaultCell.Border = 0;
tbfooter.AddCell(new Paragraph());
tbfooter.AddCell(new Paragraph());
var _cell2 = new PdfPCell(new Paragraph("This is my footer", arial_italic));
_cell2.HorizontalAlignment = Element.ALIGN_RIGHT;
_cell2.Border = 0;
tbfooter.AddCell(_cell2);
tbfooter.AddCell(new Paragraph());
tbfooter.AddCell(new Paragraph());
var _celly = new PdfPCell(new Paragraph(writer.PageNumber.ToString()));//For page no.
_celly.HorizontalAlignment = Element.ALIGN_RIGHT;
_celly.Border = 0;
tbfooter.AddCell(_celly);
float[] widths1 = new float[] { 20f, 20f, 60f };
tbfooter.SetWidths(widths1);
tbfooter.WriteSelectedRows(0, -1, document.LeftMargin, writer.PageSize.GetBottom(document.BottomMargin), writer.DirectContent);
pdfDoc.Open();
Paragraph para = new Paragraph("Hello World", new Font(Font.FontFamily.HELVETICA, 22));
para.Alignment = Element.ALIGN_CENTER;
pdfDoc.Add(para);
pdfDoc.Add(new Paragraph("\r\n"));
htmlparser.Parse(sr);
pdfDoc.Close();

Categories

Resources