目录

本文总共知识点:

pom

所有的import

生成带表格的pdf

另一种方式是指定坐标生成文本域

main方法:

创建表单域做为pdf模板:

创建签名域:

根据文字获取坐标位置

完整代码:


本文总共知识点

1.生成带表格的pdf文件

2.创建文本域

3.创建签名域

4.获取指定文字坐标位置并在对应位置添加签名域。

本文比较长,可直接搜索自己需要的功能位置。

可以将font 拿出来设置成static的,可以节省很多速度。

本文缺点:

1. 同一个线程中连续创建两个及以上pdf会报错

生成带表格的pdf参考

java处理pdf文件——iText的使用_xiaomifeng1010的博客-CSDN博客_java处理pdf文件PDF(Portable Document Format的简称,意为“便携式文档格式”),是由Adobe Systems用于与应用程序、操作系统、硬件无关的方式进行文件交换所发展出的文件格式。PDF文件以PostScript语言图象模型为基础,无论在哪种打印机上都可保证精确的颜色和准确的打印效果,即PDF会忠实地再现原稿的每一个字符、颜色以及图象。(来自百度百科的介绍)。可以用来...https://blog.csdn.net/u011174699/article/details/105903929

pom

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.1</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.1.8</version></dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.19</version><exclusions><exclusion><groupId>org.apache.commons</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency>

所有的import

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.colors.DeviceGray;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontFactory;
import org.apache.pdfbox.pdmodel.font.PDType1Font;import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.io.*;
import java.util.*;

生成带表格的pdf

