Unable to vertically align text in table cell with itextsharp - c#

I can not figure out how to vertically align text in table cell. horizontal alignment is ok. I use itextsharp to generate pdf. Alignment should be applied to cells in table kitosKalbosTable. Any help would be appreciated. here's my code:
var table = new PdfPTable(new float[]
{
36, 1, 63
});
table.WidthPercentage = 100.0f;
table.HorizontalAlignment = Element.ALIGN_LEFT;
table.DefaultCell.Border = Rectangle.NO_BORDER;
table.SplitRows = false;
.........
PdfPTable kitosKalbosTable = new PdfPTable(new float[] {10, 30});
kitosKalbosTable.TotalWidth = 40f;
kitosKalbosTable.SplitRows = false;
kitosKalbosTable.AddCell("Kalba", FontType.SmallTimes, vAligment: Element.ALIGN_MIDDLE, hAligment: Element.ALIGN_CENTER);
..........
table.AddCell(kitosKalbosTable);
//method in other file
public static PdfPCell CreateCell(
string text,
FontType? fontType = FontType.RegularTimes,
int? rotation = null,
int? colspan = null,
int? rowspan = null,
int? hAligment = null,
int? vAligment = null,
int? height = null,
int? border = null,
int[] disableBorders = null,
int? paddinLeft = null,
int? paddingRight = null,
bool? splitLate = null)
{
var cell = new PdfPCell();
............
if (vAligment.HasValue)
{
cell.VerticalAlignment = vAligment.Value;
}
return cell;
}

You have a complex example that appears to be using nested tables and extension methods. As Alexis pointed out, the VerticalAlignment is the correct property to use. Below is a full working example of this. I recommend getting rid of your extension method for now and just starting with this example.
//Our test file to output
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Standard PDF setup, nothing special here
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Create our outer table with two columns
var outerTable = new PdfPTable(2);
//Create our inner table with just a single column
var innerTable = new PdfPTable(1);
//Add a middle-align cell to the new table
var innerTableCell = new PdfPCell(new Phrase("Inner"));
innerTableCell.VerticalAlignment = Element.ALIGN_MIDDLE;
innerTable.AddCell(innerTableCell);
//Add the inner table to the outer table
outerTable.AddCell(innerTable);
//Create and add a vertically longer second cell to the outer table
var outerTableCell = new PdfPCell(new Phrase("Hello\nWorld\nHello\nWorld"));
outerTable.AddCell(outerTableCell);
//Add the table to the document
doc.Add(outerTable);
doc.Close();
}
}
}
This code produces this PDF:

Use
cell.VerticalAlignment = Element.ALIGN_MIDDLE; // or ALIGN_TOP or ALIGN_BOTTOM
Also, you can set a default vertical alignment for all cells by setting
kitosKalbosTable.DefaultCell.VerticalAlignment

It seems Element.ALIGN_MIDDLE only works, when the cell height is large i.r.t the text height.
In a PDF, margins for text in cells are large by default, see iText developers
You could append a \n and a space to your string to solve this, but the cell height will become much larger.
For normal text, one way to lift text in a chunk a few pixels is:
myChunk.SetTextRise(value);
Only drawback: when the text is underlined (like a link) it only raises the text ! not the underline..
The following seems to work for underlined text also,
myCell.PaddingBottom = value;
The idea was to put a link in a table cell.. blue font, underlined, vertical centering.
My code now:
iTextSharp.text.Font linksFont =
FontFactory.GetFont(FontFactory.HELVETICA,
10, Font.UNDERLINE, BaseColor.BLUE);
PdfPTable myTable = new PdfPTable(1);
Chunk pt = new Chunk("Go Google Dutch", linksFont);
pt.SetAnchor(new Uri("https://www.google.nl"));
Phrase ph1 = new Phrase(pt);
PdfPCell cellP = new PdfPCell();
cellP.PaddingBottom = linksFont.CalculatedSize/2;
cellP.AddElement(ph1);
myTable.AddCell(cellP);

Related

iTextSharp PdfPCell align image to bottom of cell

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.

How do I set the background color of a nested cell when using iTextSharp?

