Java 生成各种 PDF 实战方案(图片、模板、表格)

这篇具有很好参考价值的文章主要介绍了Java 生成各种 PDF 实战方案(图片、模板、表格)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇文章的重点还是在讲通过java生成pdf,其实如果是单纯的模板填充挺简单的,但是又要填充模板还要动态生成表格就比较麻烦了,因为如果在模板中画表格的框去生成的话,超过模板框的位置就会隐藏,我刚接到需求的时候也是有点难受,在网上也是找了大量的资料,研究了半天,发现好多都是你粘贴我,我粘贴你,最终我也算是搞成了,把这些整合一下,让大家用的好用一些,废话不多说,直接上代码!

这里说一下啊,如果需要生成echarts图片,先去看我的生成echarts图片文章,不然这个搞不了。

模板链接,我把他放到网盘了,需要的可以去下载:

https://pan.baidu.com/s/1YJZtLdiySxUry4h2Gd1V7g 提取码:j1l5

一、pom依赖
首先先引入咱们需要的pom依赖,我这里只粘贴pdf的吧,lombok和hutool经常用我就不粘贴了。

com.itextpdf itextpdf 5.5.9 com.itextpdf itext-asian 5.2.0 二、生成pdf,模板和图片及动态生成表格 我这个没有搞页眉,只搞了页脚,设置页眉/页脚和水印的类我会在最后粘贴出来,因为这几个案例用的都是一个配置类。

实体类

package com.example.demo.domain;

import lombok.Data;
import lombok.experimental.Accessors;

import java.math.BigDecimal;

@Data
@Accessors(chain = true)
public class DuizhangDomain {
private String jg;
private Integer ydz;
private Integer wdz;
private BigDecimal dzl;
}
package com.example.demo.domain;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
@Data
@Accessors(chain = true)
public class YqTable implements Serializable {
private String jg;
private Integer yqs;
}
生成pdf代码

