我正在尝试创建长度变化很大的文档,并使它们成为可以由表驱动的东西。我试图专门使用iTextSharp表来创建文档,包括页脚的措辞。在下面的代码中,我试图将最后一个单元格填充到与剩余空间相等的精确数量,这样我的页脚就会正好放在文档的底部,紧靠底部边距。当我尝试使用1,2或3英寸的文档边距时这很好用,但是当我使用5例如,我的页脚开始换行。我认为这可能只是一个糟糕的数学案例。有没有人有任何建议来纠正这个问题(在使用Page Events之外)?
(*注意:有两种辅助方法用于创建表格和测量段落的高度,除了按钮点击的主代码之外还包括这些方法)
(*注意:每个表都将SplitLate设置为false,以使内容从一页到另一页均匀流动);所有表都有特定的宽度,宽度被锁定
//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;
}
答案 0 :(得分:0)
使用绝对定位解决它。我通过将页脚高度添加到底部边距的值来计算页脚应该位于的位置。为了减轻对覆盖现有内容的担忧,我计算了最后一页上剩余的可用空间量;如果它对我的页脚不够,我会添加一个新页面并在下一页的开头发布我的内容。
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();
}