Java实现PDF合同生成

由于在工作中遇到了合同套打的需求,于是在之前 pdfBox获取关键字坐标 的基础上实现了,根据 pdf 模版来套打合同。

PDF合同表单生成

首先,需要确定合同是否可以套打,如果合同格式固定,需要添加数据内容一般不发生变化,则可以通过 生成表单域 来创建合同模板。

如何生成表单域

  1. 使用 pdf 工具打开 合同模板.pdf,此处使用的是 Adobe Acrobat,当然也可以使用其他pdf阅读器。
  2. 点击菜单 准备表单 ,然后如下图所示,会自动将下划线变为 文本域,如果没有也可以手动添加。
  3. 同时也会有其他如 单选按钮、复选框等表单控件。
    在这里插入图片描述

生成模版

具体实现的代码如下所示:

工具方法
	/**
	 * 填充pdf模板的表单域生成新的pdf文件
	 *
	 * @param template
	 * @param font
	 * @param data
	 * @param target
	 * @param formFlattening
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static File generatePDF(String template, String font, JSONObject data, File target, boolean formFlattening)
			throws IOException, DocumentException {
		PdfReader reader = new PdfReader(template);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		BaseFont bf = BaseFont.createFont(font, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		PdfStamper ps = new PdfStamper(reader, bos);
		AcroFields fields = ps.getAcroFields();
		ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
		fontList.add(bf);
		fields.setSubstitutionFonts(fontList);
		for (String key : data.keySet()) {
			String value = data.getString(key);
			// 设置复选框以及单选框
			if (AcroFields.FIELD_TYPE_CHECKBOX == fields.getFieldType(key)
					|| AcroFields.FIELD_TYPE_RADIOBUTTON == fields.getFieldType(key)) {
				// 为单选框赋值,需要设置
				if("On".equals(value))
				    fields.setField(key, value, true);
				else
				    fields.setField(key, value, false);
			} else {
				// 为字段赋值,注意字段名称是区分大小写的
			    fields.setField(key, value);
			}
		}
		// 表单域是否能再次赋值
		ps.setFormFlattening(formFlattening);
		ps.close();
		reader.close();
		FileUtils.writeByteArrayToFile(target, bos.toByteArray());
		return target;
	}
// 为单选框赋值,需要设置
if("On".equals(value))
    fields.setField(key, value, true);
else
    fields.setField(key, value, false);

此处设置在模板中 如下图所示:

在这里插入图片描述

水印实现

有些时候,需要为生成的pdf文件增加水印,具体的方法如下:

/*
* 水印生成
* @return
* @throws
* @author TomatoYan
*/
public void waterMark(PdfReader pdfReader, PdfStamper stamper, String waterMark) throws IOException, DocumentException {
    int interval = 50;
    BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
    Rectangle pageRect = null;
    PdfGState gs = new PdfGState();
    //设置透明度
    gs.setFillOpacity(0.3f);
    gs.setStrokeOpacity(0.4f);
    int total = pdfReader.getNumberOfPages() + 1;
    JLabel label = new JLabel();
    FontMetrics metrics;
    int textH = 0;
    int textW = 0;
    label.setText(waterMark);
    metrics = label.getFontMetrics(label.getFont());
    textH = metrics.getHeight();
    textW = metrics.stringWidth(label.getText());
    
    PdfContentByte under;
    for (int i = 1; i < total; i++) {
    pageRect = pdfReader.getPageSizeWithRotation(i);
    under = stamper.getOverContent(i);
    under.saveState();
    under.setGState(gs);
    under.beginText();
    under.setFontAndSize(base, 20);
    //设置水印颜色
    under.setColorFill(BaseColor.BLACK);
    // 水印文字成45度角倾斜
    for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 3) {
        for (int width = interval + textW; width < pageRect.getWidth() + textW; width = width + textW * 2) {
            under.showTextAligned(Element.ALIGN_LEFT, waterMark, width - textW, height - textH, 45);
            break;
        }
            break;
        }
        // 添加水印文字
        under.endText();
    }
}

水印生成可以放在工具方法中。

主函数
    /**
        参数:
        模板路径:templateDir
        模版文件名称:合同模板.pdf
        字体文件名称:simkai.ttf
        生产文件路径:outDir
        模版填充数据(表单域内容):键值对 data()
    */
    public static void main(String[] args) throws IOException, DocumentException {
		String templateDir = "D:/testpdf/";
		String outDir = "D:/testpdf/";
		generatePDF(templateDir + "合同模板.pdf", templateDir + "simkai.ttf", data(),
				new File(outDir + "result_" + System.currentTimeMillis() + ".pdf"), true);
	}
表单域内容
    public static JSONObject data() {
		JSONObject data = new JSONObject();
		data.put("name", "张三");
		data.put("bank_name", "番茄银行");
		data.put("amt", "1000.00");
		return data;
	}

表单域的填充内容为 Json格式的键值对,键值代表的是在模板PDF中表单的名称。

至此pdf的合同模板就完成了。可以结合之前的 pdfBox获取关键字坐标 文章为pdf合同增加电子签章。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值