有个人(死需求)跑过来跟你说,这些都给我输出成报告,pdf格式的,所以就有了下面这个,做一下笔记,以后有用直接过来拿。在网上找了一下,发现大家都是在用itext。
iText是著名的开放项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。
http://itextpdf.com/
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.10</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
itext有很多功能,这里先说基本的操作。其他更多高级的操作,可以继续看下面的。
基本处理步骤如下伪代码:
//Step 1—Create a Document. Document document = new Document(); //Step 2—Get a PdfWriter instance. PdfWriter.getInstance(document, new FileOutputStream(FILE_DIR + "createSamplePDF.pdf")); //Step 3—Open the Document. document.open(); //Step 4—Add content. document.add(new Paragraph("Hello World")); //Step 5—Close the Document. document.close();
这里有个特别注意的是,中文必须要指定字体,即是BaseFont
public class PDFReport { private final static String REPORT_PATH = "C:/air-navi-monitor/report"; private static void exportReport() { BaseFont bf; Font font = null; Font font2 = null; try { bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);//创建字体 font = new Font(bf, 12);//使用字体 font2 = new Font(bf, 12, Font.BOLD);//使用字体 } catch (Exception e) { e.printStackTrace(); } Document document = new Document(); try { PdfWriter.getInstance(document, new FileOutputStream("E:/2.pdf")); document.open(); Paragraph elements = new Paragraph("常州武进1区飞行报告", font2); elements.setAlignment(Paragraph.ALIGN_CENTER); document.add(elements); Image png = Image.getInstance("E://test.png"); png.setAlignment(Image.ALIGN_CENTER); document.add(png); document.add(new Paragraph("任务编号:20190701 开始日期:20190701", font)); document.add(new Paragraph("任务名称:常州武进1区 结束日期:20190701", font)); document.add(new Paragraph("平均飞行高度:100m 平均飞行速度:100km/h", font)); document.add(new Paragraph("任务面积:1000㎡ 结束日期:20190701", font)); document.add(new Paragraph("飞行总时长:1000㎡", font)); document.addCreationDate(); document.close(); } catch (Exception e) { System.out.println("file create exception"); } } /** * 生成pdf文件 * * @param missionReport * @return */ public static String exportReport(MissionReportTb missionReport) throws AirNaviException { String pdfPath = null; String imgPath = Shape2Image.getImgPath(missionReport.getMissionID()); // String imgPath = "E://test.png"; String finalReportStr = missionReport.getMissionReport(); MissionReport finalReport = JSONObject.parseObject(finalReportStr, MissionReport.class); BaseFont bf; Font font = null; Font font2 = null; try { bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);//创建字体 font = new Font(bf, 12);//使用字体 font2 = new Font(bf, 12, Font.BOLD);//使用字体 } catch (Exception e) { e.printStackTrace(); } Document document = new Document(); try { File dir = new File(REPORT_PATH); if (!dir.exists()) { dir.mkdirs(); } File file = new File(REPORT_PATH + File.separator + missionReport.getMissionID() + ".pdf"); if (!file.exists()) { file.createNewFile(); } PdfWriter.getInstance(document, new FileOutputStream(REPORT_PATH + File.separator + missionReport.getMissionID() + ".pdf")); document.open(); Paragraph elements = new Paragraph(missionReport.getMissionName() + "飞行报告", font2); elements.setAlignment(Paragraph.ALIGN_CENTER); document.add(elements); Image png = Image.getInstance(imgPath); // https://blog.csdn.net/lingbo89/article/details/76177825 float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin(); float documentHeight = documentWidth / 580 * 320;//重新设置宽高 png.scaleAbsolute(documentWidth, documentHeight);//重新设置宽高 png.scalePercent(50); // 根据域的大小缩放图片 // image.scaleToFit(signRect.getWidth(), signRect.getHeight()); png.setAlignment(Image.ALIGN_CENTER); document.add(png); document.add(new Paragraph("任务编号:" + missionReport.getMissionCode() + ",开始日期:" + finalReport.getStartTime(), font)); document.add(new Paragraph("任务名称:" + missionReport.getMissionName() + ",结束日期:" + finalReport.getEndTime(), font)); document.add(new Paragraph("平均飞行高度:" + finalReport.getAvgFlightHeight() + "m" + ",平均飞行速度:" + finalReport.getAvgFlightSpeed() + "km/h", font)); document.add(new Paragraph("任务面积:" + finalReport.getMissionArea() + "㎡" + ",飞行总时长:" + finalReport.getFlightDuration() + "min", font)); document.addCreationDate(); document.close(); pdfPath = file.getAbsolutePath(); } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); System.out.println("file create exception"); throw new AirNaviException("生成PDF失败:" + e.getMessage()); } return pdfPath; } public static void main(String[] args) throws AirNaviException { String report = "{/"detailMissionReport/":[{/"avgFlightHeight/":119.7,/"avgFlightSpeed/":71.1,/"endPoint/":/"113.27484,22.86843/",/"endTime/":/"2019-09-17 17:47:07/",/"flightDuration/":9,/"reportID/":1,/"startPoint/":/"113.31429,22.78240/",/"startTime/":/"2019-09-17 17:38:03/",/"statisticsTimes/":505}],/"missionReport/":{/"avgFlightHeight/":119.7,/"avgFlightSpeed/":71.1,/"endPoint/":/"113.31429,22.78240/",/"endTime/":/"2019-09-17 17:47:07/",/"flightDuration/":9,/"reportID/":1,/"startPoint/":/"113.31429,22.78240/",/"startTime/":/"2019-09-17 17:38:03/",/"statisticsTimes/":0},/"missionArea/":0.0,/"missionCode/":/"M001/",/"missionID/":/"888813ddef6646cd9bfaba5abb748a43/",/"missionName/":/"德胜航点M008/",/"missionStatus/":1,/"missionType/":0,/"plannedFlightTime/":/"20190909/"}"; MissionReportTb missionReportTb = JSONObject.parseObject(report, MissionReportTb.class); exportReport(missionReportTb); } }
首先你的制作一个pdf模板:
1.先用word做出模板界面
2.文件另存为pdf格式文件
3.通过Adobe Acrobat pro软件打开刚刚用word转换成的pdf文件(注:如果没有这个软件可以通过我的百度云下载,链接: http://pan.baidu.com/s/1pL2klzt )如果无法下载可以Google一下。
4.点击右边的"准备表单"按钮,选择"测试.pdf"选择开始
进去到编辑页面,打开后它会自动侦测并命名表单域,右键表单域,点击属性,出现文本域属性对话框(其实无需任何操作,一般情况下不需要修改什么东西,至少我没有修改哦。如果你想修改fill1等信息,可以进行修改)
5.做完上面的工作后,直接"另存为"将pdf存储就可以
以上部分是制作pdf模板操作,上述完成后,就开始通过程序来根据pdf模板生成pdf文件了,上java程序:
public class Snippet { // 利用模板生成pdf public static void fillTemplate() { // 模板路径 String templatePath = "E:/测试3.pdf"; // 生成的新文件路径 String newPDFPath = "E:/ceshi.pdf"; PdfReader reader; FileOutputStream out; ByteArrayOutputStream bos; PdfStamper stamper; try { out = new FileOutputStream(newPDFPath);// 输出流 reader = new PdfReader(templatePath);// 读取pdf模板 bos = new ByteArrayOutputStream(); stamper = new PdfStamper(reader, bos); AcroFields form = stamper.getAcroFields(); String[] str = {"123456789", "TOP__ONE", "男", "1991-01-01", "130222111133338888", "河北省保定市"}; int i = 0; java.util.Iterator<String> it = form.getFields().keySet().iterator(); while (it.hasNext()) { String name = it.next().toString(); System.out.println(name); form.setField(name, str[i++]); } stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true stamper.close(); Document doc = new Document(); PdfCopy copy = new PdfCopy(doc, out); doc.open(); PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1); copy.addPage(importPage); doc.close(); } catch (IOException e) { System.out.println(1); } catch (DocumentException e) { System.out.println(2); } } public static void main(String[] args) { fillTemplate(); } }
运行结果如下
1、页面大小,页面背景色,页边空白,Title,Author,Subject,Keywords
核心代码:
//页面大小 Rectangle rect = new Rectangle(PageSize.B5.rotate()); //页面背景色 rect.setBackgroundColor(BaseColor.ORANGE); Document doc = new Document(rect); PdfWriter writer = PdfWriter.getInstance(doc, out); //PDF版本(默认1.4) writer.setPdfVersion(PdfWriter.PDF_VERSION_1_2); //文档属性 doc.addTitle("Title@sample"); doc.addAuthor("Author@rensanning"); doc.addSubject("Subject@iText sample"); doc.addKeywords("Keywords@iText"); doc.addCreator("Creator@iText"); //页边空白 doc.setMargins(10, 20, 30, 40); doc.open(); doc.add(new Paragraph("Hello World"));
输出结果:
2、设置密码
核心代码:
PdfWriter writer = PdfWriter.getInstance(doc, out); // 设置密码为:"World" writer.setEncryption("Hello".getBytes(), "World".getBytes(), PdfWriter.ALLOW_SCREENREADERS, PdfWriter.STANDARD_ENCRYPTION_128); doc.open(); doc.add(new Paragraph("Hello World"));
输出结果:
3、添加Page
核心代码:
document.open(); document.add(new Paragraph("First page")); document.add(new Paragraph(Document.getVersion())); document.newPage(); writer.setPageEmpty(false); document.newPage(); document.add(new Paragraph("New page"));
4、添加水印(背景图)
//图片水印 PdfReader reader = new PdfReader(FILE_DIR + "setWatermark.pdf"); PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(FILE_DIR + "setWatermark2.pdf")); Image img = Image.getInstance("resource/watermark.jpg"); img.setAbsolutePosition(200, 400); PdfContentByte under = stamp.getUnderContent(1); under.addImage(img); //文字水印 PdfContentByte over = stamp.getOverContent(2); over.beginText(); BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED); over.setFontAndSize(bf, 18); over.setTextMatrix(30, 30); over.showTextAligned(Element.ALIGN_LEFT, "DUPLICATE", 230, 430, 45); over.endText(); //背景图 Image img2 = Image.getInstance("resource/test.jpg"); img2.setAbsolutePosition(0, 0); PdfContentByte under2 = stamp.getUnderContent(3); under2.addImage(img2); stamp.close(); reader.close();
5、插入Chunk, Phrase, Paragraph, List
核心代码
//Chunk对象: a String, a Font, and some attributes document.add(new Chunk("China")); document.add(new Chunk(" ")); Font font = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE); Chunk id = new Chunk("chinese", font); id.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f); id.setTextRise(6); document.add(id); document.add(Chunk.NEWLINE); document.add(new Chunk("Japan")); document.add(new Chunk(" ")); Font font2 = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE); Chunk id2 = new Chunk("japanese", font2); id2.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f); id2.setTextRise(6); id2.setUnderline(0.2f, -2f); document.add(id2); document.add(Chunk.NEWLINE); //Phrase对象: a List of Chunks with leading document.newPage(); document.add(new Phrase("Phrase page")); Phrase director = new Phrase(); Chunk name = new Chunk("China"); name.setUnderline(0.2f, -2f); director.add(name); director.add(new Chunk(",")); director.add(new Chunk(" ")); director.add(new Chunk("chinese")); director.setLeading(24); document.add(director); Phrase director2 = new Phrase(); Chunk name2 = new Chunk("Japan"); name2.setUnderline(0.2f, -2f); director2.add(name2); director2.add(new Chunk(",")); director2.add(new Chunk(" ")); director2.add(new Chunk("japanese")); director2.setLeading(24); document.add(director2); //Paragraph对象: a Phrase with extra properties and a newline document.newPage(); document.add(new Paragraph("Paragraph page")); Paragraph info = new Paragraph(); info.add(new Chunk("China ")); info.add(new Chunk("chinese")); info.add(Chunk.NEWLINE); info.add(new Phrase("Japan ")); info.add(new Phrase("japanese")); document.add(info); //List对象: a sequence of Paragraphs called ListItem document.newPage(); List list = new List(List.ORDERED); for (int i = 0; i < 10; i++) { ListItem item = new ListItem(String.format("%s: %d movies", "country" + (i + 1), (i + 1) * 100), new Font( Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE)); List movielist = new List(List.ORDERED, List.ALPHABETICAL); movielist.setLowercase(List.LOWERCASE); for (int j = 0; j < 5; j++) { ListItem movieitem = new ListItem("Title" + (j + 1)); List directorlist = new List(List.UNORDERED); for (int k = 0; k < 3; k++) { directorlist.add(String.format("%s, %s", "Name1" + (k + 1), "Name2" + (k + 1))); } movieitem.add(directorlist); movielist.add(movieitem); } item.add(movielist); list.add(item); } document.add(list);
6、插入表格
PdfPTable table = new PdfPTable(3); PdfPCell cell; cell = new PdfPCell(new Phrase("Cell with colspan 3")); cell.setColspan(3); table.addCell(cell); cell = new PdfPCell(new Phrase("Cell with rowspan 2")); cell.setRowspan(2); table.addCell(cell); table.addCell("row 1; cell 1"); table.addCell("row 1; cell 2"); table.addCell("row 2; cell 1"); table.addCell("row 2; cell 2"); document.add(table);
7、表格嵌套
PdfPTable table = new PdfPTable(4); //1行2列 PdfPTable nested1 = new PdfPTable(2); nested1.addCell("1.1"); nested1.addCell("1.2"); //2行1列 PdfPTable nested2 = new PdfPTable(1); nested2.addCell("2.1"); nested2.addCell("2.2"); //将表格插入到指定位置 for (int k = 0; k < 24; ++k) { if (k == 1) { table.addCell(nested1); } else if (k == 20) { table.addCell(nested2); } else { table.addCell("cell " + k); } } document.add(table);
8、设置表头
String[] bogusData = { "M0065920", "SL", "FR86000P", "PCGOLD", "119000", "96 06", "2001-08-13", "4350", "6011648299", "FLFLMTGP", "153", "119000.00" }; int NumColumns = 12; // 12 PdfPTable datatable = new PdfPTable(NumColumns); int headerwidths[] = { 9, 4, 8, 10, 8, 11, 9, 7, 9, 10, 4, 10 }; // percentage datatable.setWidths(headerwidths); datatable.setWidthPercentage(100); datatable.getDefaultCell().setPadding(3); datatable.getDefaultCell().setBorderWidth(2); datatable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER); datatable.addCell("Clock #"); datatable.addCell("Trans Type"); datatable.addCell("Cusip"); datatable.addCell("Long Name"); datatable.addCell("Quantity"); datatable.addCell("Fraction Price"); datatable.addCell("Settle Date"); datatable.addCell("Portfolio"); datatable.addCell("ADP Number"); datatable.addCell("Account ID"); datatable.addCell("Reg Rep ID"); datatable.addCell("Amt To Go "); datatable.setHeaderRows(1); //边框 datatable.getDefaultCell().setBorderWidth(1); //背景色 for (int i = 1; i < 1000; i++) { for (int x = 0; x < NumColumns; x++) { datatable.addCell(bogusData[x]); } } document.add(datatable);
篇幅有限,如果你需要更多操作,可以参考文章:
https://www.cnblogs.com/liaojie970/p/7132475.html如果对 Java、大数据感兴趣请长按二维码关注一波,我会努力带给你们价值。觉得对你哪怕有一丁点帮助的请帮忙点个赞或者转发哦。
关注公众号 【爱编码】 ,回复 2019 有相关资料哦。