java根据模板导出pdf,并将多个pdf合成一个

前言

项目中,遇到这么一个需求:根据单个模板批量导出pdf,批量导出的pdf要合并成一个pdf进行打印。两个问题点:1、根据模板生成pdf。2、pdf合并

一、前期准备工作(准备pdf模板)

这个问题可以使用itextpdf和Adobe Acrobat 来实现。
1、根据提供的word生成的pdf的模板样式
在这里插入图片描述
2、将其转出为pdf,wps就可以操作
3、用Adobe Acrobat打开该pdf
在这里插入图片描述4、选择工具打开表单
在这里插入图片描述
5、自动检测到一些域但是不全,我们可以自己添加并且编辑相关的属性
在这里插入图片描述

二、整合项目

1、生成pdf

1.1项目依赖

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.3</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

1.2将准备好的模板pdf放入到项目中
在这里插入图片描述
1.3相关代码
1、读取模板以及设置字体

File schoolRollQRCode = QrCodeUtil.generate(studentPdfVo.getSchoolRoll(), 300, 300, FileUtil.file("/qrcode" + imageNumber + ".jpg"));
            map.put("schoolRollQRCode", schoolRollQRCode.getPath());
            org.springframework.core.io.Resource resource = new ClassPathResource("pdf_template/student.pdf");
            PdfReader reader = new PdfReader(resource.getInputStream());
            BaseFont bf = BaseFont.createFont();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            PdfStamper stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            form.addSubstitutionFont(bf);

            float bigFontSize = 10;
            // false可编辑
            stamper.setFormFlattening(true);

2、普通数据的录入,即模板中文本域对应单字段的录入:

        Map<String, String> map1 = new HashMap<>(32);
        imageNumber++;
        File schoolRollQRCode = QrCodeUtil.generate(studentPdfVo.getSchoolRoll(), 300, 300, FileUtil.file("/qrcode" + imageNumber + ".jpg"));
        map.put("schoolRollQRCode", schoolRollQRCode.getPath());
        map.put("schoolRoll", studentPdfVo.getSchoolRoll());
        map.put("name", studentPdfVo.getName());
        map.put("gradeName", studentPdfVo.getGradeName());
 map.forEach((key, value) -> {
    
    
                try {
    
    
                    if ("schoolRollQRCode".equals(key)) {
    
    
                        int pageNo = stamper.getAcroFields().getFieldPositions(key).get(0).page;
                        Rectangle signRect = stamper.getAcroFields().getFieldPositions(key).get(0).position;
                        float x = signRect.getLeft();
                        float y = signRect.getBottom();
                        // 读图片
                        Image image = Image.getInstance(map.get(key));
                        // 获取操作的页面
                        PdfContentByte under = stamper.getOverContent(pageNo);
                        // 根据域的大小缩放图片
                        image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                        // 添加图片
                        image.setAbsolutePosition(x, y);
                        under.addImage(image);
                    } else {
    
    
                        //设置这个表单域的字体
                        form.setFieldProperty(key, "textfont", bfChinese, null);
                        //设置这个表单域的字体大小
                        form.setFieldProperty(key, "textsize", bigFontSize, null);
                        form.setField(key, value);
                    }
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                } catch (DocumentException e) {
    
    
                    e.printStackTrace();
                }
            });

3、二维码图片的录入

int pageNo = stamper.getAcroFields().getFieldPositions(key).get(0).page;
                        Rectangle signRect = stamper.getAcroFields().getFieldPositions(key).get(0).position;
                        float x = signRect.getLeft();
                        float y = signRect.getBottom();
                        // 读图片
                        Image image = Image.getInstance(map.get(key));
                        // 获取操作的页面
                        PdfContentByte under = stamper.getOverContent(pageNo);
                        // 根据域的大小缩放图片
                        image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                        // 添加图片
                        image.setAbsolutePosition(x, y);
                        under.addImage(image);

4、集合的录入

Map<String, List<String>> listMap = new HashMap<>(4);
            if (CollectionUtil.isNotEmpty(nameList)) {
    
    
                listMap.put("Box1", nameList);
            }
listMap.forEach((key, value) -> {
    
    
                if (CollectionUtil.isNotEmpty(value)) {
    
    
                    int pageNo = form.getFieldPositions(key).get(0).page;
                    PdfContentByte pcb = stamper.getOverContent(pageNo);
                    Rectangle signRect = form.getFieldPositions(key).get(0).position;
                    //表格位置
                    int column = 2;
                    int row = value.size();
                    PdfPTable table = new PdfPTable(column);
                    float totalWidth = signRect.getRight() - signRect.getLeft();

                    float[] width = new float[2];
                    width[0] = (totalWidth / 9) * 2;
                    width[1] = (totalWidth / 9) * 7;
                    try {
    
    
                        table.setTotalWidth(width);
                    } catch (DocumentException e) {
    
    
                        e.printStackTrace();
                    }
                    table.setLockedWidth(true);
                    table.setKeepTogether(true);
                    table.setSplitLate(false);
                    table.setSplitRows(true);
                    Font fontProve = new Font(bfChinese, 13, 0);
                    //表格数据填写
                    for (int i = 0; i < row; i++) {
    
    

                        // 第一列
                        String name = value.get(i);
                        Phrase phrase;
                        if ("体检项目".equals(name)) {
    
    
                            phrase = new Phrase(name, new Font(bfChinese, 17, 0));
                        } else {
    
    
                            phrase = new Phrase(name, fontProve);
                        }
                        PdfPCell cell = new PdfPCell(phrase);

                        cell.setBorderWidth(1);
                        cell.setBorderWidthRight(0);
                        cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                        cell.setVerticalAlignment(Element.ALIGN_CENTER);

                        cell.setLeading((float) 3.0, (float) 1.0);
                        cell.setMinimumHeight(30f);
                        table.addCell(cell);
                        // 第二列
                        Phrase phrase2 = new Phrase(null, fontProve);
                        PdfPCell cell2 = new PdfPCell(phrase2);
                        cell2.setBorderWidth(1);
                        cell2.setBorderWidthLeft(0);
                        cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
                        cell2.setVerticalAlignment(Element.ALIGN_CENTER);

                        cell2.setLeading((float) 3.0, (float) 1.0);
                        cell2.setMinimumHeight(30f);
                        table.addCell(cell2);
                    }
                    table.writeSelectedRows(0, value.size(), signRect.getLeft(), signRect.getTop(), pcb);
                }
            });

5、导出结果
在这里插入图片描述

2、pdf合并

2.1项目依赖

<dependency>
            <groupId>com.luhuiguo</groupId>
            <artifactId>aspose-pdf</artifactId>
            <version>23.1</version>
        </dependency>

2.2相关代码

OutputStream out = response.getOutputStream();
            InputStream[] inputStreams = new InputStream[outputStreams.size()];
            int i = 0;
            for (ByteArrayOutputStream byteArrayOutputStream : outputStreams) {
    
    
                // 将输出流转化成输入流
                ByteArrayInputStream swapStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                inputStreams[i] = swapStream;
                i++;
            }
            // 合并pdf
            PdfFileEditor pdfFileEditor = new PdfFileEditor();
            pdfFileEditor.concatenate(inputStreams, out);

2.3最终效果展示
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43945397/article/details/129529571