import cn.hutool.core.date.DateUtil;
import com.example.demo.domain.DuizhangDomain;
import com.example.demo.domain.YqTable;
import com.example.demo.pdf.phantom.App;
import com.example.demo.pdf.phantom.PageEvent;
import com.itextpdf.text.;
import com.itextpdf.text.pdf.
;
import freemarker.template.TemplateException;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**

  • 根据模板填充数据及图片,动态生成数据列表
    */
    public class CreatePdfEchrtsAndTableMain2 {

    private final static String TITLE = “这个是标题,可有可无”;
    public void createPdfFile(HttpServletResponse response) throws IOException, DocumentException, TemplateException {
    //设置请求返回类型
    response.setHeader(“Content-Disposition”, “attachment; filename=测试.pdf”);
    OutputStream outputStream = response.getOutputStream();
    //模板路径,放到项目里用这个ClassPathResource
    ClassPathResource classPathResource = new ClassPathResource(“templates/test1.pdf”);
    InputStream inputStream = classPathResource.getInputStream();

     PdfReader reader = new PdfReader(inputStream);
     ByteArrayOutputStream bos = new ByteArrayOutputStream();
     PdfStamper ps = new PdfStamper(reader, bos);
    
     //设置字体
     final BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
     ArrayList<BaseFont> fontList = new ArrayList<>();
     fontList.add(font);
    
     //提取表单,这个是模板画好的文本框
     AcroFields s = ps.getAcroFields();
     s.setSubstitutionFonts(fontList);
    
     s.setFieldProperty("jrfk","textfont",font,null);
     s.setFieldProperty("bjzs","textfont",font,null);
     s.setFieldProperty("type","textfont",font,null);
     s.setFieldProperty("createTime","textfont",font,null);
     s.setFieldProperty("title","textfont",font,null);
     s.setField("jrfk","10");
     s.setField("bjzs","20");
     s.setField("type","日报");
     s.setField("createTime", DateUtil.now());
     s.setField("title", TITLE);
    
    
    
     //添加图片
     PdfContentByte cb = ps.getOverContent(1);
     //添加logo
     Rectangle logo = s.getFieldPositions("logo").get(0).position;
     Image logoImage = Image.getInstance("https://img1.baidu.com/it/u=3646261857,3326755268&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?sec=1668186000&t=20050fc88fc3feb1f9d28392f4595ec6");
     //根据域的大小缩放图片,我这里宽度在原有的域基础上加了100,你们可以自己调节
     logoImage.scaleToFit(logo.getWidth() + 100,logo.getHeight());
     logoImage.setAlignment(Image.MIDDLE);
     logoImage.setAbsolutePosition(logo.getLeft(),logo.getBottom());
     cb.addImage(logoImage);
    
     //获取统计图
     //获取域
     Rectangle rlt = s.getFieldPositions("rlt").get(0).position;
     //热力图
     Image rltImage = Image.getInstance("https://img0.baidu.com/it/u=4043177345,1055141017&fm=253&app=138&size=w931&n=0&f=PNG&fmt=auto?sec=1668186000&t=8cfdc5c95cc0070eb91946d780ee8dc3");
     //根据域大小设置缩放图片
     rltImage.scaleToFit(rlt.getWidth() + 100,rlt.getHeight());
     // 设置居中
     rltImage.setAlignment(Image.MIDDLE);
     //绝对定位
     rltImage.setAbsolutePosition(rlt.getLeft(),rlt.getBottom());
     //图片旋转,这个可以将图片进行一个旋转,看自己需求
    

// rltImage.setRotationDegrees(90);
cb.addImage(rltImage);

    //按机构统计图
   //这个是生成echarts的类,如果需要生成echarts可以去看我的另一个文章,上面前言已经提到了
    App app1 = new App();
    byte[] echarts1 = app1.createEcharts("ajg.ftl");
    Image ajgImage = Image.getInstance(echarts1);
    Rectangle ajg = s.getFieldPositions("ajg").get(0).position;
    // 根据域大小设置缩放图片
    ajgImage.scaleToFit(ajg.getWidth(),400);
    // 设置居中
    ajgImage.setAlignment(Image.MIDDLE);
    // 绝对定位
    ajgImage.setAbsolutePosition(ajg.getLeft(),ajg.getBottom());
    cb.addImage(ajgImage);
    //按机构排名,这个是在图片的基础上还要添加数据,这个模板可以画好
    for (int i = 1; i <= 3; i++) {
        s.setFieldProperty("ajg" + i,"textfont",font,null);
        s.setField("ajg" + i,"机构" + i);
    }
    App app = new App();
    byte[] echarts = app.createEcharts("option.ftl");
    //按业务
    Rectangle ayw = s.getFieldPositions("ayw").get(0).position;
    Image aywImage = Image.getInstance(echarts);
    // 设根据域大小设置缩放图片
    aywImage.scaleToFit(ayw.getWidth(), 400);
    // 设置居中
    aywImage.setAlignment(Image.MIDDLE);
    // 绝对定位
    aywImage.setAbsolutePosition(ayw.getLeft(),ayw.getBottom());
    cb.addImage(aywImage);
    //按业务排名
    for (int i = 1; i <= 3; i++) {
        s.setFieldProperty("ayw" + i,"textfont",font,null);
        s.setField("ayw" + i,"机构" + i);
    }

    //按场合
    Rectangle acj = s.getFieldPositions("acj").get(0).position;
    Image acjImage = Image.getInstance(echarts);
    // 设根据域大小设置缩放图片
    acjImage.scaleToFit(acj.getWidth(), 400);
    // 设置居中
    acjImage.setAlignment(Image.MIDDLE);
    // 绝对定位
    acjImage.setAbsolutePosition(acj.getLeft(),acj.getBottom());
    cb.addImage(acjImage);
    //按场景排名
    for (int i = 1; i <= 3; i++) {
        s.setFieldProperty("acj" + i,"textfont",font,null);
        s.setField("acj" + i,"机构" + i);
    }

    //按等级
    Rectangle adj = s.getFieldPositions("adj").get(0).position;
    Image adjImage = Image.getInstance(echarts);
    // 设根据域大小设置缩放图片
    adjImage.scaleToFit(adj.getWidth(),400);
    // 设置居中
    adjImage.setAlignment(Image.MIDDLE);

    // 绝对定位
    adjImage.setAbsolutePosition(adj.getLeft(),adj.getBottom());
    cb.addImage(adjImage);
    //按场景排名
    for (int i = 1; i <= 3; i++) {
        s.setFieldProperty("adj" + i,"textfont",font,null);
        s.setField("adj" + i,"机构" + i);
    }
    ps.setFormFlattening(true);
    ps.close();

    //*******************填充编辑好后的pdf**************
    reader = new PdfReader(bos.toByteArray());
    Rectangle pageSize = reader.getPageSize(1);
    Document document = new Document(pageSize);
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);
    writer.setPageEvent(new PageEvent());
    // 打开文档
    document.open();
    PdfContentByte cbUnder = writer.getDirectContentUnder();
    PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
    cbUnder.addTemplate(pageTemplate, 0, 0);
    //重新开一页面
    document.newPage();
    createTable(writer,document);

// document.newPage();
createTableYq(writer,document);
document.close();
outputStream.close();
}

