iTextSharp Duplicating Acrofields - c#

I have an acroform on page 1 of my document. I am creating a blank second page and i would like to show one of the fields on this page as well. If the user changes the value of this field on either of the pages, i want them both to show the new value. I found a few posts that are showing this type of solution but it doesn't work as expected:
PdfFormField fNotes = PdfFormField.CreateTextField(writer, false, false, 500);
string fieldNotes = "tfNotes";
fNotes.FieldName = fieldNotes;
PdfFormField widgetNotes = PdfFormField.CreateEmpty(writer);
PdfPCell notesCell = new PdfPCell(new Paragraph("test", helv8))
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(0, 0, 100, 100), fieldNotes);
writer.AddAnnotation(fNotes);
writer.AddAnnotation(widgetNotes);
In this example, the field on page 1 is named tfNotes. If i understand correctly, i need to create a second widget reference to the acrofield. I think the above code would be for a field that doesn't already exist, in my case it does. Is there an easier way to grab a field by name on page 1 and create a duplicate reference to it on page 2?
Thank you for your time!
EDIT:
This works as expected when i take the table out of the equation, but once i try to put the duplicated field into the PdfPCell it shows up on the page at 0,0 with a width and height of 0. For some reason the rectangle of the cell is returning as 0,0,0,0.
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize);
writer.AddAnnotation(tField.GetTextField());
I think all i need to do now is find the correct rectangle coords for the cell.

So the part i was missing was a CellEvent, which i don't completely understand why, but here is the final working snippet for anyone who needs it:
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize); //Needed since this page is rotated 90 from the first page
iTextSharp.text.pdf.events.FieldPositioningEvents events = new iTextSharp.text.pdf.events.FieldPositioningEvents(writer, tField.GetTextField());
writer.AddAnnotation(tField.GetTextField());
notesCell.CellEvent = events; //This somehow ignores the original rectangle (0,0,0,0) in the TextField definition above and changes it to the cell's rectangle

Related

Set text width component via script

I am instantiating the leader board on the image (https://imgur.com/a/I0aVSaR), the problem is, I can't align properly the numbers on the center row.
I think that if I set the width of the numbers of the right row, the center row will be aligned. Right now the elements on the right row have different widths.
My problem now is how to set the width via script, I already tried rectransform.deltaSize, SetSizeWithCurrentAnchors and other similar things with no luck.
I've also tried to set a preferred width on the inspector on Layout Element but is ignored (https://imgur.com/a/O3hDeGN).
This is how the elements are created:
for (int i = 0; i < leaderboardEntries.Count; i++)
{
Transform newEntry = Instantiate(entryPrefab);
newEntry.SetParent(leaderboardEntriesPanel);
Text entryName = newEntry.GetChild(0).GetComponent<Text>();
Text entryScore = newEntry.GetChild(1).GetComponent<Text>();
Text entryRank = newEntry.GetChild(2).GetComponent<Text>();
entryName.text = leaderboardEntries[i].getName();
entryScore.text = leaderboardEntries[i].getScore().ToString();
entryRank.text = (i+1).ToString();
entryName.alignment = TextAnchor.UpperLeft;
entryScore.alignment = TextAnchor.UpperRight;
entryRank.alignment = TextAnchor.UpperRight;
}
The center row is the score, the left row the Name and the right row the rank.
Thanks!
if you want to change the width and height of a RectTransform you can try this:
rectTransform.sizeDelta = new Vector2( width, height);
but fixing their alignment need something else, first of all, all alignments should be same, UpperLeft or MiddleLeft for example.
then set anchor point of all your entries to the same value also.
then something like this should work properly:
// in this example I considered all anchor points are middle left and all
// alignments are middle left too
float width = leaderboardEntriesPanel.GetComponent<RectTransform>().rect.width;
for (int i = 0; i < leaderboardEntries.Count; i++)
{
Transform newEntry = Instantiate(entryPrefab);
newEntry.SetParent(leaderboardEntriesPanel);
Text entryName = newEntry.GetChild(0).GetComponent<Text>();
Text entryScore = newEntry.GetChild(1).GetComponent<Text>();
Text entryRank = newEntry.GetChild(2).GetComponent<Text>();
entryName.text = leaderboardEntries[i].getName();
entryScore.text = leaderboardEntries[i].getScore().ToString();
entryRank.text = (i+1).ToString();
entryName.GetComponent<RectTransform>().anchoredPosition = new Vector2(width / 15, entryName.GetComponent<RectTransform>().anchoredPosition.y);
entryScore.GetComponent<RectTransform>().anchoredPosition = new Vector2(width / 2, entryScore.GetComponent<RectTransform>().anchoredPosition.y);
entryRank.GetComponent<RectTransform>().anchoredPosition = new Vector2(width * 4 / 5, entryRank.GetComponent<RectTransform>().anchoredPosition.y);
}

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!

Unable to vertically align text in table cell with itextsharp

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);

Re-using a font object in iTextSharp

I am having trouble trying to define an iTextSharp Font object that I can re-use throughout a class.
My first attempt was to use the FontFactory.GetFont method in 2 private methods that create PdfPCell objects:
FontFactory.GetFont("helvetica", 8)
The problem with this is that only one of the methods prints the font correctly, the other method would not print the inner text of the cell.
Next I tried to create a static field in the class representing the font:
private static Font _standardCellFont;
public static PdfPCell CreateTableHeaderCell(string cellText, int colspan = 1)
{
var innerCellText = new Phrase(cellText, PdfSupport._standardCellFont);
innerCellText.Font.Color = BaseColor.WHITE;
return new PdfPCell(innerCellText)
{
Colspan = colspan,
PaddingLeft = 5,
PaddingRight = 5,
FixedHeight = 10,
BackgroundColor = BaseColor.BLACK,
VerticalAlignment = Element.ALIGN_CENTER
};
}
public static PdfPCell CreateTableCell(string cellText, int colspan = 1, int rowspan = 1, bool bold = false, float minHeight = 0)
{
var cellInnerText =
bold ?
new Phrase(cellText, FontFactory.GetFont("helvetica", 8, Font.BOLD)) :
new Phrase(cellText, PdfSupport._standardCellFont);
return new PdfPCell(cellInnerText)
{
Border = Rectangle.NO_BORDER,
Colspan = colspan,
Rowspan = rowspan,
PaddingTop = 1,
PaddingBottom = 1,
PaddingLeft = 5,
PaddingRight = 5,
MinimumHeight = minHeight,
VerticalAlignment = Element.ALIGN_CENTER
};
}
The result of this is that neither of the methods print the cell text.
I don't think I really understand what is happening when I create a font object, my goal is to be able to define a few common fonts and basic properties (Size, Bold) that I can then re-use throughout my class, however from my usage it appears that a font object cannot be persisted in this way.
How strange. They can, and SHOULD, be shared. Are the characters you're trying to draw all in WInAnsiEncoding (mostly the first 256 characters of Unicode).
Ah! I suspect you may be running into an ALIGNMENT issue.
Valid settings for VerticalAlignment:
Element.ALIGN_TOP
Element.ALIGN_MIDDLE
Element.ALIGN_BOTTOM
Element.ALIGN_CENTER is strictly for horizontal alignment. I'm not sure that would make your text vanish, but it's certainly worth looking into.
PS: I believe you can even reuse Font and BaseFont objects across documents, though I haven't tried it myself.

Categories

Resources