我使用iTextSharp有以下问题。
我正在将一些表格放入我的文档中。问题是,如果一个表格的内容不适合一个页面并进入另一个页面,我必须覆盖第二个页面标题,所以我有以下情况:
如您所见,我在页面末尾插入了一个表格,这被分成两页,第二页头被表格内容覆盖。
我想避免这种情况,但我不知道该怎么办。
我在想也许我可以做以下事情之一:
>
也许我可以检查一个元素是否完全进入一个页面。如果不创建一个新页面并将其放入这个新页面(但如果单个表需要超过一页,这可能是一个问题,在这种情况下,如果我有一个非常大的表)
我允许将表格拆分为2页,但在这种情况下,我在第二页的上部留下了一些边距行间距,以便正确显示标题。
或者我能做些什么来解决这种情况?
Tnx
编辑:
我以以下方式添加了标题:
此时它的类包含以下方法:
// 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()在每个页面的末尾添加页脚。
因此,根据我从您的回复中了解到的情况,我必须执行以下步骤:
这样做对吗?
编辑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,它只是将标题向下移动,留下一个白色顶部,但并不能解决问题。
我错过了什么?出什么事了?
我假设您正确地添加了页眉。也就是说:您已经在页面事件中实现了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);
你对头球位置的评论显示出严重缺乏洞察力。