【pdf】Java代码生成PDF

目录

依赖

创建单元格

表格数据行辅助添加方法

创建表头单元格

创建下划线

创建带下划线的文字

创建PDF


依赖

XML 复制代码
<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>

创建单元格

java 复制代码
    /**
     * 创建单元格
     *
     * @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;
    }

表格数据行辅助添加方法

java 复制代码
    /**
     * 辅助添加表格数据行
     * @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));
    }
java 复制代码
    /**
     * 辅助添加表格行数据
     * @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));
            }
        }
    }

创建表格表头

java 复制代码
    /**
     * 创建表头单元格
     *
     * @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);
    }

创建下划线

java 复制代码
    /**
     * 创建下划线
     *
     * @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;
    }
java 复制代码
    /**
     * 使用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() {
            @Override
            public 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;
    }

创建带下划线的文字

java 复制代码
    /**
     * 创建带下划线的文字块
     * @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写入器

java 复制代码
        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();

设置字体,避免中文不显示问题

java 复制代码
        // 字体,中文字体,避免文字不显示
        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);// 页脚字体

标题、副标题定义

java 复制代码
        // 标题
        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);

正文段落

java 复制代码
        // 添加内容段落
        Paragraph content = new Paragraph();
        content.setAlignment(Element.ALIGN_JUSTIFIED); // 段落两端对齐
        content.add(new Chunk("風華絕代、風流倜儻、玉樹臨風", contentFont));
        content.add(Chunk.NEWLINE);// 换行,两个效果为空一行
        content.add(Chunk.NEWLINE);

正文中添加带下划线的文字

java 复制代码
        content.add(createUnderlinedText(text,contentFont));// 正文添加带下划线的文字,需这样单独添加

表格------创建表格

java 复制代码
        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 行作为表头,跨页时重复

表格------创建表头-上面的方法

java 复制代码
        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 方法

表格------创建单元格-上面的方法

java 复制代码
        addTableRow(table, "絕代風華", "1956-09-12", "Cheung Kwok Wing", contentFont);// 添加表格数据,几行就几个 addTableRow 方法

添加页脚

java 复制代码
        // 添加页脚
        Paragraph footer = new Paragraph("【风华绝代】", footerFont);
        footer.setAlignment(Element.ALIGN_CENTER);
        document.add(footer);

添加图片

java 复制代码
        // 添加图片(可选)
        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());
        }

关闭文档

java 复制代码
        document.close();// 关闭文档

页码处理类

java 复制代码
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);
    }

    @Override
    public void onOpenDocument(PdfWriter writer, Document document) {
        totalPagesTemplate = writer.getDirectContent().createTemplate(30, 17);// 创建用于总页数的模板
    }

    @Override
    public 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();
    }

    /**
     * 文档关闭时,写入总页数到模板
     */
    @Override
    public 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 随笔

相关推荐
int型码农5 分钟前
数据结构第八章(六)-置换选择排序和最佳归并树
java·c语言·数据结构·算法·排序算法
小道仙9726 分钟前
gitlab对接,gitlabRestApi,gitlab4j-api
java·git·gitlab
oioihoii1 小时前
C++11 GC Interface:从入门到精通
java·jvm·c++
九转编程蛊1 小时前
破解版idea安装Jira插件
java·ide·intellij-idea
ggdpzhk1 小时前
输入两个正整数,计算最大公约数和最小公倍数
java·算法
Luffe船长1 小时前
springboot将文件插入到指定路径文件夹,判断文件是否存在以及根据名称删除
java·spring boot·后端·spring
weixin_462176411 小时前
(三十一)深度解析领域特定语言(DSL)第六章——语法分析:递归下降语法分析器(Recursive-Descent Parser)
java·开发语言·软件构建
YuTaoShao1 小时前
Java八股文——数据结构「数据结构篇」
java·数据结构·面试·八股文
weixin_417249713 小时前
eps转pdf-2025年6月18日星期三
pdf
程序员清风3 小时前
RocketMQ发送消息默认是什么策略,主同步成功了就算成功了?异步写?还是要大部分从都同步了?
java·后端·面试