public static void createTablePdfFile(String savePath, String fontPath, List<String[]> tableData, String title, int width){try{File pdfFile=new File(savePath);if(!pdfFile.exists()){pdfFile.getParentFile().mkdir();}//            PdfFont pdfFont= PdfFontFactory.createFont(StandardFonts.HELVETICA);
//            设置中文字体为黑体常规(传入一个字体路径或者itext中内置支持的字体,如上)PdfFont documentFont=PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H,true);
//            使用font-asian中的字体,设置字体华文宋体(STSong-Light)PdfFont tableFont=PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H",true);com.itextpdf.kernel.pdf.PdfDocument pdfDocument=new com.itextpdf.kernel.pdf.PdfDocument(new com.itextpdf.kernel.pdf.PdfWriter(pdfFile));com.itextpdf.layout.Document document=new com.itextpdf.layout.Document(pdfDocument);
//            设置文本居中对齐document.setTextAlignment(TextAlignment.CENTER);document.setHorizontalAlignment(HorizontalAlignment.CENTER);
//            设置文档字体document.setFont(documentFont);
//            表格标题Paragraph tableTitle=new Paragraph(title);
//            设置表格标题字体和颜色(段落)tableTitle.setFont(documentFont).setFontColor(DeviceGray.BLACK);document.add(tableTitle);Table table=new Table(UnitValue.createPercentArray(tableData.get(0).length)).useAllAvailableWidth();
//            设置表格字体table.setFont(tableFont);
//            设置表格列宽table.setWidth(width);
//            设置表格背景色
//            table.setBackgroundColor(ColorConstants.LIGHT_GRAY);
//            设置表格文本居中对齐table.setTextAlignment(TextAlignment.CENTER);
//            设置表格垂直对齐方式table.setVerticalAlignment(VerticalAlignment.MIDDLE);
//            设置表格水平对齐方式table.setHorizontalAlignment(HorizontalAlignment.CENTER);
//            Cell cell=new Cell();
//            设置单元格背景色为深灰色
//            cell.setBackgroundColor(ColorConstants.DARK_GRAY);for (String[] row :tableData) {
//                更精确的颜色可以使用new DeviceRgb()传入三原色的数值[0-255]来设置
//                new DeviceRgb(13,23,5);for (String cell : row) {table.addCell(new Paragraph(cell).setFontColor(DeviceRgb.BLACK));}}UnitValue height = table.getHeight();document.add(table);pdfDocument.close();}catch (Exception e){e.printStackTrace();}}

另一种方式是指定坐标生成文本域

    public static void createPdfFileTest(String savePath, String fontPath){//        创建文档页面(设置为矩形A4大小)PDPage page = new PDPage(PDRectangle.A4);
//        创建pdf文档对象,以及页面内容流对象try {File pdfFile=new File(savePath);if(!pdfFile.exists()){pdfFile.getParentFile().mkdir();}PdfFont pdfFont = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H, true);PdfFont tableFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H",true);PDDocument pdfDocument=new PDDocument();PDPageContentStream pageContentStream=new PDPageContentStream(pdfDocument,page);pdfDocument.addPage(page);
//        设置字体为Helvetica-Bold或TIMES_ROMAN;,类库中没有中文字体,程序会去查找本地是否安装了该字体,查找非常慢PDFont font= PDType1Font.TIMES_ROMAN;
//            开始页面的文本操作pageContentStream.beginText();pageContentStream.setFont(font,12);pageContentStream.moveTextPositionByAmount(100,700);
//            因为jar包中自带的没有中文字体,所以写入中文会出异常pageContentStream.showText("hello");//            结束页面文本操作pageContentStream.endText();pageContentStream.close();//            pdf文档保存在本项目所在磁盘下data目录下pdfDocument.save(pdfFile);System.out.println("文件写入成功");} catch (Exception e) {e.printStackTrace();}finally{
//            流虽然都关闭了,但是还是无法删除文件,所以手动调用一下gcSystem.gc();System.out.println("执行垃圾回收");}}

main方法:

public static void main(String[] args) {FileOutputStream out= null;PdfReader reader=null;PdfStamper pdfStamper=null;try {String createFile = "K:\\create.pdf";String fontPath = "c:\\Windows\\fonts\\simhei.ttf";long start = System.currentTimeMillis();String title = "人员信息表";List<String[]> tableData = new ArrayList<>();tableData.add(new String[]{"交易类型", "时间", "金额"});tableData.add(new String[]{"放款", "2022/10/11 18:23:22", "28432.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "11.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "12.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "52.00"});tableData.add(new String[]{"罚息", "2022/10/15 18:23:22", "11111.00"});createTablePdfFile(createFile, fontPath, tableData, title, 500);
//            createPdfFileTest(createFile, fontPath);long end = System.currentTimeMillis() - start;System.out.println(end);System.out.println(tableData.size());} catch (Exception e) {e.printStackTrace();}}

效果:

创建表单域做为pdf模板:

带有表单域填充的pdf,使用edge 打开会显示不出来填充的值,这里要特别注意下。

    /*** 创建表单文本域* @author dongdong* @date 2022/4/27* @param float llx, float lly, float urx, float ury 前面两个参数代表第一个点的 xy 坐标,后面两个参数代表第二个点的 xy 坐标值* @return*/public static void createTextFieldByDefine(String readFile, String saveFile, float llx, float lly, float urx, float ury) throws IOException, DocumentException{FileOutputStream out = new FileOutputStream(new File(saveFile));PdfReader reader=new PdfReader(new FileInputStream(new File(readFile)));PdfStamper pdfStamper=new PdfStamper(reader,out);PdfWriter writer = pdfStamper.getWriter();float height = reader.getPageSize(reader.getNumberOfPages()).getHeight();float width = reader.getPageSize(reader.getNumberOfPages()).getWidth();PdfFormField form = PdfFormField.createEmpty(writer);//普通文本框TextField field = new TextField(writer, new Rectangle(llx, lly, urx, ury), "text");field.setOptions(TextField.MULTILINE);//防止读取pdf文档时,就是有旋转角度的field.setRotation(reader.getPageRotation(1));//有些状况下,页数问题能够在这里设置,优先级最高field.getTextField().setPlaceInPage(1);form.addKid(field.getTextField());// file.setOptions(TextField.VISIBLE);//文本域可见(相对于文本域是否高亮)// file.setOptions(TextField.HIDDEN);//文本域不可见// file.setOptions(TextField.VISIBLE_BUT_DOES_NOT_PRINT);//该字段可见,但不打印。// file.setOptions(TextField.HIDDEN_BUT_PRINTABLE);//该字段不可见,但不打印。// file.setOptions(TextField.HIDDEN_BUT_PRINTABLE);//该字段不可见,但不打印。// file.setOptions(TextField.READ_ONLY);//只读// file.setOptions(TextField.REQUIRED);//该字段在经过提交表单操做导出时必须具备值。// file.setOptions(TextField.MULTILINE);//规定区域内能够换行显示// file.setOptions(TextField.DO_NOT_SCROLL);//文本域不会有滚动条,对于单行字段为水平,对于多行字段为垂直,一旦区域满了,将不会再接受任何文字。// file.setOptions(TextField.PASSWORD);//该字段用于输入安全密码,该密码不该该被可视地显示在屏幕上。// file.setOptions(TextField.FILE_SELECTION);//我的理解好像是上传文件,不是很理解// file.setOptions(TextField.DO_NOT_SPELL_CHECK);//无拼写检查// file.setOptions(TextField.EDIT);//若是设置组合框包括一个可编辑的文本框以及一个下拉列表;若是清楚,它只包括一个下拉列表。这个标志只对组合字段有意义。// file.setOptions(TextField.MULTISELECT);//无论列表是否能够有多个选择。仅适用于/ ch列表字段,而不适用于组合框。// file.setOptions(TextField.COMB);//组合框标志。pdfStamper.addAnnotation(form, reader.getNumberOfPages());// 设置表单域可被编辑,用来做为后面可以填充的模板pdfStamper.setFormFlattening(false);pdfStamper.close();out.close();}

测试方法:

    public static void main(String[] args) {FileOutputStream out= null;PdfReader reader=null;PdfStamper pdfStamper=null;try {String createFile = "K:\\resources\\META-INF\\create.pdf";String fontPath = "K:\\resources\\META-INF\\simhei.ttf";long start = System.currentTimeMillis();String title = "人员信息表";List<String[]> tableData = new ArrayList<>();tableData.add(new String[]{"交易类型", "时间", "金额"});tableData.add(new String[]{"放款", "2022/10/11 18:23:22", "28432.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "11.00"});tableData.add(new String[]{"罚息", "2022/10/15 18:23:22", "11111.00"});createTablePdfFile(createFile, fontPath, tableData, title, 500);
//            createPdfFileTest(createFile, fontPath);long end = System.currentTimeMillis() - start;System.out.println(end);System.out.println(tableData.size());String saveFile = "K:\\resources\\META-INF\\createFile2.pdf";createTextFieldByDefine(createFile, saveFile, 400, 300, 500, 400);} catch (Exception e) {e.printStackTrace();}}

坐标的话是从页面的左下角往右下角画的,这里有点不是特别的好。

效果:

创建签名域:

    public static void fillTemplate(String readFile, String savePdfFile) {PdfReader reader;FileOutputStream out;PdfStamper ps;try {out = new FileOutputStream(savePdfFile);reader = new PdfReader(new FileInputStream(new File(readFile)));//源文件ps  = new PdfStamper(reader, out);// 创建数组签名域  (因为添加两个,所以搞了两个坐标系)int x = 210, y = 437, width = 200, height = 100; // 坐标系远点位于页面左下角,左下角到右下角为  x 轴,左下角到左上角为 y 轴Rectangle areaSignatureRect = new Rectangle(// 签名域区域,由两个对角点构成的矩形区域x, // 点1 x坐标 左边距y, // 点1 y坐标 上边距x+width,// 点2 x坐标, 这个最好是左边距+宽,好调点。y+height // 点2 y坐标, 同样这个最好是上边距+高,好调点。(其实我也懵懵懂.));int pageNo = reader.getNumberOfPages(); // PDF 文件的页码从 1 开始,而不是 0。(这个就是你要在哪个页面添加签名域,我的是第五页)PdfFormField pdfFormField = PdfFormField.createSignature(ps.getWriter());pdfFormField.setFieldName("AREA_SIGNATURE"); // 签名域标识pdfFormField.setPage(pageNo);pdfFormField.setWidget(areaSignatureRect, PdfAnnotation.HIGHLIGHT_OUTLINE); // 高亮显示ps.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑ps.addAnnotation(pdfFormField, pageNo);System.err.println("生成pdf文件完成~~~~~~~~~~");ps.close();//必须要关闭,要不然生成的PDF会是0KB(此代码大部分都是网上摘抄的,以为能用来着。没写这个,让我找大半天)} catch (Exception e) {e.printStackTrace();}}

效果:

根据文字获取坐标位置

public static float[] getPdfPositionByText(String readPdfFile, String outPdfFile, String keyWords){PdfReader reader = null;FileOutputStream fileOutputStream = null;PdfStamper stamper = null;try {reader = new PdfReader(readPdfFile);fileOutputStream = new FileOutputStream(outPdfFile);//新建一个PDF解析对象PdfReaderContentParser parser = new PdfReaderContentParser(reader);//包含了PDF页面的信息,作为处理的对象stamper = new PdfStamper(reader, fileOutputStream);float[] coordinate = null;int page = 0;try{int pageNum = reader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(reader);CustomRenderListener renderListener = new CustomRenderListener();renderListener.setKeyWord(keyWords);for (page = 1; page <= pageNum; page++) {renderListener.setPage(page);pdfReaderContentParser.processContent(page, renderListener);coordinate = renderListener.getPcoordinate();if (coordinate != null) break;}} catch (IOException e) {e.printStackTrace();}return coordinate;} catch (Exception e) {e.printStackTrace();return null;}}

需要用到一个监听类

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;/*** @date 2022/4/27 18:18* 说明*/
public class CustomRenderListener implements RenderListener {private float[] pcoordinate = null;private String keyWord;private int page;public int getPage() {return page;}public void setPage(int page) {this.page = page;}public float[] getPcoordinate(){return pcoordinate;}public String getKeyWord() {return keyWord;}public void setKeyWord(String keyWord) {this.keyWord = keyWord;}@Overridepublic void beginTextBlock() {}@Overridepublic void renderImage(ImageRenderInfo renderInfo) {}@Overridepublic void endTextBlock() {}@Overridepublic void renderText(TextRenderInfo textRenderInfo) {String text = textRenderInfo.getText();if (null != text && text.contains(keyWord)) {Rectangle2D.Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();pcoordinate = new float[3];pcoordinate[0] = boundingRectange.x;pcoordinate[1] = boundingRectange.y;pcoordinate[2] = page;}}
}

最后优化了一下根据文字坐标添加签名域的方法,大体代码同上面添加签名域的,就不重新贴了

方法增加参数上面搜索到的文字坐标int x = (int)keyWordPosition[0],y = (int)keyWordPosition[1] - 100,width = 200, height = 100;

然后这个坐标是从左下角开始查找的,这里注意下。

效果:

完整代码:

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.colors.DeviceGray;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontFactory;
import org.apache.pdfbox.pdmodel.font.PDType1Font;import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.io.*;
import java.util.*;/*** @date 2022/4/26 15:10* 说明*/
public class PdfCreatedByText {/*** 创建表单文本域* @date 2022/4/27* @param float llx, float lly, float urx, float ury 前面两个参数代表第一个点的 xy 坐标,后面两个参数代表第二个点的 xy 坐标值* @return*/public static void createTextFieldByDefine(PdfReader reader, PdfStamper pdfStamper, float llx, float lly, float urx, float ury) throws IOException, DocumentException{PdfWriter writer = pdfStamper.getWriter();PdfFormField form = PdfFormField.createEmpty(writer);//普通文本框TextField field = new TextField(writer, new Rectangle(llx, lly, urx, ury), "text");field.setOptions(TextField.MULTILINE);//防止读取pdf文档时,就是有旋转角度的field.setRotation(reader.getPageRotation(1));//有些状况下,页数问题能够在这里设置,优先级最高field.getTextField().setPlaceInPage(1);form.addKid(field.getTextField());// file.setOptions(TextField.VISIBLE);//文本域可见(相对于文本域是否高亮)// file.setOptions(TextField.HIDDEN);//文本域不可见// file.setOptions(TextField.VISIBLE_BUT_DOES_NOT_PRINT);//该字段可见,但不打印。// file.setOptions(TextField.HIDDEN_BUT_PRINTABLE);//该字段不可见,但不打印。// file.setOptions(TextField.HIDDEN_BUT_PRINTABLE);//该字段不可见,但不打印。// file.setOptions(TextField.READ_ONLY);//只读// file.setOptions(TextField.REQUIRED);//该字段在经过提交表单操做导出时必须具备值。// file.setOptions(TextField.MULTILINE);//规定区域内能够换行显示// file.setOptions(TextField.DO_NOT_SCROLL);//文本域不会有滚动条,对于单行字段为水平,对于多行字段为垂直,一旦区域满了,将不会再接受任何文字。// file.setOptions(TextField.PASSWORD);//该字段用于输入安全密码,该密码不该该被可视地显示在屏幕上。// file.setOptions(TextField.FILE_SELECTION);//我的理解好像是上传文件,不是很理解// file.setOptions(TextField.DO_NOT_SPELL_CHECK);//无拼写检查// file.setOptions(TextField.EDIT);//若是设置组合框包括一个可编辑的文本框以及一个下拉列表;若是清楚,它只包括一个下拉列表。这个标志只对组合字段有意义。// file.setOptions(TextField.MULTISELECT);//无论列表是否能够有多个选择。仅适用于/ ch列表字段,而不适用于组合框。// file.setOptions(TextField.COMB);//组合框标志。pdfStamper.addAnnotation(form, reader.getNumberOfPages());// 设置表单域可被编辑,用来做为后面可以填充的模板pdfStamper.setFormFlattening(false);pdfStamper.close();}/*** @param fields* @param data* @throws IOException* @throws DocumentException*/private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {Map<String, AcroFields.Item> formFields = fields.getFields();for (String key : data.keySet()) {if(formFields.containsKey(key)){String value = data.get(key);fields.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的}}}// 生成表格public static void createPdfTextFile(String savePath){//        创建文档页面(设置为矩形A4大小)PDPage page = new PDPage(PDRectangle.A4);
//        创建pdf文档对象,以及页面内容流对象try {File pdfFile=new File(savePath);if(!pdfFile.exists()){pdfFile.getParentFile().mkdir();}PDDocument pdfDocument=new PDDocument();PDPageContentStream pageContentStream=new PDPageContentStream(pdfDocument,page);pdfDocument.addPage(page);
//        设置字体为Helvetica-Bold或TIMES_ROMAN;,类库中没有中文字体,程序会去查找本地是否安装了该字体,查找非常慢PDFont font= PDType1Font.TIMES_ROMAN;
//            开始页面的文本操作pageContentStream.beginText();pageContentStream.setFont(font,12);pageContentStream.moveTextPositionByAmount(100,700);
//            因为jar包中自带的没有中文字体,所以写入中文会出异常pageContentStream.showText("hello");//            结束页面文本操作pageContentStream.endText();pageContentStream.close();//            pdf文档保存在本项目所在磁盘下data目录下pdfDocument.save(pdfFile);System.out.println("文件写入成功");pdfDocument.close();} catch (Exception e) {e.printStackTrace();}finally{
//            流虽然都关闭了,但是还是无法删除文件,所以手动调用一下gcSystem.gc();System.out.println("执行垃圾回收");}}public static float[] getPdfPositionByText(PdfReader reader, String keyWords){try {float[] coordinate = null;int page = 0;try{int pageNum = reader.getNumberOfPages();//新建一个PDF解析对象PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(reader);CustomRenderListener renderListener = new CustomRenderListener();renderListener.setKeyWord(keyWords);for (page = 1; page <= pageNum; page++) {renderListener.setPage(page);//包含了PDF页面的信息,作为处理的对象pdfReaderContentParser.processContent(page, renderListener);coordinate = renderListener.getPcoordinate();if (coordinate != null) break;}} catch (IOException e) {e.printStackTrace();}return coordinate;} catch (Exception e) {e.printStackTrace();}return new float[3];}/*** 生成带表格的pdf文件* @date 2022/4/27* @param  tableWidth 表格宽度* @param  tableData 填充的数据,二维数据* @return*/public static void createTablePdfFile(File pdfFile, String fontPath, List<String[]> tableData, String title, int tableWidth){try{//            PdfFont pdfFont= PdfFontFactory.createFont(StandardFonts.HELVETICA);
//            设置中文字体为黑体常规(传入一个字体路径或者itext中内置支持的字体,如上)PdfFont documentFont=PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H,true);
//            使用font-asian中的字体,设置字体华文宋体(STSong-Light)PdfFont tableFont=PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H",true);com.itextpdf.kernel.pdf.PdfWriter pdfWriter = new com.itextpdf.kernel.pdf.PdfWriter(pdfFile);com.itextpdf.kernel.pdf.PdfDocument pdfDocument=new com.itextpdf.kernel.pdf.PdfDocument(pdfWriter);com.itextpdf.layout.Document document=new com.itextpdf.layout.Document(pdfDocument);
//            设置文本居中对齐document.setTextAlignment(TextAlignment.CENTER);document.setHorizontalAlignment(HorizontalAlignment.CENTER);
//            设置文档字体document.setFont(documentFont);
//            表格标题Paragraph tableTitle=new Paragraph(title);
//            设置表格标题字体和颜色(段落)tableTitle.setFont(documentFont).setFontColor(DeviceGray.BLACK);document.add(tableTitle);Table table=new Table(UnitValue.createPercentArray(tableData.get(0).length)).useAllAvailableWidth();
//            设置表格字体table.setFont(tableFont);
//            设置表格列宽table.setWidth(tableWidth);
//            设置表格背景色
//            table.setBackgroundColor(ColorConstants.LIGHT_GRAY);
//            设置表格文本居中对齐table.setTextAlignment(TextAlignment.CENTER);
//            设置表格垂直对齐方式table.setVerticalAlignment(VerticalAlignment.MIDDLE);
//            设置表格水平对齐方式table.setHorizontalAlignment(HorizontalAlignment.CENTER);
//            Cell cell=new Cell();
//            设置单元格背景色为深灰色
//            cell.setBackgroundColor(ColorConstants.DARK_GRAY);for (String[] row : tableData) {
//                更精确的颜色可以使用new DeviceRgb()传入三原色的数值[0-255]来设置
//                new DeviceRgb(13,23,5);for (String cell : row) {table.addCell(new Paragraph(cell).setFontColor(DeviceRgb.BLACK));}}document.add(table);document.close();pdfDocument.close();pdfWriter.flush();pdfWriter.close();}catch (Exception e){e.printStackTrace();}}public static void fillTemplate(PdfReader reader, PdfStamper ps, float[] keyWordPosition) {try {// 创建数组签名域  (因为添加两个,所以搞了两个坐标系)int x = (int)keyWordPosition[0],y = (int)keyWordPosition[1] - 100,width = 200, height = 100; // 坐标系远点位于页面左下角,左下角到右下角为  x 轴,左下角到左上角为 y 轴
//            int x = 210, y = 437, width = 200, height = 100; // 坐标系远点位于页面左下角,左下角到右下角为  x 轴,左下角到左上角为 y 轴Rectangle areaSignatureRect = new Rectangle(// 签名域区域,由两个对角点构成的矩形区域x, // 点1 x坐标 左边距y, // 点1 y坐标 上边距x+width,// 点2 x坐标, 这个最好是左边距+宽,好调点。y+height // 点2 y坐标, 同样这个最好是上边距+高,好调点。(其实我也懵懵懂.));int pageNo = reader.getNumberOfPages(); // PDF 文件的页码从 1 开始,而不是 0。(这个就是你要在哪个页面添加签名域,我的是第五页)PdfFormField pdfFormField = PdfFormField.createSignature(ps.getWriter());pdfFormField.setFieldName("AREA_SIGNATURE"); // 签名域标识pdfFormField.setPage(pageNo);pdfFormField.setWidget(areaSignatureRect, PdfAnnotation.HIGHLIGHT_OUTLINE); // 高亮显示ps.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑ps.addAnnotation(pdfFormField, pageNo);System.err.println("生成pdf文件完成~~~~~~~~~~");ps.close();//必须要关闭,要不然生成的PDF会是0KB(此代码大部分都是网上摘抄的,以为能用来着。没写这个,让我找大半天)} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {try {// 必须是两个不同的文件String createFilePath = "K:\\resources\\META-INF\\create.pdf";String saveFile = "K:\\resources\\META-INF\\create2.pdf";String fontPath = "K:\\resources\\META-INF\\simhei.ttf";long start = System.currentTimeMillis();String title = "人员信息表";List<String[]> tableData = new ArrayList<>();tableData.add(new String[]{"交易类型", "时间", "金额"});tableData.add(new String[]{"放款", "2022/10/11 18:23:22", "28432.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "11.00"});tableData.add(new String[]{"还款", "2022/10/13 18:23:22", "52.00"});SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:dd");tableData.add(new String[]{"罚息", simpleDateFormat.format(new Date()), "11111.00"});File pdfFile=new File(saveFile);if(!pdfFile.exists()){pdfFile.getParentFile().mkdir();pdfFile.createNewFile();}File createFile = new File(createFilePath);if(!createFile.exists()){createFile.getParentFile().mkdir();createFile.createNewFile();}// 先生成 create2 文件createTablePdfFile(pdfFile, fontPath, tableData, title, 500);// 读取  create2 文件,并写入 create 文件FileOutputStream out = new FileOutputStream(createFilePath);PdfReader reader =new PdfReader(new FileInputStream(pdfFile));PdfStamper pdfStamper =new PdfStamper(reader,out);// 生成文件测试//            createPdftextFile(createFile);//            createTextFieldByDefine(createFile, saveFile, 400, 300, 500, 400);float[] keyWordPosition = getPdfPositionByText(reader, "罚息");fillTemplate(reader, pdfStamper, keyWordPosition);long end = System.currentTimeMillis() - start;System.out.println(end);System.out.println(tableData.size());} catch (Exception e) {e.printStackTrace();}}}
CustomRenderListener
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;/*** @date 2022/4/27 18:18* 说明*/
public class CustomRenderListener implements RenderListener {private float[] pcoordinate = null;private String keyWord;private int page;public int getPage() {return page;}public void setPage(int page) {this.page = page;}public float[] getPcoordinate(){return pcoordinate;}public String getKeyWord() {return keyWord;}public void setKeyWord(String keyWord) {this.keyWord = keyWord;}@Overridepublic void beginTextBlock() {}@Overridepublic void renderImage(ImageRenderInfo renderInfo) {}@Overridepublic void endTextBlock() {}@Overridepublic void renderText(TextRenderInfo textRenderInfo) {String text = textRenderInfo.getText();if (null != text && text.contains(keyWord)) {Rectangle2D.Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();pcoordinate = new float[3];pcoordinate[0] = boundingRectange.x;pcoordinate[1] = boundingRectange.y;pcoordinate[2] = page;}}
}

最终效果:

java 文字生成pdf,并创建自定义表单域pdf模板相关推荐

  1. 自定义表单mysql_创建自定义表单

    自定义表单模块,用于收集访问前端的用户的信息. 自定义表单能够用于创建用户交互界面,用户提交的信息保存在Orchard站点中,能够随时导出. 打开Custom Forms模块 Custom Forms ...

  2. 如何通过Java代码在Word中创建可填充表单

    有时候,我们需要制作一个Word模板文档,然后发给用户填写,但我们希望用户只能在指定位置填写内容,其他内容不允许编辑和修改.这时候我们就可以通过表单控件来轻松实现这一功能.本文将为您介绍如何通过Jav ...

  3. 织梦系统 diy.php,织梦自定义表单怎样更换模板

    在用织梦做企业站时,经常会用到在线留言页面,用织梦自定义表单可以很容易做出在线留言页面,但通常我们自己做的网站不会用织梦的默认模板,默认模板也不是太美观,那怎样更换自定义表单的模板呢?其实也很简单,方 ...

  4. 织梦dede系统中自定义表单如何修改模板

    找到,'生 成'- 更新主页html 修改主页dede模板文件所在目录,一般将default/index.htm改为 {style}/index.htm 系统 默认的模板是:/根目录/templets ...

  5. java 填充pdf_Java如何创建和填充PDF表单域(代码示例)

    本篇文章给大家带来的内容是关于Java如何创建和填充PDF表单域(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 表单域,可以按用途分为多种不同的类型,常见的有文本框.多行 ...

  6. java 填充pdf_Java创建和填充PDF表单域方法

    表单域,可以按用途分为多种不同的类型,常见的有文本框.多行文本框.密码框.隐藏域.复选框.单选框和下拉选择框等,目的是用于采集用户的输入或选择的数据.下面的示例中,将分享通过Java编程在PDF中添加 ...

  7. Java 创建、填充PDF表单域

    表单域,可以按用途分为多种不同的类型,常见的有文本框.多行文本框.密码框.隐藏域.复选框.单选框和下拉选择框等,目的是用于采集用户的输入或选择的数据.下面的示例中,将分享通过Java编程在PDF中添加 ...

  8. java pdf表单域实现_Java 创建PDF表单域 - 文本框、复选框、列表框、组合框、按钮等...

    表单域包括文本框.复选框.列表框.组合框.按钮和签名域等,主要用于收集用户填写或选择的数据.这篇文章将介绍如何在Java应用程序中给PDF文档添加表单域. 导入jar文件 本文所使用的PDF类库是Fr ...

  9. 使用工具对pdf表单域编辑

    一.问题 实现线下电子签章功能,每经过一次签证,都需要保留签证 的pdf文件(带有实际电子签章), 点击电子签章有相关签章信息 难点:需要pdf文件,根据表单域进行k-v填充 二.生成pdf文件模板 ...

最新文章

  1. 2022-2028年中国封装用胶膜行业运营现状及投资发展潜力报告
  2. mysql数据库忘记密码
  3. HTML解析原理概括(转载)
  4. /dev/tcp 的简单应用
  5. 百度前端技术学院html任务,重回百度前端技术学院第一天 HTML复习
  6. mysql有没有单机版?
  7. OpenStack Nova计算服务管理(四)
  8. 合并排序算法排序过程_合并排序| 用于大型输入的最佳排序算法之一
  9. linux messages 时间错乱_BATJ 常考的 21 条 Linux 命令,速度收藏!
  10. 小白设计模式:装饰者模式
  11. Android自定义图形shape
  12. dev grdicontrol 根据条件改变行颜色,字体颜色等
  13. Linux快速入门之一(基础)
  14. 获取素材列表返回40004 invalid media type !(大坑)解决办法
  15. 算法提高 盾神与条状项链
  16. python将两个文件合并_python实现两个文件合并功能
  17. L1-087 机工士姆斯塔迪奥(Python3)
  18. 数据库JDBC(知识点整理)
  19. 对于电子签名、CA、证书的理解
  20. Installing OpenCV 2.4.9 in Ubuntu 14.04 LTS(好文章)

热门文章

  1. Java进行解析气象数据格式GRB2 ,根据经纬度查询某一格点数值
  2. 无人驾驶虚拟仿真(一)--环境搭建
  3. 字符函数和字符串函数(函数介绍)
  4. Apache Kafka for Item Setup
  5. 计算机上怎么在表格输入分秒,excel输入分秒和分秒计算例子
  6. javascript常用功能收藏
  7. ET框架---ActorComponent学习笔记
  8. 【技巧】Pandas使用drop后使用reset_index重置索性
  9. 2022-2028全球与中国微型微动开关市场现状及未来发展趋势
  10. app获取通讯录全新开发