背景:前段时候公司要开发合同PDF,公司可以根据该PDF打印出一份合同。合同中有些地方需要动态生成,因此并不能完全使用Pdf模板的形式来进行开发,比如某个PDF页面需要动态生成表格,那个这个页面就不能使用pdf模板来进行开发。但是合同中大部分都是固定不变的,所以可以将固定分离出来,只用专心开发动态部分,最后再将这些PDF合并成一个PDF就行了。
知识点:
1. 使用Itext5.5动态生成表格
2. PDF合并
3.设置页面大小:查看Itext的源码可以发现 PageSize.A4 = new Rectangle(595.0F, 842.0F);//像素
工程的目录结构如下:
GenerateContactPDFUtil.java 中的代码如下:
package com.utils; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.itextpdf.text.Chunk; import com.itextpdf.text.Document; import com.itextpdf.text.Font; import com.itextpdf.text.PageSize; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Phrase; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfWriter; import com.vo.PolicyPlan; /** * *生成 合同Pdf */ public class GenerateContactPDFUtil { public static void main(String[] args) throws Exception{ String fullPath = "table.pdf"; //合同基本信息 Map<String, String> contactInfo = new HashMap<String, String>(); contactInfo.put("firstParty", "高雄"); contactInfo.put("secondParty", "北京"); contactInfo.put("peopleCount", "100"); contactInfo.put("year", "2015"); contactInfo.put("month", "8"); contactInfo.put("day", "22"); //表头 String[] policyPlans = {"险种","保险责任","保险费"}; //数据 List<PolicyPlan> policyPlanList = new ArrayList<PolicyPlan>(); PolicyPlan policyPlan1 = new PolicyPlan("CAG13","意外身故", "455"); //实体类 PolicyPlan policyPlan2 = new PolicyPlan("CAG14","民用或商用航班飞机意外伤残", "455"); PolicyPlan policyPlan3 = new PolicyPlan("CAG15","营运水上交通工具意外伤残", "455"); PolicyPlan policyPlan4 = new PolicyPlan("CAG15","营运水上交通工具意外身故", "455"); PolicyPlan policyPlan5 = new PolicyPlan("CAG16","出行无忧", "1000"); policyPlanList.add(policyPlan1); policyPlanList.add(policyPlan2); policyPlanList.add(policyPlan3); policyPlanList.add(policyPlan4); policyPlanList.add(policyPlan5); createContactPdfHead(fullPath, contactInfo, policyPlans, policyPlanList); } /** * tableHead 表头数据 * tableDataList 表中数据 * return PDF名字 */ public static void createContactPdfHead(String fullPath, Map<String, String> contactInfo, String[] tableHeads, List<PolicyPlan> tableDataList) throws Exception{ //Document doc = new Document(PageSize.B5); Document document = new Document(PageSize.A4, 80, 80, 90, 25); //设置成A4纸大小,内容距左右上下的距离 try { PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(fullPath)); document.open();//打开PDF文件进行编辑 // 插入一个段落 //设置中文字体 BaseFont baseFontChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //1.标题字体 Font headFont = new Font(baseFontChinese , 16 , Font.BOLD); Font headFontTitle = new Font(baseFontChinese , 14 , Font.BOLD); //2.正文字体 Font contentFontFirst = new Font(baseFontChinese , 12 , Font.NORMAL); Font contentFontSecond = new Font(baseFontChinese , 10 , Font.NORMAL); //设置标题 Paragraph head1 = new Paragraph("通过Email方式提交保全申请的授权协议", headFont); head1.setAlignment(1);//设置段落居中 head1.setSpacingAfter(50); document.add(head1); //甲方 Chunk theFirstParty = new Chunk("甲方: ", headFontTitle); Chunk theFirstPartyName = new Chunk(contactInfo.get("firstParty") , headFontTitle); theFirstPartyName.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 theFirstPartyName.setUnderline(0.5f, -3f); Phrase party = new Phrase(); party.add(theFirstParty); party.add(theFirstPartyName); Paragraph head2 = new Paragraph(party); head2.setSpacingAfter(30); document.add(head2); //乙方 Chunk theSecondParty = new Chunk("乙方: 海康人寿保险有限公司 ", headFontTitle); Chunk theSecondPartyName1 = new Chunk(contactInfo.get("secondParty") , headFontTitle); theSecondPartyName1.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 theSecondPartyName1.setUnderline(0.5f, -3f); Chunk theSecondPartyName2 = new Chunk("分公司" , headFontTitle); Phrase secondParty = new Phrase(); secondParty.add(theSecondParty); secondParty.add(theSecondPartyName1); secondParty.add(theSecondPartyName2); Paragraph head3 = new Paragraph(secondParty); head3.setSpacingAfter(30); document.add(head3); //甲方在某某保险有限公司 分公司为 名员工投保了团体人寿保险,生效日期 年 月 日。 Chunk contentParty1 = new Chunk(" 甲方在某某保险有限公司 ", contentFontFirst); Chunk contentParty2 = new Chunk(contactInfo.get("secondParty"), contentFontFirst); contentParty2.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 contentParty2.setUnderline(0.5f, -3f); Chunk contentParty3 = new Chunk("分公司为 ", contentFontFirst); // String companyPersonCountStr = "100";//100个人 Chunk contentParty4 = new Chunk(contactInfo.get("peopleCount"), contentFontFirst); contentParty4.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 contentParty4.setUnderline(0.5f, -3f); Chunk contentParty5 = new Chunk("名员工投保了团体人寿保险," , contentFontFirst); //生效日期 年 月 日。 Chunk effectiveDate = new Chunk("生效日期 ", contentFontFirst); // String yearStr = "2014"; Chunk yearParty = new Chunk(contactInfo.get("year"), contentFontFirst); yearParty.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 yearParty.setUnderline(0.5f, -3f); Chunk yearPartyName = new Chunk("年 ", contentFontFirst); // String monthStr = "12"; Chunk monthParty = new Chunk(contactInfo.get("month"), contentFontFirst); monthParty.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 monthParty.setUnderline(0.5f, -3f); Chunk monthPartyName = new Chunk("月 ", contentFontFirst); // String dayStr = "12"; Chunk dayParty = new Chunk(contactInfo.get("day"), contentFontFirst); dayParty.setTextRise(1); //第一个参数:下划线粗细, 第二个参数:下划线Y轴位置 dayParty.setUnderline(0.5f, -3f); Chunk dayPartyName = new Chunk("日 ", contentFontFirst); Phrase contentPhrase = new Phrase(); contentPhrase.add(contentParty1); contentPhrase.add(contentParty2); contentPhrase.add(contentParty3); contentPhrase.add(contentParty4); contentPhrase.add(contentParty5); contentPhrase.add(effectiveDate); contentPhrase.add(yearParty); contentPhrase.add(yearPartyName); contentPhrase.add(monthParty); contentPhrase.add(monthPartyName); contentPhrase.add(dayParty); contentPhrase.add(dayPartyName); Paragraph head4 = new Paragraph(contentPhrase); head4.setSpacingAfter(10); document.add(head4); //保险方案: Paragraph insuredPlanParagraph = new Paragraph("保险方案:",contentFontFirst); insuredPlanParagraph.setIndentationLeft(20);//设置左侧缩进E insuredPlanParagraph.setSpacingAfter(10); document.add(insuredPlanParagraph); PdfPTable policyPlanTable = new PdfPTable(tableHeads.length); //设置表格有多少列 int width[] = {20,60,20};//设置每列宽度比例 policyPlanTable.setWidths(width); policyPlanTable.setWidthPercentage(100);//占页面宽度比例 //设置表格中单元格的属性,所有单元格都可以使用 PdfPCell pdfPCell = new PdfPCell();//创建一个单元格 //设置字体水平居中 pdfPCell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);//设置水平对齐 //设置字体垂直对齐居中 pdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); //保险方案内容: for(String head : tableHeads){ pdfPCell.setPhrase(new Phrase(head , contentFontFirst)); policyPlanTable.addCell(pdfPCell); } policyPlanTable.completeRow(); for(PolicyPlan policyPlan : tableDataList){ pdfPCell.setPhrase(new Phrase(policyPlan.getRiskCode(), contentFontFirst)); policyPlanTable.addCell(pdfPCell); pdfPCell.setPhrase(new Phrase(policyPlan.getLiability(), contentFontFirst)); policyPlanTable.addCell(pdfPCell); pdfPCell.setPhrase(new Phrase(policyPlan.getFee(), contentFontFirst)); policyPlanTable.addCell(pdfPCell); policyPlanTable.completeRow();//完成行 } document.add(policyPlanTable); //团体告知: Paragraph groupInformingParagraph = new Paragraph("团体告知:",contentFontFirst); groupInformingParagraph.setIndentationLeft(20);//设置左侧缩进E groupInformingParagraph.setSpacingBefore(20); groupInformingParagraph.setSpacingAfter(10); document.add(groupInformingParagraph); //团体告知内容: //1.设置表格属性 PdfPTable groupInformingTable = new PdfPTable(2); int groupInfowidth[] = {85,15};//设置每列宽度比例 groupInformingTable.setWidths(groupInfowidth); groupInformingTable.setWidthPercentage(100);//占页面宽度比例 //1.设置单元格样式 //1.1informingInfo style PdfPCell informingInfoPdfPCell = new PdfPCell();//创建一个单元格 //设置字体水平居中 informingInfoPdfPCell.setHorizontalAlignment(PdfPCell.LEFT);//设置左对齐 //设置字体垂直对齐居中 informingInfoPdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); //1.2 select style PdfPCell checkBoxPdfPCell = new PdfPCell();//创建一个单元格 //设置字体水平居中 checkBoxPdfPCell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);//设置水平对齐 //设置字体垂直对齐居中 checkBoxPdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); //1.第一条 informingInfoPdfPCell.setPhrase(new Phrase("1、 目前是否有正在病假中(产假除外),且不在岗时间达到或超过10个工作日的人员?", contentFontSecond)); groupInformingTable.addCell(informingInfoPdfPCell); checkBoxPdfPCell.setPhrase(new Phrase("囗是 囗否" , contentFontSecond)); groupInformingTable.addCell(checkBoxPdfPCell); groupInformingTable.completeRow(); //2.第二条 informingInfoPdfPCell.setPhrase(new Phrase("2、 目前是否有需要长期(一年累计超过30天)接受住院治疗的人员?", contentFontSecond)); groupInformingTable.addCell(informingInfoPdfPCell); checkBoxPdfPCell.setPhrase(new Phrase("囗是 囗否" , contentFontSecond)); groupInformingTable.addCell(checkBoxPdfPCell); groupInformingTable.completeRow(); //3.第三条 informingInfoPdfPCell.setPhrase(new Phrase("3、 近期1年内是否有因患疾病而不能全勤或全量工作,实际工作时长或工作量低于正常1/2的人员?", contentFontSecond)); groupInformingTable.addCell(informingInfoPdfPCell); checkBoxPdfPCell.setPhrase(new Phrase("囗是 囗否" , contentFontSecond)); groupInformingTable.addCell(checkBoxPdfPCell); groupInformingTable.completeRow(); //第4条 informingInfoPdfPCell.setPhrase(new Phrase("4、 目前或过去是否有以下情况被保险人人员? \n (1)曾接受器官移植手术或造血干细胞移植手术、主动脉手术、冠状动脉搭桥术或冠状动脉支架植入术;\n (2)腕关节或踝关节近躯干端以上完全缺失、深度昏迷状态、双耳失聪或双目失明、严重Ⅲ度烧伤、智力或神经障碍、语言能力丧失。", contentFontSecond)); groupInformingTable.addCell(informingInfoPdfPCell); checkBoxPdfPCell.setPhrase(new Phrase("囗是 囗否" , contentFontSecond)); groupInformingTable.addCell(checkBoxPdfPCell); groupInformingTable.completeRow(); //第五条 informingInfoPdfPCell.setPhrase(new Phrase("5、 有无员工的职业涉及或接触任何危险物(化学物质、爆炸物、有毒物质或其他危险物)、高空作业、潜水或水下作业、隧道坑道或井下作业等危险工作?", contentFontSecond)); groupInformingTable.addCell(informingInfoPdfPCell); checkBoxPdfPCell.setPhrase(new Phrase("囗是 囗否" , contentFontSecond)); groupInformingTable.addCell(checkBoxPdfPCell); groupInformingTable.completeRow(); document.add(groupInformingTable); } catch (Exception e) { e.printStackTrace(); } finally { document.close(); } } }
生成的PDF见附件。。。。
问题:
1.在使用itext5.5 时 中文不显示。
解决:在使用Itext5.5时,就不能使用老版本itext-asian.jar包了,应该使用更新版本的itext-asian.jar。细心的你可以发现老板的itext-asian与新版本的itext-asian的结构不一样。附件中提供了与itext5.5匹配的itext-asian供大家下载。