itextpdf 7生成pdf(主要是文字和表格,支持中文)

news2024/12/26 22:35:07

我们经常会遇到要导出pdf的需求,方式有很多种 今天的教程是采用itextpdf的方式生成pdf
itextpdf是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF文档,而且可以将Html文件转化为PDF文件。

这里先展示一下效果图
测试pdf效果图

首先在pom.xml中引入相关依赖

<dependencys>
	<!-- itext7 -->
	<dependency>
	    <groupId>com.itextpdf</groupId>
	    <artifactId>itext7-core</artifactId>
	    <version>7.2.1</version>
	    <type>pom</type>
	</dependency>
	<dependency>
	    <groupId>com.itextpdf</groupId>
	    <artifactId>pdftest</artifactId>
	    <version>7.1.16</version>
	    <scope>test</scope>
	</dependency>
</dependencys>

PdfUtil 工具类

创建pdf、获取字体
如果需要添加水印,可以自行修改对应的图片路径(static/logo.png)
其中用到的字体文件在这里下载

package com.***.utils.pdf;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.properties.VerticalAlignment;

import java.io.FileNotFoundException;
import java.io.IOException;

public class PdfUtil {

    static final String LOGO_TEXT = "";

    /**
     * 给pdf 添加水印
     *
     * @param doc Document 对象
     * @throws Exception
     */
    public static void generateWatermark(Document doc) throws Exception {
//        PdfDocument pdfDoc = new PdfDocument(new PdfReader(fis), new PdfWriter(fos));
//        Document doc = new Document(pdfDoc);
//        PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");

        PdfDocument pdfDoc = doc.getPdfDocument();
        // 将字体包拖到路径下
        PdfFont pdfFont = getZhFont();
        Paragraph paragraph = new Paragraph(LOGO_TEXT).setFont(pdfFont).setFontSize(14);
        ImageData img = ImageDataFactory.create(PdfUtil.class.getClassLoader().getResource("static/logo.png"));
        float w = img.getWidth();
        float h = img.getHeight();
        PdfExtGState gs1 = new PdfExtGState().setFillOpacity(0.1f);
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            pdfPage.setIgnorePageRotationForContent(true);
            PdfCanvas over = new PdfCanvas(pdfDoc.getPage(i));
            over.saveState();
            over.setExtGState(gs1);
            float x = pageSize.getX();
            float y = pageSize.getY();
            float pageWidth = pageSize.getWidth();
            float pageHeight = pageSize.getHeight();
            while (y < pageHeight) {
                if (y == 0) y = y + 10;
                while (x < pageWidth) {
//                    if(x==0) x = x+48;
                    if (x == 0) x = x + 68;
                    over.addImageWithTransformationMatrix(img, w / 2, 0, 0, h / 2, x, y, false);
//                    doc.showTextAligned(paragraph, x+32, y+38, i, TextAlignment.LEFT, VerticalAlignment.TOP, 0.3f);
                    x = x + 180;
                }
                x = pageSize.getX();
                y = y + 120;
            }
            over.restoreState();
        }
//        doc.close();
    }

    /**
     * 获取中文字体
     *
     * @return
     * @throws IOException
     */
    public static PdfFont getZhFont() throws IOException {
        return PdfFontFactory.createFont(PdfUtil.class.getClassLoader().getResource("static/msyh.ttf").toString(),
                PdfEncodings.IDENTITY_H);
    }


    /**
     * 获得一个 PDF table cell
     *
     * @param txt text
     * @param v   最大宽度百分比
     * @return
     */
    public static Cell newPdfCell(String txt, float v) {
        return new Cell().add(
                new Paragraph(txt).setTextAlignment(TextAlignment.CENTER))
                .setVerticalAlignment(VerticalAlignment.MIDDLE)
                .setMaxWidth(UnitValue.createPercentValue(v)
        );
    }

    /**
     * 新建 pdfDoc
     *
     * @param pdfPath  pdfPath
     * @param fileName 文件名
     * @return
     * @throws FileNotFoundException
     */
    public static Document newPdfDoc(String pdfPath, String fileName) throws FileNotFoundException {
        String filePath = pdfPath + fileName;
        // pdf加密
        // PdfWriter writer = new PdfWriter(filePath, new WriterProperties().setStandardEncryption(null, "Hz123456".getBytes(), EncryptionConstants.ALLOW_SCREENREADERS,
        //         EncryptionConstants.ENCRYPTION_AES_128));
        PdfWriter writer = new PdfWriter(filePath);
        PdfDocument pdf = new PdfDocument(writer);
        pdf.setDefaultPageSize(PageSize.A4);
        return new Document(pdf);
    }

}

