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

时间:2014-06-06 11:29:21

标签: c# pdf pdf-generation itextsharp itext

使用iTextSharp我有以下问题。

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

enter image description here

正如您所看到的那样,我在页面末尾插入一个表格,并将其拆分为两页,第二页面标题将被表格内容覆盖。

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

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

1)也许我可以检查元素是否会轻易进入页面。如果没有创建一个新页面并将其放入这个新页面(但如果一个表需要多于一个页面,这可能是一个问题,如果我有一个非常大的表格的情况下)

2)我允许将一个表分成2页,但在这种情况下,我在第二页的上方留下了一些边距,以便正确显示标题。

或者我该怎么做才能解决这种情况?

TNX

编辑:

我已按以下方式添加标题:

1)我实现了一个名为 PdfHeaderFooter 的类,它扩展了 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)在文档创建中使用header heigt设置上边距。

是不是?

编辑2:

我想跟你说的那样做,现在我有以下几种情况:

1)进入扩展 PdfPageEventHelper PdfHeaderFooter 我删除了 OnStartPage()方法

2)我已将头表创建转移到 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()方法包含页眉和页脚的创建。

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

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。

但我仍有同样的问题。

如果我用80改变30值,它只是向下移动标题,留下白色顶部,但不能解决问题。

我错过了什么?有什么问题?

1 个答案:

答案 0 :(得分:3)

我假设您正在正确添加页眉。即:您已在页面事件中实现了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

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

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

tabHead.WidthPercentage = 98;

但是,你在浪费资源。例如:您在页面事件中创建徽标: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);

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