生成带表格的pdf参考
java处理pdf文件——iText的使用_xiaomifeng1010的博客-CSDN博客_java处理pdf文件PDF(Portable Document Format的简称,意为“便携式文档格式”),是由Adobe Systems用于与应用程序、操作系统、硬件无关的方式进行文件交换所发展出的文件格式。PDF文件以PostScript语言图象模型为基础,无论在哪种打印机上都可保证精确的颜色和准确的打印效果,即PDF会忠实地再现原稿的每一个字符、颜色以及图象。(来自百度百科的介绍)。可以用来...https://blog.csdn.net/u011174699/article/details/105903929pom
com.itextpdf itextpdf5.5.13.1 com.itextpdf itext7-core7.1.8 org.apache.pdfbox pdfbox2.0.19 org.apache.commons commons-loggingcom.itextpdf itext-asian5.2.0
所有的import
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 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, ListtableData, 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{
// 流虽然都关闭了,但是还是无法删除文件,所以手动调用一下gc
System.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 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 打开会显示不出来填充的值,这里要特别注意下。
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 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();
}
}
效果:



