word模板替换加前台vue展示word并打印

注意:这里使用的word是docx格式的doc的不行

后端:

        pom.xml

<!-- excel工具 -->
<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi-ooxml</artifactId>
</dependency>

        写的工具替换类(从CSDN上找的,原博客找不到了,我在此基础上改动了一些)

package com.xxx.common.utils.poi;

import com.xxx.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author csdn
 * 替换word文字
 */
public class ReplaceWordUtil {

    /**
     * 替换表格内的文字
     * @param data
     * @param sourceFilePath
     * @return
     * @throws Exception
     */
    public static XWPFDocument replaceInTable(Map<String, Object> data ,String sourceFilePath) throws Exception {
        File file = new File(sourceFilePath);
        if(!file.exists()){
           throw new Exception("文件不存在!");
        }
        XWPFDocument document = new XWPFDocument(new FileInputStream(file));
        replaceTableValue(document,data);
        return document;
    }

    /**
     * 替换表格内的文字
     * @param document
     * @param data
     */
    public static void replaceTableValue(XWPFDocument document,Map<String, Object> data){
        //重构map
        buildMap(data);
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        while (tableList.hasNext()) {
            table = tableList.next();
            if (!checkText(table.getText())) {
                continue;
            }
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    if (!checkText(cell.getText())) {
                        continue;
                    }
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();
                    for (XWPFParagraph paragraph : paragraphs) {
                        replaceValue(paragraph, data);
                    }
                }
            }
        }
    }

    /**
     * 构造map,不再用外部替代了
     * @param data
     */
    public static void buildMap(Map<String, Object> data) {
        Iterator<Map.Entry<String, Object>> iterator = data.entrySet().iterator();
        Map<String, Object> newMap = new HashMap<>(data.size());
        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            String newKey = "${" + entry.getKey() + "}";
            newMap.put(newKey, entry.getValue());
            iterator.remove();
        }
        data.putAll(newMap);
    }

    /**
     * 检查文本中是否包含 ${
     * @param text
     * @return
     */
    public static boolean checkText(String text) {
        return text.indexOf("${") != -1;
    }

    /**
     * 替换内容
     * @param paragraph
     * @param textMap
     */
    public static void replaceValue(XWPFParagraph paragraph, Map<String, Object> textMap) {
        XWPFRun run, nextRun;
        String runsText;
        List<XWPFRun> runs = paragraph.getRuns();
        for (int i = 0; i < runs.size(); i++) {
            run = runs.get(i);
            runsText = run.getText(0);
            if (StringUtils.isEmpty(runsText)) {
                continue;
            }
            if (!checkText(runsText)) {
                continue;
            }
            while (!runsText.contains("}")) {
                nextRun = runs.get(i + 1);
                runsText = runsText + nextRun.getText(0);
                //删除该节点下的数据
                paragraph.removeRun(i + 1);
            }
            if (textMap.containsKey(runsText)) {
                run.setText(textMap.get(runsText).toString(), 0);
            } else {
                //如果匹配不到,则塞入空
                run.setText("", 0);
            }
        }
    }
}

word模板(注意一定要是docx的)

 后端接口请求和处理:

 @GetMapping("/getXXXXX")
    public void getXXX(HttpServletResponse response){
        try {
            XXXX xxxx= sqService.getById(12013);
            //这里转为map,去进行匹配
            Map data = JSON.parseObject(JSON.toJSONString(xxxx), Map.class);
            XWPFDocument xwpfDocument = ReplaceWordUtil.replaceInTable(data, 你模板的路径);
            response.setContentType("application/msword");
            response.setCharacterEncoding("utf-8");
            xwpfDocument.write(response.getOutputStream());
        }catch (Exception e){
            System.out.println(e);
        }
    }

前端:

     下载插件:

 npm install docx-preview

 npm install jszip

 #需要打印的再下载这个
 npm install vue-print-nb --save

   接口请求:

        这里主要就写几个页面用到的功能

// 页面
<template>
  <div class="app-container">
    //这个打印我就不多说了,需要打印的自行下载 v-print
    <el-button v-print="'#printWord'"> 打 印 </el-button>
    <div ref="word" id="printWord"></div>
  </div>
</template>

引入axios
import axios from 'axios'

//从后台获取数据的方法
     showWord(){
      const docx = require("docx-preview");
      axios.get(this.wordUrl, {responseType: "blob"}).then((res) => {
          const blob = new Blob([res.data]);
          docx.renderAsync(blob, this.$refs.word).then(this.print(this.$refs.word));
        });
    },

效果展示:

 打印效果展示

--------------------------------------------------------------------------------------