//为一个表格添加内容
public PdfPCell createSetCell(String value,Font font){
    PdfPCell cell = new PdfPCell();
    cell.setPhrase(new Phrase(value,font));
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
    return cell;
}


//添加表格
public void createTable(PdfWriter writer,Document document) throws DocumentException, IOException {

    PdfPTable table = new PdfPTable(new float[] { 30, 80, 50, 50, 50});
    table.setTotalWidth(520);
    table.setPaddingTop(500);
    table.setLockedWidth(true);
    table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
    table.writeSelectedRows(0, -1,500,800,writer.getDirectContentUnder());
    //每页都显示表头,输入几就是第几行的表头固定
    table.setHeaderRows(2);
    table.setHeaderRows(3);

    //定义数据的字体
    BaseFont baseFont = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
    Font textFont = new Font(baseFont, 10, Font.NORMAL);
    PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));

    cell.setHorizontalAlignment( Element.ALIGN_LEFT);

    cell.setVerticalAlignment(Element.ALIGN_BOTTOM);

    cell.setBorder(Rectangle.NO_BORDER);

    cell.setColspan(5);

    table.addCell(cell);

    //表头信息
    PdfPCell heandCell = new PdfPCell();
    heandCell.setRowspan(1);
    heandCell.setColspan(5);
    heandCell.setFixedHeight(60);
    heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    heandCell.setPhrase(new Phrase(TITLE + "对账情况表",textFont));
    table.addCell(heandCell);

    //表字段
    String title[] = {"序号","机构","已对账","未对账","对账率%"};
    for (int i = 0; i < title.length; i++) {
        PdfPCell heardCell = new PdfPCell();
        heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
        heardCell.setPhrase(new Phrase(title[i], textFont));
        heardCell.setMinimumHeight(20);
        table.addCell(heardCell);
    }

    //列表数据

    List<DuizhangDomain> duizhangDomains = new ArrayList<>();
    for (int i = 1; i <= 1000; i++) {
        DuizhangDomain duizhangDomain = new DuizhangDomain();
        duizhangDomain.setJg("机构" + i).setYdz(i).setWdz(i).setDzl(new BigDecimal(i));
        duizhangDomains.add(duizhangDomain);
    }

    for (int i = 0; i < duizhangDomains.size(); i++) {
        PdfPCell setCell1 = createSetCell((i + 1) + "", textFont);
        PdfPCell setCell2 = createSetCell(duizhangDomains.get(i).getJg(), textFont);
        PdfPCell setCell3 = createSetCell(duizhangDomains.get(i).getYdz().toString(), textFont);
        PdfPCell setCell4 = createSetCell(duizhangDomains.get(i).getWdz().toString(), textFont);
        PdfPCell setCell5 = createSetCell(duizhangDomains.get(i).getDzl() + "%", textFont);
        table.addCell(setCell1);
        table.addCell(setCell2);
        table.addCell(setCell3);
        table.addCell(setCell4);
        table.addCell(setCell5);
    }
    document.add(table);
}