I have two tables. The outer table is a single column/cell wrapper that I use to paint a gradient background. I then add a nested/child table which is a single row and has three cells.
// set up wrapper table
var wrapperTable = new PdfPTable(1);
wrapperTable .WidthPercentage = 100;
// set up wrapper cell
var wrapperCell = new PdfPCell();
wrapperCell.CellEvent = new GradientBackgroundEvent(writer); // set gradient background
wrapperCell.Border = PdfPCell.NO_BORDER;
// setup nested table
var nestedTable = new PdfPTable(3);
nestedTable.WidthPercentage = 100;
nestedTable.SetWidths(new float[] { 15f, 70f, 15f });
var col1 = new PdfPCell(new Phrase(myText1, font));
col1.VerticalAlignment = Element.ALIGN_TOP;
col1.HorizontalAlignment = Element.ALIGN_CENTER;
col1.Border = PdfPCell.NO_BORDER;
nestedTable.AddCell(col1);
// this is the cell that I'm interested in - borders work, but no bgcolor
var col2 = new PdfPCell(new Phrase(myText2, font));
col2.VerticalAlignment = Element.ALIGN_TOP;
col2.HorizontalAlignment = Element.ALIGN_LEFT;
col2.BackgroundColor = BaseColor.WHITE;
col2.BorderColor = new BaseColor(204, 204, 204);
col2.BorderWidth = 0.2f;
nestedTable.AddCell(col2);
var col3 = new PdfPCell(new Phrase(myText3, font));
col3.VerticalAlignment = Element.ALIGN_TOP;
col3.HorizontalAlignment = Element.ALIGN_CENTER;
col3.Border = PdfPCell.NO_BORDER;
nestedTable.AddCell(col3);
// add nested table to the wrapper table
wrapperCell.AddElement(nestedTable);
I can set the borders for these cells and they paint correctly. However nothing I've tried (short of removing the gradient background) will allow me to see the background color that I've set on a cell in the nested table.
Here is my code to do the gradient fill.
public class GradientBackgroundEvent : IPdfPCellEvent
{
private PdfWriter w;
public GradientBackgroundEvent(PdfWriter w)
{
this.w = w;
}
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
{
var c1 = new BaseColor(238, 238, 238);
var c2 = new BaseColor(221, 221, 221);
PdfShading shading = PdfShading.SimpleAxial(w, position.Left, position.Top, position.Left, position.Bottom, c1, c2);
PdfShadingPattern pattern = new PdfShadingPattern(shading);
ShadingColor color = new ShadingColor(pattern);
PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS];
position.BackgroundColor = color;
// Fill the rectangle
cb.Rectangle(position);
}
}
I've tried moving code around and changing the order in which the tables/cells are added but that makes no difference because the PDF is drawn at the end (not as it is constructed).
Judging by my debug - it looks to me like the gradient fill is being painted after the background color for the cell is set and effectively overwriting it.
Does anyone have any ideas about how this can be done? Maybe I shouldn't be using a table to achieve this?
I've seen some other posts that suggest using a form field is the way to go. I'd like to avoid this if possible but if it's the only way...
Your background color is getting drawn, unfortunately it is being drawn "under" the gradient background which is why you can't see it. As long as you're only nesting these two tables the simplest solution is probably to just draw your gradient on PdfPTable.BASECANVAS instead of PdfPTable.BACKGROUNDCANVAS.

iTextSharp - dynamic content with a footer, using padding

