Java动态填充PDF表格

我们经常会看到,一些报名的网站通常都会收集用户的数据,最后把数据填充到表格中以PDF的格式以便用户下载打印。他们是怎么做的呢?这个问题引起了我的兴趣,通过学习和探索,我取得了成功,下面是我的设计过程和思路:

1.使用word设计好表格并转换为PDF格式

2.使用Acrobat设计表单功能打开表格, 创建文本域并设置文本域属性

 

3.利用Java Map集合键值对存储的特点, 将变量值与表单文本域映射, 填充文字

4.计算图片原点位置, 根据下图(图片填充图解)的方法

 

5.设计接口, 从前端获取所需参数, 调通程序

6.完整代码如下:

@PostMapping("/pdf")
    public Result printfPDF(@RequestBody NPCMessageRequest npcMessageRequest) throws IOException {
        System.out.println("人大信息: " +npcMessageRequest);
        String basicPath = System.getProperty("user.dir") ;
        System.out.println("当前项目目录: " + basicPath);
        final String READ_PATH =  basicPath + "/人大议案管理系统人大信息一览表_read.pdf";
        String WRITE_PATH = basicPath + "/PDF/" + fileName + Calendar.getInstance().getTimeInMillis() + npcMessageRequest.getId() + ".pdf";

        String filePath = fileName + npcMessageRequest.getId() + ".pdf";
        PdfReader pdfReader = new PdfReader(READ_PATH);
        PdfWriter pdfWriter = new PdfWriter(WRITE_PATH);
        PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter);
        PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, false);
        PdfFont font = PdfFontFactory.createFont(basicPath + "/STKAITI.TTF");
        DeviceRgb color = new DeviceRgb(0, 0, 0);
        //文本填充
        Map<String, String> map = new HashMap<>();
        map.put("name", npcMessageRequest.getName());
        map.put("telephone", npcMessageRequest.getTelephone());
        map.put("email", npcMessageRequest.getEmail());
        map.put("motto", npcMessageRequest.getMotto());
        String role = npcMessageRequest.getAddress() + "人大代表";
        map.put("role", role);
        map.put("time", new SimpleDateFormat("YYYY-MM-dd").format(new Date()));
        System.out.println("PDF文件导出的时间为: " + new SimpleDateFormat("YYYY-MM-dd").format(new Date()));
        map.put("averageRate", npcMessageRequest.getAverageRate());
        for(Map.Entry<String, String> entry: map.entrySet()){
            form.getFormFields()
                    .get(entry.getKey())
                    .setValue(entry.getValue())
                    .setColor(color)
                    .setFont(font);
        }
        //获取图片元素
        PdfFormField field = form.getField("selfie");
        //获取控件对象
        List<PdfWidgetAnnotation> widgets = field.getWidgets();
        PdfWidgetAnnotation annotation = widgets.get(0);
        //域左、下角顶点坐标
        float x1 = annotation.getRectangle()
                .getAsNumber(0)
                        .floatValue();
        float y1 = annotation.getRectangle()
                .getAsNumber(1)
                .floatValue();

        //域右、上角顶点坐标
        float x2 = annotation.getRectangle()
                .getAsNumber(2)
                .floatValue();
        float y2 = annotation.getRectangle()
                .getAsNumber(3)
                .floatValue();

        //域宽高
        float fieldWidth = x2 - x1;
        float fieldHeight = y2 - y1;

        //创建图片对象
        Image img = new Image(ImageDataFactory.create("/www/wwwroot/vue/dist/" + npcMessageRequest.getSelfie().replace("../", "")));
        System.out.println("图片在本地地址: " +img);
        //图片自适应缩放
        Image image = img.scaleToFit(fieldWidth, fieldHeight);
        //获取图片自适应缩放后的宽高
        float scaleWidth = image.getImageScaledWidth();
        float scaleHeight = image.getImageScaledHeight();
        //计算图片中点位置
        //x坐标 = 域x坐标 + (域宽度 / 2) - (自适应后图片宽度 / 2);
        //y坐标 = 域y坐标 + (域高度 / 2) - (自适应后图片高度 / 2);
        float centerX = x1 + (fieldWidth / 2) - (scaleWidth / 2);
        float centerY = y1 + (fieldHeight / 2) - (scaleHeight / 2);
        //设置图片填充位置
        img.setFixedPosition(centerX, centerY);
        //获取文档对象, 将图片添加到文档
        Document document = new Document(pdfDocument);
        document.add(img);

        //清除表单中默认填充
        form.flattenFields();
        pdfDocument.close();
        pdfReader.close();
        pdfWriter.close();
        String finalUrl = upload(WRITE_PATH);
        return Result.success(finalUrl);
    }
 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值