public void createTableYq(PdfWriter writer,Document document) throws DocumentException, IOException {

    PdfPTable table = new PdfPTable(new float[] {80, 50});
    table.setTotalWidth(520);
    table.setPaddingTop(500);
    table.setLockedWidth(true);
    table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
    table.writeSelectedRows(0, -1,500,800,writer.getDirectContentUnder());
    //每页都显示表头,输入几就是第几行的表头固定
    table.setHeaderRows(2);
    table.setHeaderRows(3);

    //定义数据的字体
    BaseFont baseFont = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
    Font textFont = new Font(baseFont, 10, Font.NORMAL);
    
    //这个是为了区分两个表格加的一个间隔,可以去掉
    PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));
    cell.setHorizontalAlignment( Element.ALIGN_LEFT);
    cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
    cell.setBorder(Rectangle.NO_BORDER);
    cell.setColspan(2);
    table.addCell(cell);

    //表头信息
    PdfPCell heandCell = new PdfPCell();
    heandCell.setRowspan(1);
    heandCell.setColspan(2);
    heandCell.setFixedHeight(60);
    heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    heandCell.setPhrase(new Phrase(TITLE + "逾期表",textFont));
    table.addCell(heandCell);

    //表字段
    String title[] = {"机构名称","逾期数"};
    for (int i = 0; i < title.length; i++) {
        PdfPCell heardCell = new PdfPCell();
        heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
        heardCell.setPhrase(new Phrase(title[i], textFont));
        heardCell.setMinimumHeight(20);
        table.addCell(heardCell);
    }

    //列表数据

    List<YqTable> yqTables = new ArrayList<>();
    for (int i = 1; i <= 1000; i++) {
        YqTable yq = new YqTable();
        yq.setJg("逾期机构" + i).setYqs(i);
        yqTables.add(yq);
    }

    for (int i = 0; i < yqTables.size(); i++) {
        PdfPCell setCell2 = createSetCell(yqTables.get(i).getJg(), textFont);
        PdfPCell setCell3 = createSetCell(yqTables.get(i).getYqs().toString(), textFont);
        table.addCell(setCell2);
        table.addCell(setCell3);
    }
    document.add(table);
}

}
我说一下这个生成pdf需要注意的点,可能有的朋友很疑惑为什么要调用document.newPage(); 新开一页,这个是因为,如果你不新开一页的话会导致你动态生成的表格会跟模板内容重叠,注意是重叠而不是覆盖!!!

新开一页的话,就相当于我在第二页开始动态生成表格,这个时候可能有朋友就要问了,那如果我的模板没有占到一页怎么办,这样第一页岂不是会有空白,这个问题我也想到了,因为我的需求是生成好几种不同的pdf,下面我会把这种情况如何生成的代码放出来,我们先看一下第一种生成出来后的结果,我测的数据比较多,就粘几个结果好了。

生成结果示例

java 生成动态生成pdf,java,pdf,python

java 生成动态生成pdf,java,pdf,python

java 生成动态生成pdf,java,pdf,python

这就是结果!!!!基本上还可以

三、生成pdf,模板和动态表格
实体类都是一样的没有变。

生成pdf代码

package com.example.demo.pdf;

import cn.hutool.core.date.DateUtil;
import com.example.demo.domain.DuizhangDomain;
import com.example.demo.domain.YqTable;
import com.example.demo.pdf.phantom.PageEvent;
import com.itextpdf.text.;
import com.itextpdf.text.pdf.
;
import freemarker.template.TemplateException;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**

  • 模板第一页不占满,生成表格
    */
    public class CreatePdfEchrtsAndTableMain3 {

    public void createPdfFile(HttpServletResponse response) throws IOException, DocumentException, TemplateException {
    //设置请求返回类型
    response.setHeader(“Content-Disposition”, “attachment; filename=测试.pdf”);
    OutputStream outputStream = response.getOutputStream();
    //模板路径,放到项目里用这个ClassPathResource
    ClassPathResource classPathResource = new ClassPathResource(“templates/test3.pdf”);
    InputStream inputStream = classPathResource.getInputStream();

     PdfReader reader = new PdfReader(inputStream);
     ByteArrayOutputStream bos = new ByteArrayOutputStream();
     PdfStamper ps = new PdfStamper(reader, bos);
    
     //设置字体
     final BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
     ArrayList<BaseFont> fontList = new ArrayList<>();
     fontList.add(font);
    
     //提取表单
     AcroFields s = ps.getAcroFields();
     s.setSubstitutionFonts(fontList);
    
     s.setFieldProperty("type", "textfont", font, null);
     s.setFieldProperty("createTime", "textfont", font, null);
     s.setFieldProperty("title", "textfont", font, null);
     s.setField("type", "日报");
     s.setField("createTime", DateUtil.now());
     s.setField("title", "这是title,模板画的位置框");
     ps.setFormFlattening(true);
     ps.close();
    
     //*******************填充编辑好后的pdf**************
     reader = new PdfReader(bos.toByteArray());
     Rectangle pageSize = reader.getPageSize(1);
     Document document = new Document(pageSize);
     PdfWriter writer = PdfWriter.getInstance(document, outputStream);
     writer.setPageEvent(new PageEvent());
     // 打开文档
     document.open();
     PdfContentByte cbUnder = writer.getDirectContentUnder();
     PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
     cbUnder.addTemplate(pageTemplate, 0, 0);
     //添加间隙,这里为进行了一个封装,因为这个模板第一页只有一些title啥的,
     //重开一页太浪费,只需要确定表格要在什么位置生成,添加一个间隙就可以了
     createBlankTable(writer, document, font, 180);
    
     createTable(writer, document);
    
     createBlankTable(writer, document, font, 20);
     createTableYq(writer, document);
     document.close();
     outputStream.close();
    

    }

    //为一个表格添加内容
    public PdfPCell createSetCell(String value, Font font) {
    PdfPCell cell = new PdfPCell();
    cell.setPhrase(new Phrase(value, font));
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
    return cell;
    }

    //添加表格
    public void createTable(PdfWriter writer, Document document) throws DocumentException, IOException {

     PdfPTable table = new PdfPTable(new float[]{30, 80, 50, 50, 50});
     table.setTotalWidth(520);
     table.setPaddingTop(500);
     table.setLockedWidth(true);
     table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
     table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
     //每页都显示表头,输入几就是第几行的表头固定
     table.setHeaderRows(1);
     table.setHeaderRows(2);
    
     //定义数据的字体
     BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
     Font textFont = new Font(baseFont, 10, Font.NORMAL);
    
     //表头信息
     PdfPCell heandCell = new PdfPCell();
     heandCell.setRowspan(1);
     heandCell.setColspan(5);
     heandCell.setFixedHeight(30);
     heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
     heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
     heandCell.setPhrase(new Phrase("对账情况表", textFont));
     table.addCell(heandCell);
    
     //表字段
     String title[] = {"序号", "机构", "已对账", "未对账", "对账率%"};
     for (int i = 0; i < title.length; i++) {
         PdfPCell heardCell = new PdfPCell();
         heardCell.setRowspan(1);
         heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
         heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
         heardCell.setPhrase(new Phrase(title[i], textFont));
         heardCell.setMinimumHeight(20);
         table.addCell(heardCell);
    
     }
    
    
     //列表数据
    
     List<DuizhangDomain> duizhangDomains = new ArrayList<>();
     for (int i = 1; i <= 1000; i++) {
         DuizhangDomain duizhangDomain = new DuizhangDomain();
         duizhangDomain.setJg("机构" + i).setYdz(i).setWdz(i).setDzl(new BigDecimal(i));
         duizhangDomains.add(duizhangDomain);
     }
    
     for (int i = 0; i < duizhangDomains.size(); i++) {
         PdfPCell setCell1 = createSetCell((i + 1) + "", textFont);
         PdfPCell setCell2 = createSetCell(duizhangDomains.get(i).getJg(), textFont);
         PdfPCell setCell3 = createSetCell(duizhangDomains.get(i).getYdz().toString(), textFont);
         PdfPCell setCell4 = createSetCell(duizhangDomains.get(i).getWdz().toString(), textFont);
         PdfPCell setCell5 = createSetCell(duizhangDomains.get(i).getDzl() + "%", textFont);
         table.addCell(setCell1);
         table.addCell(setCell2);
         table.addCell(setCell3);
         table.addCell(setCell4);
         table.addCell(setCell5);
     }
     document.add(table);
    

    }

    public void createTableYq(PdfWriter writer, Document document) throws DocumentException, IOException {

     PdfPTable table = new PdfPTable(new float[]{80, 50});
     table.setTotalWidth(520);
     table.setPaddingTop(500);
     table.setLockedWidth(true);
     table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
     table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
     //每页都显示表头,输入几就是第几行的表头固定
     table.setHeaderRows(2);
     table.setHeaderRows(3);
    
     //定义数据的字体
     BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
     Font textFont = new Font(baseFont, 10, Font.NORMAL);
    
     //表头信息
     PdfPCell heandCell = new PdfPCell();
     heandCell.setRowspan(1);
     heandCell.setColspan(2);
     heandCell.setFixedHeight(30);
     heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
     heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
     heandCell.setPhrase(new Phrase("逾期表", textFont));
     table.addCell(heandCell);
    
     //表字段
     String title[] = {"机构名称", "逾期数"};
     for (int i = 0; i < title.length; i++) {
         PdfPCell heardCell = new PdfPCell();
         heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
         heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
         heardCell.setPhrase(new Phrase(title[i], textFont));
         heardCell.setMinimumHeight(20);
         table.addCell(heardCell);
     }
    
     //列表数据
    
     List<YqTable> yqTables = new ArrayList<>();
     for (int i = 1; i <= 1000; i++) {
         YqTable yq = new YqTable();
         yq.setJg("逾期机构" + i).setYqs(i);
         yqTables.add(yq);
     }
    
     for (int i = 0; i < yqTables.size(); i++) {
         PdfPCell setCell2 = createSetCell(yqTables.get(i).getJg(), textFont);
         PdfPCell setCell3 = createSetCell(yqTables.get(i).getYqs().toString(), textFont);
         table.addCell(setCell2);
         table.addCell(setCell3);
     }
     document.add(table);
    

    }

    /**

    • 创建表格跟表格之间的空白间隔
      */
      public void createBlankTable(PdfWriter writer, Document document, BaseFont font, int height) throws DocumentException {
      PdfPTable table = new PdfPTable(new float[]{30});
      table.setTotalWidth(520);
      table.setPaddingTop(500);
      table.setLockedWidth(true);
      table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
      table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
      Font textFont = new Font(font, 10, Font.NORMAL);
      PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));

      cell.setHorizontalAlignment(Element.ALIGN_LEFT);

      cell.setVerticalAlignment(Element.ALIGN_BOTTOM);

      cell.setBorder(Rectangle.NO_BORDER);
      cell.setFixedHeight(height);

      cell.setColspan(1);

      table.addCell(cell);
      document.add(table);
      }
      }
      这是第二种生成pdf的方法,生成的结果不一样,因为模板第一页没有太多的东西,所以会空出来很多空白,这个时候生成动态表格如果重开一页比较浪费,而且客户看着也不好看,所以我封装了一下生成间隙的方法,直接用间隙把模板内容和表格隔开即可,看一下效果。

