Java exports pdf based on template and combines multiple pdfs into one

Preface

In the project, I encountered such a requirement: export pdfs in batches according to a single template, and the pdfs exported in batches should be combined into one pdf for printing. Two problems: 1. Generate pdf based on the template. 2. PDF merge

1. Preparatory work (preparing pdf template)

This problem can be achieved using itextpdf and Adobe Acrobat.
1. Generate the pdf template style based on the provided word.
Insert image description here
2. Convert it to pdf, which can be operated by wps.
3. Open the pdf with Adobe Acrobat.
Insert image description here4. Select the tool to open the form
Insert image description here
. 5. Some fields are automatically detected but incomplete. We You can add and edit related attributes yourself
Insert image description here

2. Integration projects

1. Generate pdf

1.1 Project dependencies

<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 Put the prepared template pdf into the project
Insert image description here
1.3 Related code
1. Read the template and set the font

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. Entry of ordinary data, that is, entry of a single field corresponding to the text field in the template:

        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. Input of QR code pictures

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. Entry of collections

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. Export results
Insert image description here

2. PDF merge

2.1 Project dependencies

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

2.2 Related code

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 Final effect display
Insert image description here

Guess you like

Origin blog.csdn.net/weixin_43945397/article/details/129529571