Acrobat与Itextpdf的搭配使用-根据模板填充PDF

本文介绍了如何通过Acrobat Pro和iTextPDF库操作PDF,包括文本域、单选/复选框、图片域、条形码、二维码和二维条码的使用。还涵盖了如何根据模板动态生成PDF,以及页码确定和不确定的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【一、准备工具】

1、首先安装好acrobat pro,这里提供一个绿色版的

Acrobat Pro 2020绿色版https://pan.baidu.com/s/1zftc5qH0cKd98yio9J6jKA?pwd=2n2d

2、acrobat的初步使用

        

         先将一个自定义的word模板转成pdf,然后在“更多工具”里找到并选中“准备表单”。上图的"TextField"为表单框的字段域名,之后将在代码里作为变量赋值使用。

        最为常用的有:文本域、复选框、单选框、图片框,参见上图圈红部分。

3、acrobat的一些细节用法

        在编辑框的属性中可以进行一些细节设置。

>>>文本框

图3-1图3-2
文本最终展示方向勾选“多行”后,有内容在一行展示不下时,自动换行,但字体不会自动调节

>>>单选框

        可以调节按钮展示的样式,及设置选中值,选中值将在代码里赋值使用

 >>>复选框

        同单选框操作。

 【二、代码使用环境】

1、maven引入

## itextpdf创建编辑pdf

itext-asian为字体库,这里可能会遇到导包问题,参见

(5条消息) itext生成PDF文件报错“Font 'STSong-Light' with 'UniGB-UCS2-H' is not recognized.”_bisal的专栏-CSDN博客https://bisal.blog.csdn.net/article/details/48021867?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2.pc_relevant_default

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.2</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

## pdf转图片(非必要)

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>2.0.24</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.24</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>jbig2-imageio</artifactId>
    <version>3.0.3</version>
</dependency>

【三、模块分析】

1、文本域实现的功能有:

## 文本框

/**
 * 最简字段域赋值
 * @param fieldName 文本域名称
 * @param fieldVal 文本内容
 * @param form AcroFields
 */
public static void setFieldAndFont(String fieldName, String fieldVal,AcroFields form) throws IOException, DocumentException {
    //参数3设置true是针对单选复选框展示
    form.setField(fieldName,fieldVal,true);
}

## 条形码

//绘制条码
Barcode128 barcode128 = new Barcode128();
//字号
barcode128.setSize(6);
//条码高度
barcode128.setBarHeight(12);
//条码与数字间距
barcode128.setBaseline(10);
//条码值
barcode128.setCode("条形码");
barcode128.setStartStopText(false);
barcode128.setExtended(true);
//生成条码图片 
PdfStamper ps;
PdfContentByte cb = ps.getOverContent(1);
Image image = barcode128.createImageWithBarcode(cb, null, null);

## 二维码

BarcodeQRCode qrCode = new BarcodeQRCode("二维码", width, height, null);
//生成二维码图像
Image image = qrCode.getImage();

## 二维条码

//绘制二维条码
BarcodePDF417 pdf417 = new BarcodePDF417();
pdf417.setText("二维条码");
Image image = pdf417.getImage();

## 图片填充

URL url = new URL("http://xxx.png");
Image img = Image.getInstance(url);

//图片自适应定义框。与scalePercent(10f)方法(可自行配置缩放)效果类似
img.scaleToFit(width,height);
//定位框左下位置(x,y)
img.setAbsolutePosition(x,y);
//获取字段操作页面
PdfContentByte content = pdfStamper.getOverContent(1);
content.addImage(img);

2、单选按钮域

//假设pdf模板里有名为radioGroup的单选域,其包含A,B,C三个单选按钮

AcroFields form;

form.setField("radioGroup","B",true); //表示选中了B

3、复选按钮域

//假设pdf模板里有名为CheckBox1-5的复选域组,在模板里定义的选中值为Y

AcroFields form;

form.setField("CheckBox1","Y",true); //表示选中了CheckBox1

form.setField("CheckBox3","Y",true); //表示选中了CheckBox3

4、图片域

//从acrobat中看出,图片域实际上是一个button组件
URL url = new URL("http://xxx.png");
Image img = Image.getInstance(url);
//PushbuttonField用来操作button组件
PushbuttonField pushbuttonField = form.getNewPushbuttonFromField("图片域名称");
pushbuttonField.setImage(img);
PdfFormField pdfFormField = pushbuttonField.getField();
form.replacePushbuttonField(fieldName, pdfFormField);

5、文字水印与图片水印

/**
 * 附加文字水印
 * @param showWords 水印内容
 * @param fontSize 字号
 * @param xRepeat 水平重复值
 * @param yRepeat 垂直重复值
 * @param opacity 透明度
 * @param rotation 旋转角度
 */
private static void appendWatermark(String showWords,int fontSize,int xRepeat,int yRepeat,float opacity,float rotation,PdfStamper pdfStamper,BaseFont baseFont,BaseColor baseColor){
    Rectangle pageRect = pdfStamper.getReader().getPageSizeWithRotation(1);
    // 计算水印每个单位步长X,Y
    float x = pageRect.getWidth() / xRepeat;
    float y = pageRect.getHeight() / yRepeat;

    PdfContentByte cb = pdfStamper.getOverContent(1);
    PdfGState gs = new PdfGState();
    // 设置透明度
    gs.setFillOpacity(opacity);
    cb.setGState(gs);
    cb.saveState();

    cb.beginText();
    cb.setColorFill(baseColor);
    cb.setFontAndSize(baseFont, fontSize);

    for (int n = 0; n < xRepeat + 1; n++) {
        for (int m = 0; m < yRepeat + 1; m++) {
            cb.showTextAligned(Element.ALIGN_CENTER, showWords, x * n, y * m, rotation);
        }
    }
    //添加图片水印
    //cb.addImage(image);
    cb.endText();
}

【四、模板页数确定与不确定的用法】

## 页码确定

private static boolean formPdfModelStatic() {
        //模板加载路径(项目目录下)
        String modelPath = "xxx.pdf";
        //文件输出路径
        String outputPath = "yyy.pdf";

        FileOutputStream fos = null;
        ByteArrayOutputStream baos = null;
        PdfReader pdfReader = null;
        PdfStamper pdfStamper = null;
        Document doc = null;
        PdfCopy copy = null;
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = resourceLoader.getResource("classpath:"+ modelPath);
        /*数据源*/
        List<FieldPropertyBind> prepareDataList = prepareDataFill();
        try {
            if(!FileOptUtils.checkFullFileCreate(outputPath)){
                return false;
            }
            fos = new FileOutputStream(outputPath);
            pdfReader = new PdfReader(resource.getURL());
            baos = new ByteArrayOutputStream();
            pdfStamper = new PdfStamper(pdfReader,baos);
            AcroFields form = pdfStamper.getAcroFields();
            BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
            form.addSubstitutionFont(baseFont);

            /*此块进行内容填充*/        


            //true代表生成的PDF文件不可编辑,会清除编辑痕迹的显示
            pdfStamper.setFormFlattening(true);
            pdfStamper.close();
            doc = new Document();
            copy = new PdfCopy(doc,fos);
            //开始文件操作
            doc.open();
            //指定模板第几页
            PdfImportedPage importedPage1 = copy.getImportedPage(new PdfReader(baos.toByteArray()), 1);
//            PdfImportedPage importedPage2 = copy.getImportedPage(new PdfReader(baos.toByteArray()), 2);
            //逐页添加
            copy.addPage(importedPage1);
//            copy.addPage(importedPage2);
        } catch (IOException | DocumentException e) {
            log.error("formPdfModelStatic_error:",e);
            return false;
        }finally {
            if (pdfReader != null){
                pdfReader.close();
            }
            if(doc != null){
                doc.close();
            }
            if (copy != null){
                copy.close();
            }
            IOUtils.closeQuietly(baos);
            IOUtils.closeQuietly(fos);
        }
        return true;
    }

## 页码不确定