生成结果示例

java 生成动态生成pdf,java,pdf,python

可以看到,我们在代码中并没有新开一页,只是加了一个间隙,就可以保证动态生成的表格和模板在一个页面,就此,基本上就算完成了。

页眉/页脚和水印类

package com.example.demo.pdf.phantom;

import com.itextpdf.text.;
import com.itextpdf.text.pdf.
;

import java.io.IOException;

public class PageEvent extends PdfPageEventHelper {
/**
* 页眉
*/
//public String header = “itext测试页眉”;

/**
 * 文档字体大小,页脚页眉最好和文本大小一致
 */
public int presentFontSize = 10;

/**
 * 文档页面大小,最好前面传入,否则默认为A4纸张
 */
public Rectangle pageSize = PageSize.A4;

// 模板
public PdfTemplate total;

// 基础字体对象
public BaseFont bf = null;

// 利用基础字体生成的字体对象,一般用于生成中文文字
public Font fontDetail = null;


/**
 *
 * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
 *
 */
public PageEvent() {

}

/**
 *
 * Creates a new instance of PdfReportM1HeaderFooter 构造方法.
 *
 * @param
 *
 * @param presentFontSize
 *            数据体字体大小
 * @param pageSize
 *            页面文档大小,A4,A5,A6横转翻转等Rectangle对象
 */

// public PDFBuilder(String yeMei, int presentFontSize, Rectangle pageSize) {
// this.header = yeMei;
// this.presentFontSize = presentFontSize;
// this.pageSize = pageSize;
// }
public PageEvent( int presentFontSize, Rectangle pageSize) {
this.presentFontSize = presentFontSize;
this.pageSize = pageSize;
}

// public void setHeader(String header) {
// this.header = header;
// }

public void setPresentFontSize(int presentFontSize) {
    this.presentFontSize = presentFontSize;
}


/**
 *
 * TODO 文档打开时创建模板
 *
 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter,
 *      com.itextpdf.text.Document)
 */
public void onOpenDocument(PdfWriter writer, Document document) {
    total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
}

/**
 *
 * TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
 *
 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter,
 *      com.itextpdf.text.Document)
 */
public void onEndPage(PdfWriter writer, Document document) {
    this.addPage(writer, document);
    //加水印
    this.addWatermark(writer);
}

//加分页
public void addPage(PdfWriter writer, Document document){
    //设置分页页眉页脚字体
    try {
        if (bf == null) {
            bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
        }
        if (fontDetail == null) {
            fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
        }
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    // 1.写入页眉

// ColumnText.showTextAligned(writer.getDirectContent(),
// Element.ALIGN_LEFT, new Phrase(header, fontDetail),
// document.left(), document.top() + 20, 0);
// 页眉添加图片
// String path = ResourceUtils.getFile(“classpath:”).getPath();
// Image img = Image.getInstance(path + “/pdfTemplates/logo.jpg”);
// img.setAlignment(Image.MIDDLE);
// img.setWidthPercentage(80);
// img.scaleToFit(50,40);
// img.setAbsolutePosition(document.left(),document.top());
// writer.getDirectContent().addImage(img);
//页眉加下划线
// PdfPTable tableHeader = new PdfPTable(1);
// tableHeader.setTotalWidth(PageSize.A4.getWidth() - 60);
// PdfPCell pCell = new PdfPCell();
// pCell.setBorderWidthBottom(0.3f);
// tableHeader.addCell(pCell);
// tableHeader.writeSelectedRows(0, -1, 30, 805, writer.getDirectContent());

    // 2.写入前半部分的 第 X页/共
    int pageS = writer.getPageNumber();
    String foot1 = "第 " + pageS + " 页 /共";

// String foot1 = pageS +“/”;
Phrase footer = new Phrase(foot1, fontDetail);

    // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len
    float len = bf.getWidthPoint(foot1, presentFontSize);

    // 4.拿到当前的PdfContentByte
    PdfContentByte cb = writer.getDirectContent();

    // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
    // 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了
    // ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。
    ColumnText
            .showTextAligned(
                    cb,
                    Element.ALIGN_CENTER,
                    footer,
                    (document.rightMargin() + document.right()
                            + document.leftMargin() - document.left() - len) / 2.0F ,
                    document.bottom() - 20, 0);

    // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F +
    // len , y 轴和之前的保持一致,底边界-20
    cb.addTemplate(total, (document.rightMargin() + document.right()
                    + document.leftMargin() - document.left()) / 2.0F ,
            document.bottom() - 20); // 调节模版显示的位置

}

//加水印
public void addWatermark(PdfWriter writer) {
    // 水印图片

// Image image;
// try {
// image = Image.getInstance(“./web/images/001.jpg”);
// PdfContentByte content = writer.getDirectContentUnder();
// content.beginText();
// // 开始写入水印
// for(int k=0;k<5;k++){
// for (int j = 0; j <4; j++) {
// image.setAbsolutePosition(150j,170k);
// content.addImage(image);
// }
// }
// content.endText();
// } catch (IOException | DocumentException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
BaseFont font = null;
try {
font = BaseFont.createFont(“STSong-Light”,“UniGB-UCS2-H”, BaseFont.NOT_EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
PdfGState gs = new PdfGState();
//添加透明度
gs.setFillOpacity(0.4f);
PdfContentByte content = writer.getDirectContentUnder();
content.beginText();
//水印颜色
content.setColorFill(BaseColor.DARK_GRAY);
content.setGState(gs);
//水印字体样式和大小
content.setFontAndSize(font, 35);
//插入水印 循环每页插入的条数
for (int j = 0; j < 3; j++) {
content.showTextAligned(Element.ALIGN_CENTER, “锦鲤飞上天测试水印”, 300, 200 * (j + 1), 30);
}
content.endText();
}

/**
 *
 * TODO 关闭文档时,替换模板,完成整个页眉页脚组件
 *
 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter,
 *      com.itextpdf.text.Document)
 */
public void onCloseDocument(PdfWriter writer, Document document) {
    // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
    total.beginText();
    total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
    String foot2 = " " + (writer.getPageNumber()) + " 页"; //页脚内容拼接  如  第1页/共2页

// String foot2 = String.valueOf(writer.getPageNumber()); //页脚内容拼接 如 1/2
total.showText(foot2);// 模版显示的内容
total.endText();
total.closePath();
}
}
好了这就是生成pdf的代码了,controller层我就不粘出来了自己搞一下吧,希望可以帮助各位有需要的人,如果帮助到你了就帮忙点个赞,关注一下,我会不定时更新一些自己解决过的业务,希望可以帮助大家!!!文章来源地址https://www.toymoban.com/news/detail-781497.html

到了这里,关于Java 生成各种 PDF 实战方案(图片、模板、表格)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java-根据模板生成PDF

    在有些场景下我们可能需要根据指定的模板来生成 PDF,比如说合同、收据、发票等等。因为 PDF 是不可编辑的,所以用代码直接对 PDF 文件进行修改是很不方便的,这里我是通过 itext 和 Adobe Acrobat 来实现的,以下就是具体实现方法。 Adobe Acrobat 是由 Adobe 公司开发的一款 PDF (

    2024年02月04日
    浏览(41)
  • 如何通过Java的Apache PDFBox库制作一个PDF表格模板并填充数据

    要使用Java的Apache PDFBox库制作一个PDF表格模板并填充数据,你需要遵循以下步骤: 添加依赖 :首先,确保你的项目中包含了Apache PDFBox的依赖。如果你使用Maven,可以在你的 pom.xml 文件中添加以下依赖: 创建PDF模板 :你可以使用PDFBox创建一个简单的PDF模板,或者使用其他工具

    2024年02月22日
    浏览(46)
  • java JFreeChart 绘制各种图形 并使用itextPdf生成PDF导出

    参考: https://blog.csdn.net/hfy1237/article/details/126693786 https://blog.csdn.net/qq_39149275/article/details/119381389

    2024年01月19日
    浏览(32)
  • 【生成PDF】【JAVA】纯后台生成Echarts图片,并将图片生成到PDF文档

    目录 前言 一、如何后台生成Echarts图片? 1.PhantomJS 2.PhantomJS的下载  3.用phantomjs调用echarts-converts.js生成图片 二、Java如何将Echarts图生成到PDF 1.生成PDF依赖 2.Java代码测试例子:  3.测试结果   三、下载生成的PDF ReportFormUtil 提示:本文仅用于记录日常,多有不足,仅供参考。

    2024年02月09日
    浏览(34)
  • Java-模板生成PDF方式3-HtmlToPDF

    使用thymeleaf做html模板,由xhtmlrenderer/flying-saucer-pdf-openpdf将html转为PDF LGPL 和 MPL 许可 pom.xml引入依赖 yml增加配置 工具类转换 HTML模板 applying_for_volunteer_service_form_html.html 资源 字体 src/main/resources/fonts/simhei.ttf 源码地址 https://gitee.com/cocoxike/pdfdemo.git 效果图 问题 1.中文显示 方法中加

    2024年02月08日
    浏览(23)
  • java生成pdf表格并支持下载可选另存为

    直接复制以上代码即可完成,但是也要引入一些依赖 引入以后修修补补增增改改就可以了

    2024年02月10日
    浏览(34)
  • java集成itextpdf实现通过pdf模板填充数据生成pdf

    我采用的是pdfelement 官网地址需要付费或者自行破解,也可以使用其他pdf编辑器。 将制作好的pdf模板放入项目resources/pdf目录下,如图 浏览器访问ip:port/test/pdf,其中ip为你的ip地址,port为你的端口,访问结果如下:

    2024年02月16日
    浏览(28)
  • JAVA之利用easypoi将word模板导出为pdf(可带图片)

    EasyPoi是一款基于POI的Java快速导出/导入Excel工具。它在POI的基础上进行了封装,提供了更加简洁易用的API,使得生成Excel文件更加容易和高效。 使用EasyPoi可以轻松地生成Excel文件,并支持多种格式,如xlsx、xls、csv等。同时,EasyPoi也支持读取Excel文件,可以方便地获取其中的数

    2024年02月08日
    浏览(39)
  • Java根据word模板生成word文档并转成PDF文件

    定义完我们的模板之后,我们要将文档保存为xml的格式 生成的xml格式看起来比较乱,没有层次感, 所以需要格式化一下 格式化 基础信息的定义 基础信息的定义只要保证我们转化成的xml文件中的${name}等格式没错误即可 表格的定义 遍历实现,表格的数据填充 在xml文件中我们的

    2024年02月09日
    浏览(43)
  • Java 生成 PDF 文档方案整理

    最近项目需要实现PDF下载的功能,由于没有这方面的经验,从网上花了很长时间才找到相关的资料。整理之后,发现有如下几个框架可以实现这个功能。 1. 开源框架支持 iText,生成PDF文档,还支持将XML、Html文件转化为PDF文件; Apache PDFBox,生成、合并PDF文档; docx4j,生成d

    2024年02月01日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包