前言
我在用iText 5.5.13.3这个版本做报表导出功能,遇到了一张报表需要将表头进行固定。查询了一些资料,发现似乎没有官方的资料实现了这个功能。因此,只好自己来实现了。我之前有实现过页眉页脚功能,所以我就在想能否将表头固定到页眉中,这样便可以每页都有显示。
因此我的方案就是在页眉中放一个表,再将内容表放在下方。
一、效果
从图中可以看出,第2页依旧有相同的页眉表格。
二、代码
package com.mieasy.chilin.es.assess.system.java2pdf.measure;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.mieasy.chilin.es.assess.module_common.dto.MeasureList;
import com.mieasy.chilin.es.assess.system.java2pdf.utils.CellUtil;
import com.mieasy.chilin.es.assess.system.java2pdf.utils.FontUtil;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author Youngpine
* @create 2024/1/14
* @description 导出成PDF
*/
public class MeasureList2PDF {
public static final String DEST = "C:\\Users\\youngpine\\Desktop\\simple_table.pdf";
public static BaseFont bfChinese;
public static Map<String, Object> resident;
static {
bfChinese = FontUtil.generate();
}
public static void createPdf(String dest, Map<String, Object> para) throws IOException, DocumentException {
resident = (Map<String, Object>)para.get("resident");
List<MeasureList> list = (List<MeasureList>) para.get("list");
Document document = new Document();
// 这一步很关键,默认创建的document的边距都为36f,但是如果页眉表格占用太宽,
// 就会内容和表头重叠,因此设定上边距为页眉表格headerTable的高度,即可以通
// 过headerTable.getTotalheight()来获取
document.setMargins(36f, 36f, 114f, 16f);
document.setPageSize(PageSize.A4.rotate());
// 获取文档的页大小
Rectangle pageSize = document.getPageSize();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
// 添加页事件处理器
HeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
// 打开文档,添加内容
document.open();
// 创建一个字体
Font font = new Font(bfChinese, 11, Font.NORMAL, BaseColor.BLACK);
// 创建表格
PdfPTable table = new PdfPTable(14);
table.setWidthPercentage(100);
table.setTotalWidth(pageSize.getWidth() - document.leftMargin() - document.rightMargin()); // 计算出表的宽度,实际为了和页面中的headerTable宽度保持一直
table.setSpacingBefore(10f); // 前间距
table.setSpacingAfter(10f); // 后间距
for (int i = 0; i < 100; i++) {
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
table.addCell(generateTitle("test", 1, 1, font));
}
document.add(table);
document.close();
}
// 内部类,用于在PDF关闭时往里面加数据
private static class HeaderFooterPageEvent extends PdfPageEventHelper{
@Override
public void onEndPage(PdfWriter writer, Document document) {
// 获取文档的页大小
Rectangle pageSize = document.getPageSize();
// 创建页眉表格
PdfPTable headerTable = new PdfPTable(14);
headerTable.setWidthPercentage(100f);
headerTable.setTotalWidth(pageSize.getWidth() - document.leftMargin() - document.rightMargin()); // 计算表格宽度
Font font = new Font(bfChinese, 12, Font.NORMAL, BaseColor.BLACK);
Font fontBold = new Font(bfChinese, 12, Font.BOLD, BaseColor.BLACK);
headerTable.addCell(generateTitleNoBorder("服務", 1, 2, fontBold));
headerTable.addCell(CellUtil.generateEmptyCell(10));
headerTable.addCell(generateTitleNoBorder("資料", 1, 2, fontBold));
headerTable.addCell(generateTitleNoBorder("(院)", 1, 2, font));
headerTable.addCell(CellUtil.generateEmptyCell(4));
headerTable.addCell(generateTitleNoBorder("記錄", 1, 2, fontBold));
headerTable.addCell(CellUtil.generateEmptyCell(6));
headerTable.addCell(CellUtil.generateTitleRightMiddle("姓名:", 2, font));
headerTable.addCell(CellUtil.generateContent("123", 3, font));
headerTable.addCell(CellUtil.generateTitleRightMiddle("性别:", 1, font));
headerTable.addCell(CellUtil.generateContent("123", 1, font));
headerTable.addCell(CellUtil.generateTitleRightMiddle("年龄:", 1, font));
headerTable.addCell(CellUtil.generateContent("123", 2, font));
headerTable.addCell(CellUtil.generateTitleRightMiddle("房號:", 2, font));
headerTable.addCell(CellUtil.generateContent("123", 2, font));
// 添加内容到表格(这里可以添加你需要的内容)
headerTable.addCell(generateTitle("title", 2, 1, font));
headerTable.addCell(generateTitle("title", 2, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 2, font));
headerTable.addCell(generateTitle("title", 1, 2, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 2, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
headerTable.addCell(generateTitle("title", 1, 1, font));
// 定位页眉表格的起始坐标
float x = (pageSize.getLeft() + pageSize.getRight()) / 2 - headerTable.getTotalWidth() / 2;
float y = pageSize.getTop() - 8f;
// 将表格添加到文档
headerTable.writeSelectedRows(0, -1, x, y, writer.getDirectContent());
PdfContentByte cb = writer.getDirectContent();
cb.beginText();
cb.setFontAndSize(bfChinese, 12);
// 页脚右侧写入页码
Phrase pageNum = new Phrase(writer.getPageNumber() + "");
cb.showTextAligned(Element.ALIGN_RIGHT, pageNum.getContent(), document.right(), document.bottom() - 10, 0);
cb.endText();
}
}
// 生成一个单元格内容的工具代码
public static PdfPCell generateTitle(String title, int rowspan, int colspan, Font font) {
PdfPCell cell = new PdfPCell(new Phrase(title, font));
cell.setRowspan(rowspan);
cell.setColspan(colspan);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setMinimumHeight(20f);
return cell;
}
public static PdfPCell generateTitleNoBorder(String title, int rowspan, int colspan, Font font) {
PdfPCell cell = new PdfPCell(new Phrase(title, font));
cell.setRowspan(rowspan);
cell.setColspan(colspan);
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
return cell;
}
}
总结
本文记录了用iText进行PDF导出时做一个固定表头的功能,这个功能就是通过在页眉中插入一个表头。若有人有其他方案,欢迎分享。