I am attempting to create documents that are highly-variable in length, and make them something that can be table-driven. I am trying to use iTextSharp tables exclusively to create the documents, including footer verbiage. In the code below Iā€™m trying to pad the very last cell to the exact amount equal to the remaining space, so that my footer will be placed exactly at the bottom of the document, tight against the bottom margin. This works fine when I try to use document margins of 1, 2, or 3 inches, but when I use 5 for example, my footer begins to wrap. I think this may simply be a case of bad math. Does anyone have any suggestions to correct this (outside of using Page Events)?
(*Note: there are 2 helper methods used in creating tables and measuring the height of a paragraph, also included in addition to the main code from a button click)
(*Note: each table has SplitLate set to false, to make the content flow from page to page evenly); all tables have a specific width, and the width is locked
//declare path for the PDF file to be created
string strpath = #"C:\CROauto\Junk\MSE.pdf";
//instantiate a new PDF document
//(regular portrait format, with half-inch margins all around)
var doc = new Document(PageSize.LETTER,
iTextSharp.text.Utilities.InchesToPoints(1f),
iTextSharp.text.Utilities.InchesToPoints(1f),
iTextSharp.text.Utilities.InchesToPoints(5f),
iTextSharp.text.Utilities.InchesToPoints(.5f));
//create a PDF table
//(2 column, with no border)
PdfPTable mas_tbl = clsPDF.CreateTable(2, false, cell_padding_bottom: 0f, total_width: doc.PageSize.Width - doc.LeftMargin - doc.RightMargin);
//get base font types
BaseFont font_tb = FontFactory.GetFont(FontFactory.TIMES_BOLD).BaseFont;
BaseFont font_t = FontFactory.GetFont(FontFactory.TIMES).BaseFont;
//create regular Font objects, with varying sizes
iTextSharp.text.Font f10 = new iTextSharp.text.Font(font_t, 10);
iTextSharp.text.Font f8 = new iTextSharp.text.Font(font_t, 8);
//create regular Font objects, bold, with varying sizes
iTextSharp.text.Font fb10 = new iTextSharp.text.Font(font_tb, 10);
iTextSharp.text.Font fb8 = new iTextSharp.text.Font(font_tb, 8);
//get image
iTextSharp.text.Image da_img = iTextSharp.text.Image.GetInstance(#"C:\CROauto\Junk\img.gif");
//scale the image to a good size
da_img.ScaleAbsolute(iTextSharp.text.Utilities.InchesToPoints(.75f),
iTextSharp.text.Utilities.InchesToPoints(.75f));
//create new PDF cell to hold image
PdfPCell icell = new PdfPCell();
icell.PaddingBottom = 0f;
//make sure the "image" cell has no border
icell.Border = iTextSharp.text.Rectangle.NO_BORDER;
//add the image to the PDF cell
icell.AddElement(da_img);
//add the image cell to the table
mas_tbl.AddCell(icell);
//work with the return address
PdfPCell ra = new PdfPCell();
ra.Border = iTextSharp.text.Rectangle.NO_BORDER;
ra.PaddingBottom = 5f;
PdfPTable tblra = clsPDF.CreateTable(1, false);
tblra.HorizontalAlignment = Element.ALIGN_RIGHT;
Chunk c = new Chunk("Help Me Please", fb8);
string rtnadd = "\r\n123 iTextSharp Rd\r\nHelpMe, ST 12345\r\n\r\nstackoverflow.com";
Phrase pra = new Phrase(rtnadd, f8);
Paragraph p = new Paragraph();
p.SetLeading(1f, 1.1f);
p.Add(c);
p.Add(pra);
tblra.TotalWidth = clsPDF.GetLongestWidth(p) + ra.PaddingLeft + ra.PaddingRight + 2;
ra.AddElement(p);
tblra.AddCell(ra);
PdfPCell dummy = new PdfPCell();
dummy.PaddingBottom = 0f;
dummy.Border = iTextSharp.text.Rectangle.NO_BORDER;
dummy.AddElement(tblra);
mas_tbl.AddCell(dummy);
//create "content" table
PdfPTable t2 = clsPDF.CreateTable(1, false, Element.ALIGN_JUSTIFIED, cell_padding_bottom: 0f);
//create FileStream for the file
using (FileStream fs = new FileStream(strpath, FileMode.Create))
{
//get an instance of a PdfWriter, attached to the FileStream
PdfWriter.GetInstance(doc, fs);
//open the document
doc.Open();
string tmp = "";
for (int i = 0; i < 80; i++)
{
tmp += "The brown fox jumped over the lazy dog a whole bunch of times." + i.ToString();
}
Phrase p2 = new Phrase(tmp, f10);
t2.AddCell(p2);
p2 = new Phrase("Another paragraph", f10);
t2.AddCell(p2);
tmp = "";
PdfPTable t3 = clsPDF.CreateTable(1, false, cell_padding_bottom: 0f);
for (int i = 0; i < 150; i++)
{
tmp += "The lazy dog didn't like that very much." + i.ToString();
}
t3.AddCell(new Phrase(tmp, f10));
t2.AddCell(t3);
t2.AddCell(new Phrase("I SURE HOPE THIS WORKED", f10));
PdfPCell c2 = new PdfPCell();
c2.PaddingBottom = 0f;
c2.Border = iTextSharp.text.Rectangle.NO_BORDER;
c2.Colspan = mas_tbl.NumberOfColumns;
c2.AddElement(t2);
mas_tbl.AddCell(c2);
//work with adding a footer
//FOOTER MSE: ADD ENOUGH PADDING TO PUSH THE FOOTER TO THE BOTTOM OF THE PAGE
Paragraph fp = new Paragraph(new Phrase("Line 1 of footer\r\nLine 2 of footer\r\nhere's more of my footer text:\r\nthis project was SOOOO much fun\r\nand stuff", fb8));
//get the height of the footer
float footer_height = clsPDF.GetTotalHeightOfParagraph(fp);
Console.WriteLine("Footer height {0}", footer_height.ToString());
//get the total amount of "writeable" space per page
//(taking top and bottom margins into consideration)
float avail = doc.PageSize.Height - (doc.TopMargin + doc.BottomMargin);
//declare a variable to assist in calculating
//the total amount of "writeable" room remaining
//on the last page;
//start with with the current height of the master table
//(will do math below to calculate just what it's using
// on the last page)
float mas_tbl_last_page_height = mas_tbl.TotalHeight;
//the purpose of this loop is to start determining
//how much writeable space is left on the last page;
//this loop will subtract the "available" value from
//the total height of the master table until what's
//left is the amount of space the master table is
//using on the last page of the document only
while (mas_tbl_last_page_height > avail)
{
mas_tbl_last_page_height -= avail;
}
//to truly calculate the amount of writeable space
//remaining, subtract the amount of space that the
//master table is utilizing on the last page of
//the document, from the total amount of writeable
//space per page
float room_remaining = avail - mas_tbl_last_page_height;
//declare variable for the padding amount
//that will be used above the footer
float pad_amt = 0f;
if (room_remaining > (footer_height * 2))
{
//pad to push down
pad_amt = room_remaining - (footer_height * 2);
}
else
{
//don't use a pad
//(just let the table wrap normally)
pad_amt = 0f;
}
//declare the footer cell, and set all of it's values
PdfPCell ftcell = new PdfPCell();
ftcell.HorizontalAlignment = Element.ALIGN_JUSTIFIED;
//(use column span that is equal to the number of
// columns in the master table)
ftcell.Colspan = mas_tbl.NumberOfColumns;
ftcell.Border = iTextSharp.text.Rectangle.NO_BORDER;
ftcell.PaddingTop = pad_amt;
ftcell.PaddingBottom = 0f;
ftcell.AddElement(fp);
//add the footer cell to the master table
mas_tbl.AddCell(ftcell);
//add the master table to the document, which should contain everything
doc.Add(mas_tbl);
//close the document
doc.Close();
//HELPER METHODS
internal static PdfPTable CreateTable(int column_count,
bool include_border,
int h_align = Element.ALIGN_LEFT,
int v_align = Element.ALIGN_TOP,
float leading_multiplier = 1.1f,
float total_width = 468f,
float cell_padding_bottom = 5f,
float cell_padding_top = 0)
{
////////////////////////////////////////////////////////////////////////////////////
PdfPTable t = new PdfPTable(column_count);
//this line will keep the inner tables,
//from splitting off onto a 2nd page
//(making them only do it on wrapping)
//*NOTE: this needs to be tested thoroughly
// to make sure that rows aren't dropped!!!
t.SplitLate = false;
//used if you're adding paragraphs directly to table cells,
//instead of adding new PdfPCell objects
if (include_border == false)
{
t.DefaultCell.Border = Rectangle.NO_BORDER;
}
t.DefaultCell.PaddingLeft = 0f;
t.DefaultCell.PaddingRight = 0f;
t.DefaultCell.PaddingTop = cell_padding_top;
t.DefaultCell.PaddingBottom = cell_padding_bottom;
t.DefaultCell.HorizontalAlignment = h_align;
t.DefaultCell.VerticalAlignment = h_align;
t.TotalWidth = total_width;
t.LockedWidth = true;
t.DefaultCell.SetLeading(0, leading_multiplier);
return t;
}
internal static float GetLongestWidth(Paragraph p)
{
List<float> f = new List<float>();
foreach (Chunk c in p.Chunks)
{
string[] strarray = c.Content.Split(new string[] { "\r\n" }, System.StringSplitOptions.None);
for (int i = 0; i < strarray.Length; i++)
{
Chunk tc = new Chunk(strarray[i], c.Font);
Console.WriteLine(tc.Content + ", width: {0}", tc.GetWidthPoint().ToString());
f.Add(tc.GetWidthPoint());
}
}
return f.Max();
}
internal static float GetTotalHeightOfParagraph(Paragraph p)
{
PdfPTable t = clsPDF.CreateTable(1, false, cell_padding_bottom: 0f);
t.DefaultCell.PaddingBottom = 0f;
t.DefaultCell.PaddingTop = 0f;
t.AddCell(p);
return t.TotalHeight;
}
Solved it by using absolute positioning. I calculate the position that the footer should be in, by adding the footer height to the value of the bottom margin. To alleviate concerns about overwriting existing content, I calculate the amount of available space remaining on the last page; if it's not enough for my footer, I add a new page and post my content at the beginning of the next page.
byte[] content;
using (MemoryStream output = new MemoryStream())
{
PdfReader pdf_rdr = new PdfReader(strpath);
PdfStamper stamper = new PdfStamper(pdf_rdr, output);
PdfContentByte pcb = stamper.GetOverContent(pdf_rdr.NumberOfPages);
PdfPTable ftbl = clsPDF.CreateTable(1, false, cell_padding_bottom: 0f);
Paragraph fp = new Paragraph(new Phrase("Line 1 of footer\r\nLine 2 of footer\r\nhere's more of my footer text:\r\nthis project was SOOOO much fun\r\nand stuff", fb8));
//get the height of the footer
float footer_height = clsPDF.GetTotalHeightOfParagraph(fp);
Console.WriteLine("Footer height {0}", footer_height.ToString());
//get the total amount of "writeable" space per page
//(taking top and bottom margins into consideration)
float avail = doc.PageSize.Height - (doc.TopMargin + doc.BottomMargin);
//declare a variable to assist in calculating
//the total amount of "writeable" room remaining
//on the last page;
//start with with the current height of the master table
//(will do math below to calculate just what it's using
// on the last page)
float mas_tbl_last_page_height = mas_tbl.TotalHeight;
mas_tbl_last_page_height = mas_tbl_last_page_height % avail;
avail = avail - mas_tbl_last_page_height;
Console.WriteLine(clsPDF.GetTotalHeightOfParagraph(fp).ToString());
//float ft_top = avail - mas_tbl_last_page_height - clsPDF.GetTotalHeightOfParagraph(fp) - doc.BottomMargin;
float ft_top = doc.BottomMargin + clsPDF.GetTotalHeightOfParagraph(fp);
ftbl.AddCell(fp);
if (avail < clsPDF.GetTotalHeightOfParagraph(fp))
{
stamper.InsertPage(pdf_rdr.NumberOfPages + 1, pdf_rdr.GetPageSize(1));
pcb = stamper.GetOverContent(pdf_rdr.NumberOfPages);
ft_top = doc.PageSize.Height - doc.TopMargin;
}
ftbl.WriteSelectedRows(0, -1, doc.LeftMargin, ft_top, pcb);
// Set the flattening flag to true, as the editing is done
stamper.FormFlattening = true;
// close the pdf stamper
stamper.Close();
//close the PDF reader
pdf_rdr.Close();
content = output.ToArray();
}
//write the content to a PDF file
using (FileStream fs = File.Create(strpath))
{
fs.Write(content, 0, (int)content.Length);
fs.Flush();
}

I can't insert something as "Page X of Y" into my PDF footer using iTextSharp

I am pretty new in iTextSharp and I have the following situation: I am creating a PDF that contains an header and a footer (for the header and footer creation I am using a class that extends PdfPageEventHelper and I have override the OnStartPage() and the OnEndPage() method, it work fine).
Now my problem is that I have to insert as Page X of Y into my footer. Where X**is the **current page number and Y is the total page number. The value of Y is not fixed (because the length of my PDF is not known in advance because it depends depends on the length of the content and can differ from PDF to PDF). How can I handle this situation? (inserting the correct Y value in each footer?)
Searching online I have find this tutorial (that is for Java iText but maybe it is not so different from iTextSharp version): http://itextpdf.com/examples/iia.php?id=104
In this example it create a PDF and its header contains something like Page X of Y.
I am trying to understand this example (and translate it for iTextSharp) but I have some doubts about how it work (and if it is a real solution for my problem).
From what I can understand it perform the following operations:
Into the class that extends PdfPageEventHelper it is declared a PdfTemplate object
PdfTemplate total;
I think that maybe it handles the total pages number that are into my PDF document, but reading the official documentation I have not many information about what exactly do this class: http://api.itextpdf.com/itext/com/itextpdf/text/pdf/PdfTemplate.html
I am trying to do something similar into my class that extends PdfPageEventHelper but I can't do it.
This is my not working code:
public class PdfHeaderFooter : PdfPageEventHelper
{
// The template with the total number of pages:
PdfTemplate total;
private static int numPagina = 1;
public Image CellImage;
private string folderImages;
private string _sourceId;
public PdfHeaderFooter(string _folderImages, string sourceId)
{
folderImages = _folderImages;
_sourceId = sourceId;
}
/* Creates the PdfTemplate that will hold the total number of pages.
* Write on top of document
* */
public override void OnOpenDocument(PdfWriter writer, Document document)
{
base.OnOpenDocument(writer, document);
// (Nobili) Page Number:
total = writer.DirectContent.CreateTemplate(30, 16);
//PdfPTable tabFot = new PdfPTable(new float[] { 1F });
PdfPTable tabFot = new PdfPTable(2);
tabFot.WidthPercentage = 98;
tabFot.SpacingAfter = 10F;
PdfPCell cell;
//tabFot.TotalWidth = 300F;
cell = new PdfPCell(new Phrase("Header"));
tabFot.AddCell(cell);
tabFot.WriteSelectedRows(0, -1, 150, document.Top, writer.DirectContent);
}
// write on end of each page
public override void OnEndPage(PdfWriter writer, Document document)
{
base.OnEndPage(writer, document);
int pageN = writer.PageNumber;
String text = "Page " + pageN + " of ";
//PdfPTable tabFoot = new PdfPTable(new float[] { 1F });
PdfPTable tabFoot = new PdfPTable(3);
tabFoot.TotalWidth = document.Right - document.Left;
tabFoot.DefaultCell.Border = PdfPCell.NO_BORDER;
tabFoot.DefaultCell.CellEvent = new RoundedBorder();
PdfPTable innerTable = new PdfPTable(2);
innerTable.SetWidths(new int[] { 247, 246 });
innerTable.TotalWidth = document.Right - document.Left;
innerTable.DefaultCell.Border = PdfPCell.NO_BORDER;
PdfPCell innerCellLeft = new PdfPCell(new Phrase("Early Warning - Bollettino")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_LEFT };
//PdfPCell innerCellRight = new PdfPCell(new Phrase("Pag. " + numPagina + "/5")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
PdfPCell innerCellCenter = new PdfPCell(new Phrase(text)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
PdfPCell innerCellRight = new PdfPCell(Image.GetInstance(total)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
innerTable.AddCell(innerCellLeft);
innerTable.AddCell(innerCellRight);
tabFoot.AddCell(innerTable);
tabFoot.WriteSelectedRows(0, -1, document.Left, document.Bottom, writer.DirectContent);
numPagina++;
}
// write on start of each page
public override void OnStartPage(PdfWriter writer, Document document)
{
base.OnStartPage(writer, document);
PdfPTable tabHead = new PdfPTable(3);
tabHead.SetWidths(new int[] { 165, 205, 125 });
//tabHead.TotalWidth = 460F;
tabHead.TotalWidth = document.Right - document.Left; // TotalWidth = 495
tabHead.WidthPercentage = 98;
PdfPCell cell1 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "logoEarlyWarning.png"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell1);
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 1:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15, });
tabHead.AddCell(new PdfPCell(new Phrase("CELL 2:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
if(_sourceId == "NVD")
{
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png");
logo.ScalePercent(48f);
//PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"), true) { Border = PdfPCell.BOTTOM_BORDER, PaddingBottom = 25 };
PdfPCell cell3 = new PdfPCell(logo) { Border = PdfPCell.BOTTOM_BORDER, PaddingLeft = 50 };
tabHead.AddCell(cell3);
}
else if(_sourceId == "DeepSight")
{
PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "DSLogo.jpg"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell3);
}
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 3:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
}
//write on close of document
public override void OnCloseDocument(PdfWriter writer, Document document)
{
base.OnCloseDocument(writer, document);
}
}
}
I want put in the footer something like the Page X of Y as shown in the tutorial
I tryied to do the following thing:
1) I declared the PdfTemplate total; object as field of my class and I initialize it into my OnOpenDocument() method
total = writer.DirectContent.CreateTemplate(30, 16);
2) Into my OnEndPage() method I put:
String text = "Page " + pageN + " of ";
and I created the following table to show the Page X of Y
PdfPCell innerCellLeft = new PdfPCell(new Phrase("Early Warning - Bollettino")) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_LEFT };
PdfPCell innerCellCenter = new PdfPCell(new Phrase(text)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
PdfPCell innerCellRight = new PdfPCell(Image.GetInstance(total)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 20, HorizontalAlignment = Element.ALIGN_RIGHT };
But it don't work and throw me an exception
What could be the problem in my code?
You are copy/pasting code without reading the documentation that comes with the examples. Moreover you are completely ignoring the C# version of the examples from my book. I have paid good money to a C# developer to port these examples. It feels as if that money was thrown away. You can find the example you tried to port yourself here: http://tinyurl.com/itextsharpIIA2C05
Error #1: you are adding content in the OnStartPage() method. That is forbidden! This is documented on many places. See for instance this answer copied from page 150 of the official documentation:
FAQ Why is it not advised to add content in the onStartPage() method? You'll remember from section 5.2.4 that iText ignores newPage() calls when the current page is empty. This method is executed ā€” or ignored ā€” when you call it explicitly from your code, but it's also invoked implicitly from within iText on multiple occasions. It's important that it's ignored for empty pages; otherwise you'd end up with plenty of unwanted new pages that are unintentionally left blank. If you add content in an onStartPage() method, there's always a risk of having unwanted pages. Consider it more safe to reserve the onEndPage() method for adding content.
Error #2: you are adding content in the OnOpenDocument() method. Why would that make sense?
Error #3: you create the total object because you want to create a place holder that can be added to each page. Once you know the total number of pages, you want to fill out that number on that place holder. However: I don't see you doing this anywhere. The appropriate place to do this, is obviously in the OnCloseDocument() even. This event is triggered right before the document is closed, so at that moment, the total number of pages is known. This is, as Sherlock Holmes would say, elementary, my dear!

How to make the table non breaking using iTextSharp

I am having a table
PdfPTable tblSummary = new PdfPTable(1);
And it does have 2 tables nested within it. How can I make the tblSummary to appear as a whole (the rows must not break to another page) or entire table be shifted to another page if it doesn't fits in the current page.
I have tried SplitLate and SplitRows
And my code is like this
PdfPTable tblSummary = new PdfPTable(1);
PdfPCell csummarycell = new PdfPCell();
PdfPTable tblSummaryFirst = new PdfPTable(3);
.
.
csummarycell.AddElement(tblSummaryFirst);
.
.
tblSummary.AddCell(csummarycell);
tblSummary.SplitLate = true;
tblSummary.SplitRows = false;
like this I add up one more table(s) to the tblSummary while the resulting table height is always less than that of pagesize so there is certainty that the table's content won't be more than the page height.
Any suggestions would be really helping.
Have you tried this:
tblSummary.KeepTogether = true;
PdfPTable tabla = new PdfPTable(2);
float[] anchosTablaTituloDescripcion = new float[] { 4f, 4f };
tabla.SetWidths(anchosTablaTituloDescripcion);
tabla.WidthPercentage = 100;
tabla.KeepTogether = true;

Categories

Resources