如何使用Java生成pdf报告

文章目录

这篇主要说一下如何使用Java生成pdf,包括标题,文字,图片,表格的插入和调整等相关内容。

一、环境准备与Maven依赖说明

这里我使用的是iTextPDF,依次添加下面的依赖

核心依赖说明:

xml 复制代码
        <!-- pdf:start -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
        <!-- 支持中文 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- 支持css样式渲染 -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-itext5</artifactId>
            <version>9.1.16</version>
        </dependency>
        <!-- 转换html为标准xhtml包 -->
        <dependency>
            <groupId>net.sf.jtidy</groupId>
            <artifactId>jtidy</artifactId>
            <version>r938</version>
        </dependency>


        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.3</version>
        </dependency>

        <!-- Jetty WebSocket支持 -->
        <dependency>
            <groupId>org.eclipse.jetty.websocket</groupId>
            <artifactId>javax-websocket-server-impl</artifactId>
            <version>9.4.44.v20210927</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>9.4.44.v20210927</version>
        </dependency>

        <!-- Apache HttpClient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

二、核心代码解析

1. 基础文档创建

文档的创建:

java 复制代码
// 创建A4文档,设置页边距(左、右、上、下)
Document document = new Document(PageSize.A4, 40, 40, 40, 40);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);

// 必须显式打开文档
document.open();
2. 中文字体处理

字体调整:

java 复制代码
// 使用内置STSong-Light字体
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font bodyFont = new Font(bf, 12);

// 推荐做法:使用外部字体文件
BaseFont externalFont = BaseFont.createFont("fonts/SourceHanSansCN-Regular.ttf", 
                                          BaseFont.IDENTITY_H, 
                                          BaseFont.EMBEDDED);
3. 复杂表格创建

表格创建:

java 复制代码
// 创建5列表格,设置列宽比例
float[] colWidths = {2f, 1.5f, 1.5f, 1.5f, 1.5f};
PdfPTable table = new PdfPTable(colWidths);

// 设置表格占页面宽度的100%
table.setWidthPercentage(100);

// 添加表头
addTableHeader(table, new String[]{"指标", "Q1", "Q2", "Q3", "Q4"}, headerFont);

// 添加数据行
addTableRow(table, new String[]{"响应时间(ms)", "230", "180", "150", "120"}, bodyFont);
4. 图片插入

插入本地图片:

java 复制代码
// 推荐使用相对路径
String imagePath = "src/main/resources/charts/tech_trend.png";

// 自动缩放适应宽度
Image image = Image.getInstance(imagePath);
image.scaleToFit(document.getPageSize().getWidth() - 80, Float.MAX_VALUE);
image.setAlignment(Image.ALIGN_CENTER);

// 添加图片描述
Paragraph caption = new Paragraph("图1 2023年季度性能趋势对比", captionFont);
caption.setAlignment(Element.ALIGN_CENTER);
document.add(caption);
document.add(image);

三、完整代码示例

下面是完整的代码示例,可以直接调整使用

java 复制代码
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.ruoyi.RuoYiApplication;
import com.ruoyi.common.utils.http.HttpUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.*;
import java.text.ParseException;


@RunWith(SpringRunner.class)
@SpringBootTest(classes= RuoYiApplication.class)
public class pdfDemoTest5 {


    /**
     * PDF生成- 公司年度技术报告
     */
    @Test
    public void generateDemoPdf() throws Exception {
        // 文档设置(调整页边距)
        Document document = new Document(PageSize.A4, 40, 40, 40, 40);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("tech_report_demo.pdf"));

        // 创建中文字体
        BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

        // 定义字体样式
        Font redTitleFont = new Font(bf, 20, Font.BOLD, BaseColor.RED);
        Font programFont = new Font(bf, 16, Font.BOLD);
        Font sectionFont = new Font(bf, 14, Font.BOLD);
        Font bodyFont = new Font(bf, 12);
        Font tableHeaderFont = new Font(bf, 12, Font.BOLD);
        Font contactFont = new Font(bf, 11, Font.BOLD);

        document.open();

        // ========== 标题区块 ==========
        Paragraph program = new Paragraph();
        program.add(new Chunk("2023年度技术发展报告\n", programFont));
        program.add(new Chunk("科技创新与数字化转型", programFont));
        program.setAlignment(Element.ALIGN_CENTER);
        program.setSpacingAfter(15f);
        document.add(program);

        // 红色主标题(带下划线)
        Paragraph mainTitle = new Paragraph("技术研发中心年度报告", redTitleFont);
        mainTitle.setAlignment(Element.ALIGN_CENTER);
        mainTitle.setSpacingAfter(10f);
        document.add(mainTitle);

        // ========== 期号信息 ==========
        Paragraph issue = new Paragraph();
        issue.add(new Chunk("[2023]年度报告", bodyFont));
        issue.add(new Chunk("                                   ", bodyFont)); // 空格占位
        issue.add(new Chunk("发布日期:[2024]年[1]月[15]日", bodyFont));
        issue.setAlignment(Element.ALIGN_RIGHT);
        document.add(issue);

        // 添加下划线效果
        Chunk underline = new Chunk(new LineSeparator(1.5f, 100f, BaseColor.RED, Element.ALIGN_CENTER, -1));
        document.add(underline);