TableBuilder 工具类

用于构建pdf中用到的表格

package com.***.pdf;

import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.properties.VerticalAlignment;
import lombok.Data;

import java.util.List;

@Data
public class TableBuilder {
    /**
     * pdf表格对象
     */
    Table table;
    /**
     * 表格列数
     */
    Integer column;
    /**
     * 每列宽度百分比
     */
    Float columnWidthPercent;

    /**
     * 创建表格
     *
     * @param column  列数
     * @param pdfFont 字体
     * @return
     */
    public static TableBuilder builder(int column, PdfFont pdfFont) {
        TableBuilder tableBuilder = new TableBuilder();
        tableBuilder.setColumn(column);
        tableBuilder.setColumnWidthPercent(100f / column);
        float[] values = new float[column];
        for (int i = 0; i < column; i++) {
            values[i] = 3;
        }
        Table table = new Table(UnitValue.createPercentArray(values))
        		// 这里是设置表格占整个pdf的宽度百分比,这里设置的是100%
                .setWidth(UnitValue.createPercentValue(100))
                .setTextAlignment(TextAlignment.CENTER)
                .setVerticalAlignment(VerticalAlignment.MIDDLE)
                // 设置字体
                .setFont(pdfFont)
                // 设置字体大小
                .setFontSize(10);
        tableBuilder.setTable(table);
        return tableBuilder;
    }

    // 这里添加数据时,需要注意,每一行的数据个数必须与表格列数一致,单元格无数据时,添加空字符串
    /**
     * 添加一行数据
     * @param row 一行数据
     * @return
     */
    public TableBuilder addRow(List<String> row) {
        for (String item : row) {
            this.table.addCell(PdfUtil.newPdfCell(item, this.columnWidthPercent));
        }
        return this;
    }

    /**
     * 添加多行数据
     * @param rowList 多行数据
     * @return
     */
    public TableBuilder addRows(List<List<String>> rowList) {
        for (List<String> row : rowList) {
            this.addRow(row);
        }
        return this;
    }

    /**
     * 获取表格对象
     * @return
     */
    public Table build() {
        return this.table;
    }

}

使用以上工具类构建一个测试的pdf,测试pdf效果在文章开头查看

package com.***;

import com.***.utils.pdf.PdfUtil;
import com.***.utils.pdf.TableBuilder;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Div;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.UnitValue;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class PdfTest {

    @Test
    public void testPdf() throws IOException {
        Document document = PdfUtil.newPdfDoc("/Desktop/", "test.pdf");
        // 这里的字体对象一个pdf用一次,不能重复(多个pdf)使用,否则会报错
        PdfFont pdfFont = PdfUtil.getZhFont();
        Div head1Div = new Div().setWidth(UnitValue.createPercentValue(100))
                .setHeight(UnitValue.createPercentValue(100))
                .setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 标题,22号字体,居中对齐,加粗
        Paragraph title = new Paragraph("测试pdf标题")
                .setFont(pdfFont).setFontSize(22).setHorizontalAlignment(HorizontalAlignment.CENTER)
                .setTextAlignment(TextAlignment.CENTER).setBold();
        head1Div.add(title);
        head1Div.add(
                new Paragraph("一、第一部分:测试表格")
                        .setFont(pdfFont).setFontSize(16).setBold()
        );
        List<String> header = Arrays.asList("姓名", "年龄", "性别", "手机号", "邮箱", "地址", "职业", "备注");
        List<List<String>> data = Arrays.asList(
                Arrays.asList("张三", "25", "男", "13812345678", "zhangsan@qq.com", "北京市海淀区", "学生", "无"),
                Arrays.asList("王五", "28", "男", "13812345680", "wangwu@qq.com", "广东省深圳市", "律师", "无")
        );
        // 表格,8列,字体为pdfFont
        Table table = TableBuilder.builder(8, pdfFont)
                .addRow(header).addRows(data).build();
        head1Div.add(table);
        document.add(head1Div);
        document.close();
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1663871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

目标检测——道路检测数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

K8S搭建

文章目录 K8S搭建配置要求 安装 Kuboard-Spray加载离线资源包规划并安装集群访问集群重启Kubernetes集群Worker节点不能启动许多Pod一直Crash或不能正常访问 containerd配置网络代理 常用的 kubectl 命令&#xff1a; K8S搭建 安装高可用的Kubernetes集群 配置要求 对于 Kub…

PG 检查点管理与Oracle的比较

之前介绍过&#xff0c;在任何数据库中&#xff0c;一条DML操作执行都需要在内存中执行&#xff0c;但当操作越来越多&#xff0c;总有时候内存会写满&#xff0c;这时候就需要把内存中的块写入到磁盘&#xff0c;释放内存&#xff0c;保存数据。 写入到磁盘这一步&#xff0c;…

基于 Satchmo 实现自定义捐款模块

1、问题背景 我在 Satchmo 中构建捐款模块时遇到了一些困难。我可以自定义 Satchmo 的产品模型&#xff0c;但无法找到任何与捐赠相关的内容。 我知道可以创建一个捐赠虚拟产品&#xff0c;但据我所知&#xff0c;这仍然需要预先设定金额&#xff08;例如 5 美元、10 美元等&…

Java并发处理

Java并发处理 问题描述:项目中业务编号出现重复编号 生成编号规则&#xff1a;获取数据库表最大值&#xff0c;然后再做1处理&#xff0c;即为新编号&#xff08;因为起始值是不固定的&#xff0c;还存在‘字符数据’格式&#xff0c;做了字典项可配置&#xff0c;所以不能直…

03、SpringBoot 源码分析 - SpringApplication启动流程三

SpringBoot 源码分析 - SpringApplication启动流程三 初始化基本流程SpringApplication的setListeners设置监听器deduceMainApplicationClass对端主启动类rungetRunListeners获取SpringApplicationRunListener监听器EventPublishingRunListener的构造方法SimpleApplicationEven…

js 数据格式转换,对象转数组,数组转对象

1.对象转数组 // 对象obj转换成数组格式 let obj { orgCode:分局编码, alertId:告警ID, name:告警名称 } let arr [] for(let key in obj) { console.log(11,key,obj[key]); // 定义一个对象&#xff0c;赋值 let o { id: key, // key是obj对象的键值 label: obj[key] …

LeetCode-2391. 收集垃圾的最少总时间【数组 字符串 前缀和】

LeetCode-2391. 收集垃圾的最少总时间【数组 字符串 前缀和】 题目描述&#xff1a;解题思路一&#xff1a;处理垃圾和路程单独计算。解题思路二&#xff1a;逆向思维&#xff0c;计算多走的路解题思路三&#xff1a;只记录&#xff0c;当前t需要计算几次 题目描述&#xff1a;…

Qt---窗口系统

一、QMainWindow 1. 菜单栏(最多有一个) QMenuBar *bar MenuBar(); SetMenuBar(bar); QMenu *fileMenu bar->addMenu("文件"); 创建菜单 QAction *newAction fileMenu->addAction("新建"); 创建菜单项 添加分割线fileMenu-…

如何使用联合体判断一个机器是大端还是小端

如何使用联合体判断一个机器是大端还是小端 #include<iostream> using namespace std; union Checker//联合体中的数据共享内存 {int val;char ch[2]; }; int main() {Checker checker;checker.val 0x1234;if (checker.ch[0] 0x34)//数组中的数据是由低地址往高地址存放…

构建NFS远程共享存储

nfs-server:10.1.59.237 nfs-web:10..159.218 centos7,服务端和客户端都关闭防火墙和selinux内核防火墙&#xff0c;如果公司要求开启防火墙&#xff0c;那需要放行几个端口 firewall-cmd --add-port2049/tcp --permanent firewall-cmd --add-port111/tcp --permanent firew…

yum、rpm相关命令-工具手册

1.rpm文件: 1.1安装rpm文件: rpm -ivh kde-select.rpm23 #--nodeps强制安装,无视环境缺少依赖的检查 rpm -ivh --nodeps kde-select.rpm #--force --replacefiles可以无视rpm的冲突去强制替换(如两个rpm的安装路径相同了会有冲突) rpm -ivh --nodeps --force --replacef…

空间复杂度与链表刷题

"一切的一切都是你自己在感应." 本文索引 空间复杂度复杂度实例实例1实例2实例3 链表题目1. 返回倒数第K个节点2. 链表的回文结构3. 相交链表4. 随机链表的复制5. 环形链表 总结: 前言: 本文主要探究空间复杂度与链表题目讲解 更多文章点击主页: 酷酷学!!! 如果此文对…

IDEA安装通义灵码(太好用了)

一、什么是通义灵码 1、 介绍 通义灵码&#xff0c;是阿里云出品的一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云 SDK/Op…

带你了解|大数据信用报告隔多久查一次比较好?

随着大数据技术的不断发展&#xff0c;大数据信用报告已经成为人们了解个人信用状况的重要途径之一。然而&#xff0c;对于隔多久查一次大数据信用报告比较好&#xff0c;却是一个需要认真考虑的问题&#xff0c;本文通过分析不同场景对大数据信用查询的需求进行介绍&#xff0…

新加坡首届ChatGPT-4提示词大赛冠军竟是华裔!

就是前几天&#xff0c;新加坡举办了首届ChatGPT-4的prompt比赛&#xff0c;没想到本次比赛的冠军竟然是我们华夏子民&#xff01; 这个冠军得主名叫张希拉。 她推出的一套名为CO-STAR的提示词框架 如何应用 CO-STAR 框架&#xff1a; (C) 上下文&#xff1a;为任务提供背景信…

一起长锈:3 类型安全的Rust宏(从Java与C++转Rust之旅)

讲动人的故事,写懂人的代码 故事梗概:在她所维护的老旧Java系统即将被淘汰的危机边缘,这位在编程中总想快速完事的女程序员,希望能转岗到公司内部使用Rust语言的新项目组,因此开始自学Rust;然而,在掌握了Rust编程知识之后,为了通过Rust项目组的技术面试,使得转岗成功而…

实现桌面动态壁纸——认识 WebView2 控件

目录 前言 一、什么是 WebView2 &#xff1f; 二、使用示例存储库 2.1 下载存储库 2.2 编译解决方案项目文件 2.3 运行示例程序 三、如何修改 WebView2 示例 本文来源于&#xff1a;https://blog.csdn.net/qq_59075481/article/details/138637909。 前言 上一节我们讲…

指针的奥秘(三):数组指针+函数指针(+typedef)+函数数组指针+转移表

指针 一.数组指针1.数组指针变量是什么&#xff1f;2.指针数组和数组指针区别和口诀3.数组指针变量怎么初始化4.二维数组传参的本质 二.函数指针1.函数指针变量的创建2.函数指针变量的使用3.两段有趣的代码1.( *( void ( * )( ) )0 ) ( );2.void( *signle(int, void( * )(int) …

小程序开发平台源码系统 低成本助力中小企业建站 带完整的安装代码包以及搭建教程

在当今数字化时代&#xff0c;拥有一个功能齐全、界面美观的小程序对于中小企业来说至关重要。然而&#xff0c;高昂的开发成本和复杂的搭建流程往往成为制约中小企业建立小程序的瓶颈。小编给大家分享一款低成本、易用性强的小程序开发平台源码系统&#xff0c;旨在助力中小企…