根据word模板生成word和PDF

根据word模板生成word和PDF

需求:有一个固定的合同模板,在vue前台填写指定的信息,替换合同模板指定的内容

我们使用的默认模板内容如图:

根据word模板生成word和PDF_第1张图片

我们在前端填写的字段就是合同名称、项目名称和项目金额,vue将这些内容填写到name、project、money字段,进行替换。

数据库表内容:(仅作为测试demo使用,需根据具体需求更改)

根据word模板生成word和PDF_第2张图片

前端界面:

路径字段不应该展示,这里只是为了演示方便
根据word模板生成word和PDF_第3张图片

点击合同签订按钮,跳转字段填写界面
根据word模板生成word和PDF_第4张图片

这里填写的信息会传递到后台,进行替换,并且把替换后的word以及pdf路径生成到wordpath和pdfpath字段里,进而实现下载功能。

前台代码:(基础信息查询界面不再展示,只展示)



//js连接后台路径,另一个"@/api/project/filepdf"不写了
export function updateFile(data) {
  return request({
    url: '/project/api/process/',
    method: 'post',
    data: data,
  })
}

后台代码:

这段代码的大致流程是:

  1. 接收前端传递过来的Filepdf对象,其中包含了Word文件的路径、姓名、项目名称和金额等信息。
  2. 将Word文件读取为XWPFDocument对象,遍历其中的所有段落,并判断是否包含需要替换的文本串,如果包含则进行文本替换。
  3. 将替换后的XWPFDocument写入到新的Word文件中(命名方式为"word_当前时间戳.docx")。
  4. 将新生成的Word文件读取为另一个XWPFDocument对象,然后将其转换为PDF格式,并将PDF输出到新的文件中(命名方式为"pdf_当前时间戳.pdf")。
  5. 将新生成的Word和PDF文件的访问路径(“http://127.0.0.1:9300/statics/具体名称”)分别设置到Filepdf对象的Wordpath和Pdfpath字段中。
  6. 更新Filepdf对象,并返回操作成功的信息。
 // 文件处理接口
    @PostMapping("/process")
    public AjaxResult processFile(@RequestBody Filepdf filepdf) throws IOException {


        //接收到前台传递过来的filepdf
        //把 filepdf的Wordpath字段设置为模板的路径
        filepdf.setWordpath("D:\\YinHe-Yqgbathe\\ruoyi-modules\\ruoyi-project\\src\\main\\java\\com\\ruoyi\\project\\module\\gs\\template.docx");
        //wordfilePath设置为模板的路径
        String wordfilePath = filepdf.getWordpath();
        //声明fis,以字节流的形式读取文件,fis 代表一个 FileInputStream 对象,它指向要读取的 Word 文件。
        FileInputStream fis = new FileInputStream(wordfilePath);
        //创建一个 XWPFDocument 实例,该实例与指定的 Word 文件建立了连接,XWPFDocument 是一个用于处理 .docx 文件的类
        XWPFDocument document = new XWPFDocument(fis);
        //使用 for 循环遍历 XWPFDocument 中的所有段落
        for (XWPFParagraph paragraph : document.getParagraphs()) {
        //使用 XWPFParagraph 类中的 getParagraphText() 方法来获取当前处理的段落中包含的文本内容
            String paragraphText = paragraph.getParagraphText();
            // 判断该段落中是否包含需要替换的文本串,因为我们要替换name,project,money,具体根据需求更改
            if (paragraphText.contains("name") || paragraphText.contains("project") || paragraphText.contains("money")) {
        //使用while是为了替换每一个,防止漏掉
                boolean foundMatch = true;
                while (foundMatch) {
                    foundMatch = false;
                    //使用 XWPFParagraph 类中的 getRuns() 方法获取当前处理的段落中包含的所有文本样式 Run
                    for (XWPFRun run : paragraph.getRuns()) {
                        //调用 getText(int pos) 方法可以获取该文本样式 Run 中从指定位置(pos)开始的所有文本信息,并将其作为一个字符串返回
                        String runText = run.getText(0);
                        //以下三个if是具体替换,eg.如果有name就替换为filepdf.getHname(),就是前端接受的内容
                        if (runText != null && runText.contains("name")) {
                            runText = runText.replaceFirst("name", filepdf.getHname());
                            run.setText(runText, 0);
                            foundMatch = true;
                        }
                        if (runText != null && runText.contains("project")) {
                            runText = runText.replaceFirst("project", filepdf.getProject());
                            run.setText(runText, 0);
                            foundMatch = true;
                        }
                        if (runText != null && runText.contains("money")) {
                            runText = runText.replaceFirst("money", filepdf.getMoney());
                            run.setText(runText, 0);
                            foundMatch = true;
                        }
                    }
                }
            }
        }
        //关闭FileInputStream
        fis.close();
        //设置path1为D:/ruoyi/uploadPath,因为若依默认存储为D:/ruoyi/uploadPath,可以根据配置文件进行更改
        String path = "D:/ruoyi/uploadPath";
        //拼接具体名称,按照时间命名,并且存储到相应位置
        String newwordFilePath = path + "/word_" + System.currentTimeMillis() + ".docx";
        FileOutputStream fos = new FileOutputStream(newwordFilePath);
        document.write(fos);
        fos.close();

        XWPFDocument doc = new XWPFDocument(new FileInputStream(newwordFilePath));// docx
        //转为pdf
        // 创建输出流,设置名称
        String newPdfFilePath = path + "/pdf_" + System.currentTimeMillis() + ".pdf";

        String outputPDFFiles = newPdfFilePath; // 输出的.pdf文件路径
        FileOutputStream foss = new FileOutputStream(outputPDFFiles);

        PdfOptions options = PdfOptions.create();
        // 将 .docx 转换为 .pdf
        PdfConverter.getInstance().convert(doc, foss, options);

        // 关闭输出流
        foss.close();

        System.out.println("转换完成");

        //因为前端不可以下载绝对路径,所以要拼接成http://127.0.0.1:9300/statics/***的形式,***为具体名称(D:/ruoyi/uploadPath后的名称)

        //设置wordpath字段
        int index = newwordFilePath.lastIndexOf("/");
        String q = newwordFilePath.substring(index);

        filepdf.setWordpath("http://127.0.0.1:9300/statics" + q);
        //设置pdfpath字段
        int index1 = newPdfFilePath.lastIndexOf("/");
        String q1 = newPdfFilePath.substring(index1);

        filepdf.setPdfpath("http://127.0.0.1:9300/statics" + q1);
        // 执行更新
        filepdfService.updateFilepdf(filepdf);
        return AjaxResult.success();

    }

注:需要在pom.xml中导入指定依赖,内容为:


    org.apache.poi
    poi-ooxml
    3.15



    org.apache.pdfbox
    pdfbox
    2.0.13



    org.apache.poi
    poi
    3.15



    fr.opensagres.xdocreport
    org.apache.poi.xwpf.converter.pdf
    1.0.6



    org.apache.pdfbox
    xmpbox
    2.0.13



    fr.opensagres.xdocreport
    org.apache.poi.xwpf.converter.pdf
    1.0.6



    org.apache.pdfbox
    xmpbox
    2.0.13

你可能感兴趣的:(word,pdf,vue.js,spring,boot,apache)