        // ========== 报告标题 ==========
        Paragraph reportTitle = new Paragraph(
                "2023年度技术研发成果与2024年展望",
                sectionFont);
        reportTitle.setAlignment(Element.ALIGN_CENTER);
        reportTitle.setSpacingBefore(15f);
        reportTitle.setSpacingAfter(20f);
        document.add(reportTitle);

        // ========== 正文内容 ==========
        // 年度总结部分
        addSection(document, "1. 年度技术成果总结", sectionFont,
                "2023年,我司在人工智能、大数据分析和云计算领域取得了显著进展。主要成果包括完成了新一代智能分析平台的开发,实现了数据处理效率提升300%;发布了基于机器学习的预测模型,准确率达到行业领先水平;完成了核心系统的云原生改造,系统稳定性提升至99.99%。", bodyFont);

        // 技术指标部分
        addSection(document, "2. 关键技术指标", sectionFont, "", bodyFont);

        // 表格样式优化
        float[] colWidths = {2f, 1.5f, 1.5f, 1.5f, 1.5f};

        // 创建表格标题
        Paragraph tableCaption = new Paragraph("表1 2023年关键技术指标对比", bodyFont);
        tableCaption.setAlignment(Element.ALIGN_CENTER);
        tableCaption.setSpacingBefore(10f);
        tableCaption.setSpacingAfter(5f);
        document.add(tableCaption);

        // 创建表格
        createComparisonTable(document,
                new String[]{"系统响应时间(ms)", "230", "180", "150", "120"},
                new String[]{"数据处理量(TB/天)", "5.2", "8.7", "12.4", "15.8"},
                colWidths, tableHeaderFont, bodyFont);

        // ========== 技术趋势图 ==========
        Paragraph imageParagraph = new Paragraph();
        imageParagraph.setSpacingBefore(20f);
        imageParagraph.add(new Chunk("图1 2023年技术发展趋势", bodyFont));
        imageParagraph.setAlignment(Element.ALIGN_CENTER);
        document.add(imageParagraph);

        // 插入本地图片(示例)
        String localImagePath = "D:\\test.jpg";
        Image localImage = Image.getInstance(localImagePath);
        localImage.scaleToFit(400, 250);
        localImage.setAlignment(Image.ALIGN_CENTER);
        document.add(localImage);

        // ========== 未来展望 ==========
        addSection(document, "3. 2024年技术发展规划", sectionFont,
                "2024年,我们将重点布局以下领域:\n\n" +
                        "• 人工智能:深化自然语言处理技术应用\n" +
                        "• 边缘计算:构建分布式计算网络\n" +
                        "• 数据安全:实施零信任安全架构\n" +
                        "• 云原生:全面容器化改造\n\n" +
                        "预计2024年研发投入将增长30%,重点培养高端技术人才50名。", bodyFont);

        // ========== 联系方式 ==========
        Paragraph contacts = new Paragraph();
        contacts.add(new Chunk("技术咨询:", contactFont));
        contacts.add(new Chunk(" 400-123-4567   ", bodyFont));
        contacts.add(new Chunk("电子邮箱:", contactFont));
        contacts.add(new Chunk("tech@company.com\n", bodyFont));
        contacts.add(new Chunk("公司地址:", contactFont));
        contacts.add(new Chunk("北京市海淀区科技园区88号 创新大厦B座", bodyFont));
        contacts.setSpacingBefore(20f);
        document.add(contacts);

        document.close();
    }

    // 辅助方法:添加章节
    private void addSection(Document doc, String title, Font titleFont, String content, Font bodyFont) {
        try {
            Paragraph section = new Paragraph(title, titleFont);
            section.setSpacingBefore(15f);
            doc.add(section);

            if(!content.isEmpty()) {
                Paragraph text = new Paragraph(content, bodyFont);
                text.setSpacingAfter(15f);
                doc.add(text);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:创建对比表格
    private void createComparisonTable(Document doc,
                                       String[] row1, String[] row2,
                                       float[] colWidths, Font headerFont, Font bodyFont) {
        try {
            PdfPTable table = new PdfPTable(colWidths);
            table.setWidthPercentage(100);
            table.setSpacingBefore(0f); // 标题与表格的间距由外部控制
            table.setSpacingAfter(15f);

            // 表头
            addTableHeader(table, new String[]{"省份", "河南省", "河北省", "山东省", "江苏省", "安徽省"}, headerFont);

            // 数据行
            addTableRow(table, row1, bodyFont);
            addTableRow(table, row2, bodyFont);

            doc.add(table);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法:添加表头
    private void addTableHeader(PdfPTable table, String[] headers, Font font) {
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Paragraph(header, font));
            cell.setBackgroundColor(new BaseColor(240, 240, 240));
            cell.setPadding(5);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(cell);
        }
    }

    // 辅助方法:添加表格行
    private void addTableRow(PdfPTable table, String[] data, Font font) {
        for (String item : data) {
            PdfPCell cell = new PdfPCell(new Paragraph(item, font));
            cell.setPadding(5);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(cell);
        }
    }





}

四、最终效果

这个就是上面代码生成的最终的pdf的效果图

相关推荐
缺点内向2 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅2 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看4 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程4 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t4 小时前
ZIP工具类
java·zip
lang201509284 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan5 小时前
第10章 Maven
java·maven
百锦再6 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说6 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多6 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring