目录
依赖
创建单元格
表格数据行辅助添加方法
创建表头单元格
创建下划线
创建带下划线的文字
创建PDF
依赖
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.2</version>
</dependency>
<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.13</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version>
</dependency>
创建单元格
/*** 创建单元格** @param text 显示值* @param font 字体* @param horizontalAlign 值水平显示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign 值垂直显示位置(例:Element.ALIGN_MIDDLE => 居中)* @param minHeight 最小行高* @return PdfPCell*/private static PdfPCell createCell(String text, Font font, int horizontalAlign, int verticalAlign, float minHeight) {Paragraph para = new Paragraph(text, font);para.setAlignment(horizontalAlign);para.setLeading(para.getLeading() * 1.2f);PdfPCell cell = new PdfPCell(para);cell.setHorizontalAlignment(horizontalAlign);// 水平居中cell.setVerticalAlignment(verticalAlign);// 垂直居中cell.setMinimumHeight(minHeight); // 设置最小高度
// cell.setPadding(0);// 内边距cell.setBorderWidth(0.5f);// 单元格边框宽度cell.setNoWrap(false);// 自动换行return cell;}
表格数据行辅助添加方法
/*** 辅助添加表格数据行* @param table 表格* @param col1 列1值* @param col2 列2值* @param col3 列3值* @param font 字体*/private static void addTableRow(PdfPTable table, String col1, String col2, String col3, Font font) {// 有几列几个 table.addCell 方法table.addCell(createCell(col1, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));table.addCell(createCell(col2, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));table.addCell(createCell(col3, font, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f));}
/*** 辅助添加表格行数据* @param table 表格* @param tableHeaderNumber 表格表头列数* @param font 字体* @param horizontalAlign 值水平显示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign 值垂直显示位置(例:Element.ALIGN_MIDDLE => 居中)* @param minHeight 最小行高* @param column 单元格数据,x列传入x个使用【,】隔开*/private static void addTableRow(PdfPTable table,int tableHeaderNumber, Font font, int horizontalAlign, int verticalAlign, float minHeight, String... column) {if (column.length == 1 && column[0].isEmpty()) {// 只传入一个【""】值if (tableHeaderNumber > 0) {// 表头列数 <= 0 时,不创建空行数据for (int i = 0; i < tableHeaderNumber; i++) {// 根据表头列数生成对应的空行数据,值为【" "】(为""时不会创建空行数据)table.addCell(createCell(" ", font, horizontalAlign, verticalAlign, minHeight));}}}else {for (String s : column) {table.addCell(createCell(s, font, horizontalAlign, verticalAlign, minHeight));}}}
创建表格表头
/*** 创建表头单元格** @param table 表* @param text 显示值* @param font 字体* @param bgColor 单元格背景色* @param horizontalAlign 值水平显示位置(例:Element.ALIGN_CENTER => 居中)* @param verticalAlign 值垂直显示位置(例:Element.ALIGN_MIDDLE => 居中)* @param height 行高*/private static void createTableHeader(PdfPTable table, String text, Font font, BaseColor bgColor, int horizontalAlign, int verticalAlign, float height) {Paragraph para = new Paragraph(text, font);para.setAlignment(horizontalAlign);PdfPCell cell = new PdfPCell(para);cell.setBackgroundColor(bgColor);cell.setHorizontalAlignment(horizontalAlign);// 水平居中cell.setVerticalAlignment(verticalAlign);// 垂直居中cell.setMinimumHeight(height); // 设置最小高度cell.setBorderWidth(0.5f);// 单元格边框宽度
// cell.setFixedHeight(height); // 固定行高,文字超出高度不会显示
// cell.setPadding(8);// 内边距
// cell.setNoWrap(false);// 自动换行table.addCell(cell);}
创建下划线
/*** 创建下划线** @param width 宽* @param font 字体* @return Chunk*/private static Chunk createUnderlineChunk(float width, Font font) {Chunk underlineChunk = new Chunk(" ");underlineChunk.setHorizontalScaling(width); // 设置宽度underlineChunk.setUnderline(0.5f, -1f);// param-1:线宽 param-2:线位置,基于行底部,负数下调正数上调underlineChunk.setFont(font);// 设置字体return underlineChunk;}
/*** 使用PdfContentByte自定义绘制下划线** @param writer PdfWriter* @param width 宽度* @return Chunk*/private static Chunk createCustomDrawnLine(PdfWriter writer, float width) {// 创建一个空白Chunk作为占位符Chunk placeholder = new Chunk(" ");// 添加自定义绘制功能placeholder.setGenericTag(" ");writer.setPageEvent(new PdfPageEventHelper() {@Overridepublic void onGenericTag(PdfWriter writer, Document document,Rectangle rect, String text) {// 获取画布PdfContentByte canvas = writer.getDirectContent();canvas.saveState();// 设置下划线样式canvas.setLineWidth(0.5f);canvas.setColorStroke(BaseColor.BLACK);// 计算下划线位置float y = rect.getBottom() - 3; // 在文本下方3点处float x1 = rect.getLeft();float x2 = x1 + width;// 绘制下划线canvas.moveTo(x1, y);canvas.lineTo(x2, y);canvas.stroke();canvas.restoreState();}});return placeholder;}
创建带下划线的文字
/*** 创建带下划线的文字块* @param text 文字* @param font 字体* @return Chunk*/private static Chunk createUnderlinedText(String text, Font font){Chunk textChunk = new Chunk(text, font);textChunk.setUnderline(0.5f, -1f);// 设置下划线:线宽0.5,位置在基线下方1点return textChunk;}
创建PDF
创建 Document 对象、pdf写入器
Document document = new Document(PageSize.A4, 90, 90, 80, 50);// 创建文档对象(A4纸大小,边距:左, 右, 上, 下)PdfWriter writer = PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(dest)));// 创建PDF写入器
// PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));PageNumberEventHandler eventHandler = new PageNumberEventHandler();writer.setPageEvent(eventHandler);// 打开文档document.open();
设置字体,避免中文不显示问题
// 字体,中文字体,避免文字不显示BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font titleFont = new Font(baseFont, 18, Font.BOLD);// 标题字体Font subtitleFont = new Font(baseFont, 12);// 副标题字体Font contentFont = new Font(baseFont, 12);// 正文字体Font headerFont = new Font(baseFont, 12);// 表头字体Font footerFont = new Font(baseFont, 12);// 页脚字体
标题、副标题定义
// 标题Paragraph title = new Paragraph("Leslie Lee", titleFont);title.setAlignment(Element.ALIGN_CENTER);// 左右居中title.setSpacingAfter(5f); // 设置段后间距document.add(title);// 副标题Paragraph subtitle = new Paragraph("(風華絕代)", subtitleFont);subtitle.setAlignment(Element.ALIGN_CENTER);subtitle.setSpacingAfter(25f);document.add(subtitle);
正文段落
// 添加内容段落Paragraph content = new Paragraph();content.setAlignment(Element.ALIGN_JUSTIFIED); // 段落两端对齐content.add(new Chunk("風華絕代、風流倜儻、玉樹臨風", contentFont));content.add(Chunk.NEWLINE);// 换行,两个效果为空一行content.add(Chunk.NEWLINE);
正文中添加带下划线的文字
content.add(createUnderlinedText(text,contentFont));// 正文添加带下划线的文字,需这样单独添加
表格——创建表格
PdfPTable table = new PdfPTable(3);// 创建表格 x列table.setWidthPercentage(100); // 表格宽度占页面百分比table.setSpacingBefore(5f); // 表格前间距table.setSpacingAfter(10f); // 表格后间距table.setSplitLate(false); // 防止单元格在分页时被拆分table.setSplitRows(true); // 允许行拆分
// table.setHeaderRows(1); // 前 x 行作为表头,跨页时重复
表格——创建表头-上面的方法
addTableHeader(table, "代表作", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表头单元格,几列就几个 addTableHeader 方法addTableHeader(table, "时间", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表头单元格,几列就几个 addTableHeader 方法addTableHeader(table, "角色", headerFont, null, Element.ALIGN_CENTER, Element.ALIGN_MIDDLE, 25f);// 添加表头单元格,几列就几个 addTableHeader 方法
表格——创建单元格-上面的方法
addTableRow(table, "絕代風華", "1956-09-12", "Cheung Kwok Wing", contentFont);// 添加表格数据,几行就几个 addTableRow 方法
添加页脚
// 添加页脚Paragraph footer = new Paragraph("【风华绝代】", footerFont);footer.setAlignment(Element.ALIGN_CENTER);document.add(footer);
添加图片
// 添加图片(可选)try {String imagePath = "img.jpg"; // 替换为实际图片路径Image img = Image.getInstance(imagePath);img.scaleToFit(100, 100); // 调整图片大小img.setAbsolutePosition(36, 36); // 左下角位置document.add(img);} catch (Exception e) {System.err.println("图片添加失败: " + e.getMessage());}
关闭文档
document.close();// 关闭文档
页码处理类
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;import java.io.IOException;/** 页码处理* @author Leslie Lee* @version 2003/04/01* @date 1956/09/12*/
public class PageNumberEventHandler extends PdfPageEventHelper {private final Font footerFont;// 页脚字体private PdfTemplate totalPagesTemplate;// 用于存储总页数的模板private final BaseFont baseFont;// 基础字体public PageNumberEventHandler() throws DocumentException, IOException {super();baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);footerFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.DARK_GRAY);}@Overridepublic void onOpenDocument(PdfWriter writer, Document document) {totalPagesTemplate = writer.getDirectContent().createTemplate(30, 17);// 创建用于总页数的模板}@Overridepublic void onEndPage(PdfWriter writer, Document document) {PdfContentByte canvas = writer.getDirectContent();// 获取PDF内容canvas.saveState();// 保存当前状态// 创建页码文本String footerText = writer.getPageNumber() + " /";// 当前页码// 设置页脚位置(居中底部)float x = (document.left() + document.right()) / 2;// 文档中间位置float y = document.bottom() - 20;// 文档底部上移 20 的位置ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, new Phrase(footerText, footerFont), x, y, 0);// 添加页码文本float pageTextWidth = baseFont.getWidthPoint(footerText, 9);// 计算页码文本宽度// 添加总页数模板(占位符)canvas.addTemplate(totalPagesTemplate, x + pageTextWidth / 2 + 3, y); // 计算位置 x为左右位置(数大越右、数小越左) y为垂直位置(减数为下调、加数为上调)// 添加"页"字
// canvas.beginText();
// canvas.setFontAndSize(baseFont, 9);
// canvas.setColorFill(BaseColor.DARK_GRAY);
// canvas.showTextAligned(Element.ALIGN_CENTER, "页", x + pageTextWidth / 2 + 22, y, 0);
// canvas.endText();// 添加页码左标题
// String titleText = "";
// ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(titleText, footerFont), document.left(), y, 0);// 添加页码右标题
// String companyText = "";
// ColumnText.showTextAligned(canvas, Element.ALIGN_RIGHT, new Phrase(companyText, footerFont), document.right(), y, 0);// 添加页脚分隔线
// canvas.setLineWidth(0.5f);// 分隔线粗细
// canvas.setColorStroke(BaseColor.LIGHT_GRAY);// 灰色
// canvas.moveTo(document.left(), y + 10);// 坐标起点 参数1:开始位置(左右) 参数2:高度(上下) 正数上调负数下调
// canvas.lineTo(document.right(), y + 10);// 坐标终点 参数1:结束位置(左右) 参数2:高度(上下) 正数上调负数下调
// canvas.stroke();// 恢复状态canvas.restoreState();}/*** 文档关闭时,写入总页数到模板*/@Overridepublic void onCloseDocument(PdfWriter writer, Document document) {totalPagesTemplate.beginText();totalPagesTemplate.setFontAndSize(baseFont, 10);totalPagesTemplate.setColorFill(BaseColor.DARK_GRAY);totalPagesTemplate.showText(String.valueOf(writer.getPageNumber())); // 有几页封面就减几,没有封面不减totalPagesTemplate.endText();}
}
Leslie Lee 随笔