创建PDF文档,页眉页脚是必不可少的一环,页面页脚的作用一般是会存放一些固定的信息,例如当前页面的章节名称,公司logo,页码等等,我这里以下图为例:
位置: 1 : 显示当前页面的所在的版块名称,例如一本书的第几章等
2: 显示当前的用户名或作者之类
3:logo图片
4:当前页码
一、事件
页眉页脚在每一页的布局和逻辑都是一致,除了页码需要跟着页面变动而改变。在itext7 提供了事件出来的方式。代码如下
pdfDoc.addEventHandler(type,IEventHandler);
参数:type : 事件的类型,有四种分别是 PdfDocumentEvent.END_PAGE ; PdfDocumentEvent.START_PAGE; PdfDocumentEvent.INSERT_PAGE; PdfDocumentEvent.REMOVE_PAGE。
看名称就是知道分别代表都是页面完成,开始,插入,移除时触发事件
IEventHandler : 触发的事件具体代码,需要自己编写一个类,并实现接口IEventHandler
二、具体代码
1、实现接口IEventHandler的类 DemoHeaderFooterHandler.java
public class DemoHeaderFooterHandler implements IEventHandler {
private final String imgLogo;
private final PdfFont font;
public DemoHeaderFooterHandler(final String imgLogo, final PdfFont font) {
this.imgLogo = imgLogo;
this.font = font;
}
@Override
public void handleEvent(final Event event) {
try {
final PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
final PdfDocument pdfDoc = docEvent.getDocument();
final Document doc = new Document(pdfDoc);
final PdfPage page = docEvent.getPage();
final int pageNumber = pdfDoc.getPageNumber(page);
final Rectangle pageSize = page.getPageSize();
final float pdfWidth = pageSize.getWidth();
final float pdfHeight = pageSize.getHeight();
final PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
final Color lineColor = new DeviceRgb(57, 123, 198);
pdfCanvas.setLineWidth(1.5f).setStrokeColor(lineColor);
final float tableWidth = pdfWidth - doc.getRightMargin() - doc.getLeftMargin();
// 页眉
final float x0 = doc.getRightMargin(), y0 = pdfHeight - doc.getTopMargin();
pdfCanvas.moveTo(x0, y0).lineTo(pdfWidth - doc.getRightMargin(), y0).stroke();
final Table headerTable = new Table(2);
headerTable.setHeight(30);
headerTable.setFixedLayout();
headerTable.setWidth(tableWidth);
headerTable.setHorizontalAlignment(HorizontalAlignment.CENTER);
final Paragraph pageNameParagraph = new Paragraph();
// realnameParagraph.setFixedLeading(4f);
pageNameParagraph.setVerticalAlignment(VerticalAlignment.BOTTOM);
pageNameParagraph.add("页面名称");
final Cell pageNameCell = new Cell();
pageNameCell.setBorder(Border.NO_BORDER);
pageNameCell.add(pageNameParagraph);
pageNameCell.setFont(this.font);
pageNameCell.setFontSize(12f);
pageNameCell.setFontColor(lineColor);
pageNameCell.setVerticalAlignment(VerticalAlignment.BOTTOM);
headerTable.addCell(pageNameCell);
final Paragraph realnameParagraph = new Paragraph();
// realnameParagraph.setFixedLeading(4f);
realnameParagraph.setVerticalAlignment(VerticalAlignment.BOTTOM);
realnameParagraph.add(new Tab()).addTabStops(new TabStop(1000, TabAlignment.RIGHT));
realnameParagraph.add("半路凉亭");
final Cell realnameCell = new Cell();
realnameCell.setBorder(Border.NO_BORDER);
realnameCell.add(realnameParagraph);
realnameCell.setFont(this.font);
realnameCell.setFontSize(12f);
realnameCell.setFontColor(lineColor);
realnameCell.setVerticalAlignment(VerticalAlignment.BOTTOM);
headerTable.addCell(realnameCell);
headerTable.setFixedPosition(doc.getLeftMargin(), pdfHeight - doc.getTopMargin(), tableWidth);
doc.add(headerTable);
// 页脚
pdfCanvas.moveTo(x0, doc.getBottomMargin()).lineTo(pdfWidth - doc.getRightMargin(), doc.getBottomMargin())
.stroke();
final Table table = new Table(2);
table.setHeight(40);
table.setFixedLayout();
table.setWidth(tableWidth);
table.setHorizontalAlignment(HorizontalAlignment.CENTER);
final Cell imgCell = new Cell();
imgCell.setBorder(Border.NO_BORDER);
imgCell.add(this.getLogoImage());
imgCell.setVerticalAlignment(VerticalAlignment.TOP);
table.addCell(imgCell);
final String pageNo = String.format("%d", pageNumber);
final Paragraph pageNoParagraph = new Paragraph();
pageNoParagraph.setFontColor(new DeviceRgb(166, 166, 166));
pageNoParagraph.setFontSize(12f);
pageNoParagraph.add(new Tab()).addTabStops(new TabStop(1000, TabAlignment.RIGHT));
pageNoParagraph.add(pageNo);
table.addCell(new Cell().add(pageNoParagraph).setBorder(Border.NO_BORDER));
table.setFixedPosition(doc.getLeftMargin(), doc.getBottomMargin() - table.getHeight().getValue(),
tableWidth);
doc.add(table);
System.out.println("***" + table.getHeight());
} catch (final Exception e) {
e.printStackTrace();
throw new NormStarRuntimeException("页脚异常" + e.getMessage());
}
}
private Image getLogoImage() {
Image image;
try {
image = new Image(ImageDataFactory.create(this.imgLogo));
image.scaleToFit(75, 100);
} catch (final MalformedURLException e) {
final String errorMessage = "logo图片";
throw new NormStarRuntimeException(errorMessage, e);
}
return image;
}
}
2、生成文档的代码
private final String fileImg = "D:/itext-pdf/logo.png";
public PdfFont getSongTiFont() throws IOException {
return PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);
}
public PdfFont getHeiTiFont() throws IOException {
return PdfFontFactory.createFont("D:/itext-pdf/font/heiti.TTF", PdfEncodings.IDENTITY_H,
false);
}
/**
* 页眉页脚
*
* @author
* @date 2021年3月29日
*/
@Test
public void testHeaderFooter() {
final File file = new File("D:/itext-pdf/001.pdf");
Document doc = null;
try {
final PdfFont font = this.getSongTiFont();
final PdfWriter writer = new PdfWriter(file);
final PdfDocument pdfDoc = new PdfDocument(writer);
doc = new Document(pdfDoc);
final Image img = new Image(ImageDataFactory.create(this.fileImg));
img.setHeight(new UnitValue(UnitValue.POINT, 35f));
img.setWidth(new UnitValue(UnitValue.POINT, 100f));
doc.setMargins(50, 60, 50, 60);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE,
new DemoHeaderFooterHandler(this.fileImg, this.getHeiTiFont()));
pdfDoc.addNewPage();
final int number = pdfDoc.getNumberOfPages();
final float pdfWidth = pdfDoc.getPage(number).getPageSize().getWidth();
final float pdfHeight = pdfDoc.getPage(number).getPageSize().getHeight();
final Paragraph paragraph = new Paragraph("你好 itext-pdf");
paragraph.add("第" + number + "页");
paragraph.add("宽:" + pdfWidth + " 高:" + pdfHeight); // 宽:595.0 高:842.0
paragraph.setFont(font);
paragraph.add(img);
doc.add(paragraph);
// PdfContentByte cb = writer.getDirectContent();
final PdfOutline root = pdfDoc.getOutlines(true);
final String title = String.format("Numbers from %s to %s", 1, 10);
final Text c = new Text(title);
//final TOCTextRenderer renderer = new TOCTextRenderer(root, c);
//c.setNextRenderer(renderer);
doc.add(new Paragraph(c));
pdfDoc.addNewPage();
System.out.println("***" + root.getTitle());
} catch (final Exception e) {
e.printStackTrace();
final String errorMessage = "异常";
throw new NormStarRuntimeException(errorMessage, e);
} finally {
if (doc != null) {
doc.close();
}
}
}
注意:
1.中文字体问题
页尾页脚中如果有中文字体,则必须使用外部嵌入的字体,如我这里嵌入的黑体,使用默认的宋体,则会报错
2.表格绝对坐标定位
setFixedPosition(); 使用这个方法写入表格时,是以表格的左下角为坐标原点定位的。