提问者:小点点

如何处理iText\iTextSharp表拆分为两个页面的情况?


我使用iTextSharp有以下问题。

我正在将一些表格放入我的文档中。问题是,如果一个表格的内容不适合一个页面并进入另一个页面,我必须覆盖第二个页面标题,所以我有以下情况:

如您所见,我在页面末尾插入了一个表格,这被分成两页,第二页头被表格内容覆盖。

我想避免这种情况,但我不知道该怎么办。

我在想也许我可以做以下事情之一:

>

  • 也许我可以检查一个元素是否完全进入一个页面。如果不创建一个新页面并将其放入这个新页面(但如果单个表需要超过一页,这可能是一个问题,在这种情况下,如果我有一个非常大的表)

    我允许将表格拆分为2页,但在这种情况下,我在第二页的上部留下了一些边距行间距,以便正确显示标题。

    或者我能做些什么来解决这种情况?

    Tnx

    编辑:

    我以以下方式添加了标题:

    1. 我已经实现了创建一个名为PdfHeaderFoter的类,它扩展了PdfPageEventHelper类并实现了它的方法。

    此时它的类包含以下方法:

        // 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("")) { 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 end of each page
        public override void OnEndPage(PdfWriter writer, Document document)
        {
            base.OnEndPage(writer, document);
    
            int pageN = writer.PageNumber;      // numero della pagina corrente OK
            String text = "Page " + pageN + " of ";
            float len = bf.GetWidthPoint(text, 8);
    
            Rectangle pageSize = document.PageSize;
            
            cb.SetRGBColorFill(100, 100, 100);
    
            cb.BeginText();
            cb.SetFontAndSize(bf, 8);
            cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
            cb.ShowText(text);
            cb.EndText();
    
            cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
    
            cb.BeginText();
            cb.SetFontAndSize(bf, 8);
            cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
                "Printed On " + PrintTime,
                pageSize.GetRight(40),
                pageSize.GetBottom(30), 0);
            cb.EndText();
        }
    

    因此,您可以看到,OnStartPage()方法在每个页面的开头添加页眉,OnEndPage()在每个页面的末尾添加页脚。

    因此,根据我从您的回复中了解到的情况,我必须执行以下步骤:

    1. 将标头插入从OnStartPage()移动到OnEndPage()
    2. 使用绝对位置将其放置在页面的上部。
    3. 在文档创建中使用标题高度来设置顶部边距。

    这样做对吗?

    编辑2:

    我试着按你说的做,现在我有以下情况:

    >

  • 在扩展PdfPageEventHelper的PdfHeaderFoter中,我删除了OnStartPage()方法

    我已经将头表创建移动到OnEndPage()方法中,现在它是这样的:

     // write on end of each page
     public override void OnEndPage(PdfWriter writer, Document document)
     {
         base.OnEndPage(writer, document);
    
         // HEADER:
         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("")) { 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);
    
         float headerHeight = tabHead.CalculateHeights();
    
    
    
         // FOOTER:
         int pageN = writer.PageNumber;      // numero della pagina corrente OK
         String text = "Page " + pageN + " of ";
         float len = bf.GetWidthPoint(text, 8);
    
         Rectangle pageSize = document.PageSize;
    
         cb.SetRGBColorFill(100, 100, 100);
    
         cb.BeginText();
         cb.SetFontAndSize(bf, 8);
         cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
         cb.ShowText(text);
         cb.EndText();
    
         cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
    
         cb.BeginText();
         cb.SetFontAndSize(bf, 8);
         cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
             "Printed On " + PrintTime,
             pageSize.GetRight(40),
             pageSize.GetBottom(30), 0);
         cb.EndText();
     }
    

    正如您现在看到的,OnEndPage()方法包含页眉和页脚创建。

    在我看来tabHeader(我的标题表)使用绝对定位,因为我有:

    tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
    

    在我创建文档的另一个类中,我有这一行:

    document = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 50, 50, 30, 65);
    

    所以页面是A4,上边距为30px。

    但是我仍然有同样的问题。

    如果我将30值更改为80,它只是将标题向下移动,留下一个白色顶部,但并不能解决问题。

    我错过了什么?出什么事了?


  • 共1个答案

    匿名用户

    我假设您正确地添加了页眉。也就是说:您已经在页面事件中实现了onEndPage()方法(而不是onStartPage()方法)并且您正在绝对位置添加页眉。当您在绝对位置添加页眉时,您确切地知道它需要多少空间。

    创建文档对象时,您定义页面大小。如果不这样做,页面大小将为A4(595 x 842用户单位)。您还定义边距。如果不这样做,两边的边距将为半英寸(36个用户单位)。

    当表格拆分时,页面大小和边距会得到尊重:iText不会将表格的任何部分放在该区域。

    因此,解决方案很简单:因为您知道标题所需的空间,所以您所要做的就是以标题适合于边距的方式定义边距。

    问题更新后更新:

    1.

    这是错误的:

    // write on start of each page
    public override void OnStartPage(PdfWriter writer, Document document)
    {
        ...
        tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
    }
    

    您永远不应在OnStartPage()方法中添加任何内容。将写入标头的代码移动到OnEndPage()方法。

    2.

    您已经在使用绝对位置添加tabHeader:您正在坐标x=Document. left;y=document.Top处添加它。

    您为在绝对位置添加的文件定义宽度百分比。这没有任何意义,请删除以下行:

    tabHead.WidthPercentage = 98;
    

    但是,您正在浪费资源。例如:您在page事件中创建徽标:iTextSharp. text.Image.GetInstance(folderImages"nvdLogo.png")。这意味着您添加图像字节的次数与页面一样多,导致PDF文件中的冗余信息(您有一个臃肿的文件)。

    您可以通过在onEndPage()方法之外创建图像来优化该过程。您甚至可以在该方法之外创建表。例如:在事件类中创建成员变量tabHead,并在事件实现的构造函数中或在OnOpenDocument()方法中创建表(该方法只被调用一次)。在onEndPage()方法中重用表(和图像)。

    现在图像字节将只出现在PDF文件中一次(您将获得大量KBytes),并且您只需创建一次表(减少CPU时间的浪费)。

    3.

    一个更好的解决方案是在页面事件之外和打开文档之前创建tabhead对象。当您定义总宽度时,您可以询问表格的高度:

    float h = tabHead.TotalHeight;
    

    现在您可以使用h来定义上边距:

    document.SetMargins(36f, 36f, h, 36f);
    

    请注意,在打开文档之前设置边距很重要。您还必须调整添加表格的坐标。例如:

    tabHead.WriteSelectedRows(0, -1, document.Left, document.Top + h, writer.DirectContent);
    

    你对头球位置的评论显示出严重缺乏洞察力。