java使用itext填充pdf模板文字和图片,并使填充后的模板内容垂直水平居中

一、背景

由于业务需求,我需要将程序的部分数据生成PDF报告以供下载浏览

二、实现方式

  1. 设计一个pdf模板,可以通过pdf编辑工具编辑模板、市面上支持编辑表单的pdf编辑都可以,如Adobe Acrobat DC、万兴PDF、迅捷PDF等等
  2. 通过表单编辑设置表单单元格对应名,后续程序赋值用
    java使用itext填充pdf模板文字和图片,并使填充后的模板内容垂直水平居中_第1张图片
  3. 可以设置文本水平居中(但目前的程序都不支持设置垂直居中,后续想要实现的话需要从程序下手)
    java使用itext填充pdf模板文字和图片,并使填充后的模板内容垂直水平居中_第2张图片
  4. 设置好文本则可以开始编写程序赋值(核心代码)
  //创建A4大小的文档
  Document document = new Document(PageSize.A4);
        document.open();
        //读取现有模板内容(templateFile为模板路径)
        PdfReader reader = new PdfReader(FileUtil.path(templateFile));
        //创建输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //实例化PdfStamper准备编辑pdf内容
        PdfStamper ps = new PdfStamper(reader, bos);
        //获取表单所有元素
        AcroFields fields = ps.getAcroFields();
        //设置具体字体格式编码,不设置的话中文可能会不显示
        BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        /添加替换元素
        fields.addSubstitutionFont(baseFont);
		//data是一个Map 主要存储 key 表单模板中的单元格名 value为想要赋的值,遍历
        for (String key : data.keySet()) {
            String value = data.get(key);
            //个人逻辑,参考即可,对于特定的表单元素设置不同的字体格式大小
            if("r_game".equals(key)) {
            //设置格式
                fields.setFieldProperty(key, "textsize", 35f, null);
            }else if("i_title".equals(key)) {
                fields.setFieldProperty(key, "textsize", 20f, null);
            }else if ("r_image".equals(key)){
                if (!StringUtils.isEmpty(value)){
                //设置添加图片
                    addImageToPdf(fields, ps,value);
                    continue;
                }
            }else if ("r_project_name".equals(key)||"r_header".equals(key)||"r_appraisal".equals(key)){
            //将文本垂直居中添加
                addTextToPdfCenter(fields,ps,value,key,baseFont);
                continue;
            }
            else {
                fields.setFieldProperty(key, "textsize", defaultSize, null);
            }
            fields.setField(key, value);
        }
		//生成的文档可编辑
        ps.setFormFlattening(true);
        //关闭操作
        ps.close();
        //将编辑后的文件输出到outputFile路径下
        OutputStream fos = new FileOutputStream(FileUtil.path(outputFile));
        fos.write(bos.toByteArray());
        bos.close();
        fos.close();
        document.close();
  1. 图片填充到表模板
 private static void addImageToPdf(AcroFields form, PdfStamper stamper, String filePath) throws DocumentException, IOException {

        // 通过域名获取所在页和坐标,左下角为起点
        int pageNo = form.getFieldPositions("r_image").get(0).page;
        Rectangle signRect = form.getFieldPositions("r_image").get(0).position;
        float x = signRect.getLeft()+signRect.getRight();
        float y = signRect.getTop();

        // 读图片
        Image image = Image.getInstance(filePath);
        // 获取操作的页面
        PdfContentByte under = stamper.getOverContent(pageNo);
        // 根据域的大小缩放图片
        image.scaleToFit(signRect.getWidth()/4, signRect.getHeight()/4);
        // 添加图片并设置位置(个人通过此设置使得图片垂直水平居中,可参考,具体情况已实际为准)
        image.setAbsolutePosition(x/2-image.getWidth()/2, y/2+image.getHeight());
        under.addImage(image);
    }
  1. 文本未垂直居中效果如下
    java使用itext填充pdf模板文字和图片,并使填充后的模板内容垂直水平居中_第3张图片

将文本设置为垂直居中

通过获取模板位置,然后重构表单单元格实现垂直居中

  private static void addTextToPdfCenter(AcroFields form, PdfStamper stamper, String text,String fieldName,BaseFont baseFont){
        // 通过模板表单单元格名获取所在页和坐标,左下角为起点
        int pageNo = form.getFieldPositions(fieldName).get(0).page;
        Rectangle signRect = form.getFieldPositions(fieldName).get(0).position;
        // 获取操作的页面
        PdfContentByte contentByte = stamper.getOverContent(pageNo);
        //创建表单
        PdfPTable table = new PdfPTable(1);
        //获取当前模板表单宽度
        float totalWidth = signRect.getRight() - signRect.getLeft() - 1;
        //设置新表单宽度
        table.setTotalWidth(totalWidth);
        //设置中文格式
        Font font = new Font(baseFont);
        //设置单元格格式
        PdfPCell cell = new PdfPCell(new Phrase(text,font));
        //设置单元格高度
        cell.setFixedHeight(signRect.getTop()-signRect.getBottom()-1);
        cell.setBorderWidth(0);
        //设置垂直居中
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        //设置水平居中
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        //添加到表单中
        table.addCell(cell);
        //写入pdf
        table.writeSelectedRows(0, -1, signRect.getLeft(), signRect.getTop(), contentByte);
    }

效果如下
java使用itext填充pdf模板文字和图片,并使填充后的模板内容垂直水平居中_第4张图片

你可能感兴趣的:(itext,java,itext)