因为前端展示的是转换为html后的数据,所以展示之前填充的数据位置都不准了,现修改为word转换为图片进行打印和展示

pom:

        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>5.2.0</version>
        </dependency>

代码:

    @GetMapping("/getXXXX")
    public String getXXX(XXX) {
        try {
            xxxxx byId = sqService.getById(12014);
            Map data = JSON.parseObject(JSON.toJSONString(byId), Map.class);
          
            XWPFDocument xwpfDocument = ReplaceWordUtil.replaceInTable(data, "模板路径");

            //将word 写入流
            ByteArrayOutputStream wordDocument = new ByteArrayOutputStream();
            xwpfDocument.write(wordDocument);
            
            //读取之前的流
            InputStream inputStream = new ByteArrayInputStream(wordDocument.toByteArray());
            Document document = new Document();
            document.loadFromStream(inputStream,FileFormat.Docx);

            //选择word的第一页进行转换为图片
            BufferedImage bufferedImage = document.saveToImages(0, ImageType.Bitmap);
            ByteArrayOutputStream imgOutStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "PNG", imgOutStream);
            BASE64Encoder encoder = new sun.misc.BASE64Encoder();
            String trim = encoder.encodeBuffer(imgOutStream.toByteArray()).trim();
            String s = trim.replaceAll("\n", "").replaceAll("\r", "");
            return "data:image/png;base64,"+s;
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }

后端返回的是base64的图片,前端怎么展示就不用多说了吧

--------------------------------------------------------------------------------------------------

接下来看似完成了,但因为是word转成图片展示的,导致清晰度不够高,那怎么办?是使用图片清晰化?还是什么?

我的建议是将word转为pdf后文件存放在本地,通过配置negix映射使用浏览器访问打开并打印

    @GetMapping("/getXXXX")
    public String getXXX(XXX) {
        try {
            xxxxx byId = sqService.getById(12014);
            Map data = JSON.parseObject(JSON.toJSONString(byId), Map.class);
          
            XWPFDocument xwpfDocument = ReplaceWordUtil.replaceInTable(data, "模板路径");


            String sendPdfName =  UUID.randomUUID() +".pdf";
            File file = new File(文件夹路径);
            if(!file.isDirectory()){
                file.mkdirs();
            }
            //直接将word转为pdf存储,并返回文件名
            WordUtil.wordToPdf(xwpfDocument,xxxxConfig.getTempFilePath() + sendPdfName);
            return sendPdfName;
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }
package com.xxx.common.utils.poi;

import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.documents.ImageType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;

/**
 * word工具类
 */
public class WordUtil {


    /**
     * 将word 转为pdf 并返回pdf 的名字
     * @param xwpfDocument
     * @param path
     * @return
     * @throws Exception
     */
    public static void wordToPdf(XWPFDocument xwpfDocument,String path) throws Exception{
        ByteArrayOutputStream wordDocument = new ByteArrayOutputStream();
        xwpfDocument.write(wordDocument);
        InputStream inputStream = new ByteArrayInputStream(wordDocument.toByteArray());
        com.spire.doc.Document document = new Document();
        document.loadFromStream(inputStream, FileFormat.Docx);
        document.saveToFile(path,FileFormat.PDF);
    }
}

接着就是在negix内配置 你 xxxxConfig.getTempFilePath() 这个在服务器的路径了

location /tempFilePath/
		{
			alias D:/xxx/temp/xx/;
		}

接着只需要在你前端代码里接收返回时,用浏览器打印就完事了,记得用google浏览器啊

xxxx(query).then(rep =>{
    if (rep) {
      window.open("/tempFilePath/" + rep, "_blank");
    } else {
      this.$message.error("打印出错!");
    }
  })

/--------------------------再补充一个word转pdf的方法----------------------------------------------------------------

下载maven

<dependency>
  <groupId>com.luhuiguo</groupId>
  <artifactId>aspose-words</artifactId>
  <version>22.10</version>
</dependency>

新建license.xml 放在resources下

<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;


public class WordToPdf {

    public static boolean getLicense() {
        boolean result = false;
        try {
            InputStream is = WordToPdf.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    

    /**
     * word转pdf
     * @param inPath word路径
     * @param outPath 输出路径
     * @return
     * @throws Exception
     */
    public static boolean docToPdf(String inPath, String outPath) throws Exception {
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) {
            return false;
        }
        try {
            // 新建一个空白pdf文档
            File file = new File(outPath);
            FileOutputStream os = new FileOutputStream(file);
            // Address是将要被转化的word文档
            Document doc = new Document(inPath);
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            doc.save(os, SaveFormat.PDF);
            os.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值