带有页脚的动态内容,使用填充

本文关键字:填充 动态 | 更新日期: 2023-09-27 18:16:44

我正在尝试创建长度高度可变的文档,并使它们可以是表驱动的。我正试图使用iTextSharp表专门创建文档,包括页脚废话。在下面的代码中,我试图将最后一个单元格填充到与剩余空间相等的确切数量,以便我的页脚将正好放置在文档的底部,紧靠底部边距。当我尝试使用1、2或3英寸的文档边距时,这很好,但是当我使用5英寸时,我的页脚开始换行。我认为这可能只是一个数学不好的例子。有没有人有任何建议来纠正这一点(使用页面事件之外)?

(*注:有两个辅助方法用于创建表格和测量段落的高度,也包括除了主代码从一个按钮点击)

(*注:每个表都有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;
}

带有页脚的动态内容,使用填充

使用绝对定位求解。我通过将页脚高度添加到底部边距的值来计算页脚应该在的位置。为了减轻对覆盖现有内容的担忧,我计算了最后一页上剩余的可用空间量;如果不够我的页脚,我会添加一个新页面,并在下一页的开头发布我的内容。

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