public static boolean formPdfModelActive(){
        FileOutputStream fos = null;
        List<PdfReader> readerList = new ArrayList<>();
        Resource resource;
        try {
            //BaseFont.IDENTITY_V 为文字纵向排列。 IDENTITY_H 横向排列
            //STSongStd-Light 参见[itext-asian-5.2.0.jar \com\itextpdf\text\pdf\fonts\cjk_registry.properties] fonts (Adobe_GB1 表示字体排版)
            BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",BaseFont.EMBEDDED);
            /*动态模板1*/
            fos = generateActivePdf(baseFont, readerList);
            if (fos == null){
                return false;
            }
            streamListWriteToDoc(fos, readerList);
            readerList.clear();
            /*动态模板2-写法同动态模板1*/

        } catch (DocumentException | IOException e) {
            log.error("formPdfModelActive_error: ",e);
            return false;
        }finally {
            IOUtils.closeQuietly(fos);
        }
        return true;
    }
    
 /**动态pdf页数*/
    private static FileOutputStream generateActivePdf(BaseFont baseFont, List<PdfReader> readerList) throws IOException, DocumentException {
        //模板加载路径(项目目录下)
        String modelPath = "xxx.pdf";
        //文件输出路径
        String outputPath = "yyy.pdf";
        if(!FileOptUtils.checkFullFileCreate(outputPath)){
            return null;
        }
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = resourceLoader.getResource("classpath:"+ modelPath);
        ByteArrayOutputStream baos = null;

        /*数据源*/
        List<List<FieldPropertyBind>> wholeInfoList = new ArrayList<>();
        try {
            for (List<FieldPropertyBind> wholeInfo : wholeInfoList) {
                PdfReader sourceReader = new PdfReader(resource.getURL());
                PdfReader reader = null;
                baos = new ByteArrayOutputStream();
                PdfStamper pdfStamper = new PdfStamper(sourceReader,baos);
                AcroFields form = pdfStamper.getAcroFields();
                form.addSubstitutionFont(baseFont);
                /*数据填充*/
                
                
                pdfStamper.setFormFlattening(true);
                pdfStamper.close();
                reader = new PdfReader(baos.toByteArray());
                readerList.add(reader);
            }
        } finally {
            IOUtils.closeQuietly(baos);
        }
        return new FileOutputStream(outputPath);
    }

【五、资料引用及推荐】

1、纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)

(5条消息) 【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)_小帅丶的专栏-CSDN博客_java导出pdf表格怎么设置样式https://ydxiaoshuai.blog.csdn.net/article/details/96427606?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-2.no_search_link2、Itextpdf超详细整理

IText使用(超详解) - sudt - 博客园 (cnblogs.com)https://www.cnblogs.com/fonks/p/15090635.html3、java使用itext(根据一个模板生成多页数据)
(5条消息) java动态生成pdf文件(使用itext编辑pdf)_Aurora_____的博客-CSDN博客_动态生成pdf文件https://blog.csdn.net/Aurora_____/article/details/111209096?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1.no_search_link&spm=1001.2101.3001.4242.2&utm_relevant_index=4

4、java 实现生成公司的电子公章,并且盖章生成电子合同

(5条消息) java 实现生成公司的电子公章,并且盖章生成电子合同_三叶酸草有点酸的博客-CSDN博客_java 生成电子合同https://blog.csdn.net/weixin_41576903/article/details/108833567?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.pc_relevant_aa&utm_relevant_index=25、比较综合的itextpdf的运用

(5条消息) JAVA按模版导出PDF文件,含条码,二维码,表格_The...Exception-CSDN博客https://blog.csdn.net/ruixue0117/article/details/77599808?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.pc_relevant_paycolumn_v2&spm=1001.2101.3001.4242.1&utm_relevant_index=3


完整代码地址(develop分支)

修_瞻犀 / 编程博客代码仓库 · GitCodeGitCode——开源代码托管平台,独立第三方开源社区,Git/Github/Gitlabhttps://gitcode.net/qq_42130324/share_with.git

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值