首页 > 其他分享 >使用Apache POI往word模板中插入数据并转换文档格式

使用Apache POI往word模板中插入数据并转换文档格式

时间:2023-10-13 13:47:15浏览次数:35  
标签:word String 表格 picData void paragraph POI Apache document

word模板报告数据插入及格式转换

1. 向模板内写入数据

1.1 单文本插入

//通过查询得到数据用参数或者对象接收后,与模板内参数对应完成文本插入
String code = usersService.findByCode().getCode();
TestUsers byCode = usersService.findByCode();
Map<String, Object> data = new HashMap<>();
data.put("${barcode}", code);
data.put("${barcode}", byCode.getCode());

效果

image-20231012142506258

1.2 图片插入

1.2.1 根据文件路径插入

 Map<String, Object> picData = new HashMap<>();
        String inspection = "张三";
        String audit = "C:\\Users\\chongchong\\Desktop\\repositories\\img\\shenhe.jpg";
        String source = inspection + File.separator;
        String targer = audit + File.separator;
//判断字符串是否是文件路径,调用不同的文本插入方法,且与模板内设计参数对应
        if(source.matches("^[A-z]:\\\\(.+?\\\\)*$") && targer.matches("^[A-z]:\\\\(.+?\\\\)*$")){
            picData.put("${inspection}", source);
            picData.put("${audit}", targer);
        } else if (source.matches("^[A-z]:\\\\(.+?\\\\)*$")){
            picData.put("${inspection}",source);
            data.put("${audit}",targer.substring(0,targer.length() - 1));
        } else if (targer.matches("^[A-z]:\\\\(.+?\\\\)*$")){
            data.put("${inspection}",source.substring(0,source.length() - 1));
            picData.put("${audit}",targer);
        } else {
            data.put("${inspection}",source);
            data.put("${audit}",targer);
        }

效果

image-20231012142518124

1.2.2 根据网络链接插入

/**
    * @Author: chongchong
    * @Description: 通过获取网络链接图片存储到本地,然后选择插入数据
    * @DateTime: 2023/10/13 9:47
    * @Params: imageUrl:网络链接 localImagePath:本地存储地址
    * @Return void
    */
    public static void UrlImg(String imageUrl,String localImagePath) throws IOException {
        URL url = new URL(imageUrl);
        InputStream in = url.openStream();
        FileOutputStream out = new FileOutputStream(localImagePath);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
    }

效果

image-20231013095501759

1.3 批量文本插入

//通过选中的itemId查询对应的数据 
List<TestItemsDetail> byItemId = itemsDetailService.getByItemId(Long.valueOf(29));
//遍历获取的对象数据,然后向表格内插入数据,此处知23条数据,剔除单独数据插入,具体使用时可以先判断再插入
for (int i = 0; i < byItemId.size() / 2; i++) {
                arrearsList.add(Arrays.asList(byItemId.get(i).getName(),byItemId.get(i).getRefRangeStart(),
                        byItemId.get(byItemId.size() - i - 1).getName(),byItemId.get(byItemId.size() - i -1).getRefRangeStart()));
            }
            arrearsList.add(Arrays.asList(byItemId.get(byItemId.size()/2).getName(),byItemId.get(byItemId.size()/2).getRefRangeStart()));

效果

image-20231012142430656

1.4 写入新的模板

/**
调用创建新报告方法,往其中插入对应的文本、图片等数据,
modelWord:模板word所在路径;
replaceWord:插入数据生成路径;
data:单文本;
picData:图片;
1:默认为1,代表的是批量插入文本所在的第几个表格(从0开始),此处批量插入数据的表格是第二个表格;
arrearsList:批量插入文本;
**/
ReplaceWord.operateWord(modelWord,replaceWord,data, picData,1,arrearsList);

2.根据文件路径转换格式

2.1 转换格式

调用AsposeUtil方法wordToPdf方法进行格式转换

getLicense方法是将格式转换的水印不生成

/**
wordPath:需要转换格式的文件路径("C:\\Users\\chongchong\\Desktop\\repositories\\word\\23分型报告单模板1.docx")
pdfPath:转换格式后的路径("C:\\Users\\chongchong\\Desktop\\repositories\\23分型报告单.pdf")
**/
AsposeUtil.wordToPdf(wordPath,pdfPath);

效果

image-20231012144445138

3.代码

向模板内写入数据方法

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Author: chongchong
 * @DateTime: 2023/10/11 17:10
 * @Description: word模板数据填充
 */
public class ReplaceWordService {

    /**
    * @Author: chongchong
    * @Description: 替换段落文本
    * @DateTime: 2023/10/11 17:11
    * @Params: document docx解析对象 textMap  需要替换的信息集合
    * @Return void
    */
    public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
        // 获取段落集合
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        XWPFParagraph paragraph = null;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            // 判断此段落是否需要替换
            if (checkText(paragraph.getText())) {
                replaceValue(paragraph, textMap);
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 检查文本中是否包含指定的字符(此处为“$”)
    * @DateTime: 2023/10/11 17:12
    * @Params: text
    * @Return boolean
    */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.contains("$")) {
            check = true;
        }
        return check;
    }

    /**
    * @Author: chongchong
    * @Description: 替换图片
    * @DateTime: 2023/10/11 17:12
    * @Params: document picData
    * @throws: Exception
    * @Return 
    */
    public static void changePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        // 获取段落集合
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        XWPFParagraph paragraph;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            // 判断此段落是否需要替换
            String text = paragraph.getText();
            if (checkText(text)) {
                replacePicValue(paragraph, picData);
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 替换表格内的文字
    * @DateTime: 2023/10/11 17:14
    * @Params: document data
    * @Return void
    */
    public static void changeTableText(XWPFDocument document, Map<String, Object> data) {
        // 获取文件的表格
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        // 循环所有需要进行替换的文本,进行替换
        while (tableList.hasNext()) {
            table = tableList.next();
            if (checkText(table.getText())) {
                rows = table.getRows();
                // 遍历表格,并替换模板
                for (XWPFTableRow row : rows) {
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        // 判断单元格是否需要替换
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs) {
                                replaceValue(paragraph, data);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 替换表格内图片
    * @DateTime: 2023/10/11 17:14
    * @Params: document picData
    * @Return void
    */
    public static void changeTablePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        // 获取文件的表格
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        // 循环所有需要进行替换的文本,进行替换
        while (tableList.hasNext()) {
            table = tableList.next();
            if (checkText(table.getText())) {
                rows = table.getRows();
                // 遍历表格,并替换模板
                for (XWPFTableRow row : rows) {
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        // 判断单元格是否需要替换
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs) {
                                replacePicValue(paragraph, picData);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 替换内容
    * @DateTime: 2023/10/11 17:15
    * @Params: paragraph textMap
    * @Return void
    */
    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 (runsText.contains("${") || (runsText.contains("$") && runs.get(i + 1).getText(0).substring(0, 1).equals("{"))) {
                while (!runsText.contains("}")) {
                    nextRun = runs.get(i + 1);
                    runsText = runsText + nextRun.getText(0);
                    //删除该节点下的数据
                    paragraph.removeRun(i + 1);
                }
                Object value = changeValue(runsText, textMap);
                //判断key在Map中是否存在
                if (textMap.containsKey(runsText)) {
                    run.setText(value.toString(), 0);
                } else {
                    //如果匹配不到,则不修改
                    run.setText(runsText, 0);
                }
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 替换图片内容
    * @DateTime: 2023/10/11 17:15
    * @Params: paragraph picData
    * @Return void
    */
    public static void replacePicValue(XWPFParagraph paragraph, Map<String, Object> picData) throws Exception {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            Object value = changeValue(run.toString(), picData);
            if (picData.containsKey(run.toString())) {
                //清空内容
                run.setText("", 0);
                FileInputStream is = new FileInputStream((String) value);
                //规定图片宽度、高度
                int width = Units.toEMU(30), height = Units.toEMU(30);
                //添加图片信息,段落高度需要在模板中自行调整
                run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, (String) value, width, height);
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 匹配参数
    * @DateTime: 2023/10/11 17:16
    * @Params: value textMap
    * @Return java.lang.Object
    */
    public static Object changeValue(String value, Map<String, Object> textMap) {
        Object valu = "";
        for (Map.Entry<String, Object> textSet : textMap.entrySet()) {
            // 匹配模板与替换值 格式${key}
            String key = textSet.getKey();
            if (value.contains(key)) {
                valu = textSet.getValue();
            }
        }
        return valu;
    }

    /**
    * @Author: chongchong
    * @Description: 批量替换表格内容
    * @DateTime: 2023/10/11 17:16
    * @Params: index(表格索引:第几个表格) tableList(批量增加的数据源)
    * @Return void
    */
    public static void replaceTable(XWPFDocument document,int index, List<List<String>> tableList) {
        XWPFTable table = document.getTables().get(index);
        //创建行,根据需要插入的数据添加新行,不处理表头
        /*for (int i = 1; i <= tableList.size(); i++) {
            table.createRow();
        }*/
        //遍历表格插入数据
        List<XWPFTableRow> rows = table.getRows();
        for (int i = 1; i < tableList.size()+1; i++) {
            XWPFTableRow newRow = table.getRow(i);
            List<XWPFTableCell> cells = newRow.getTableCells();
            List<String> rowData = tableList.get(i - 1);
            for (int j = 0; j < rowData.size(); j++) {
                XWPFTableCell cell = cells.get(j);
                String text = rowData.get(j);
                cell.setText(text);
                if (text.equals("阳性")){
                    cell.setColor("ff0000");
                }
                //表格样式一致-->没有此段表格会默认左对齐
                //有此段会使表格格式一致
                /*CTTc cttc = cell.getCTTc();
                CTTcPr ctPr = cttc.addNewTcPr();
                ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);*/
            }
        }
    }

    /**
    * @Author: chongchong
    * @Description: 根据模板所需替换的形式调用不同的方法向模板中添加信息,然后导出写入数据的新的文档
    * @DateTime: 2023/10/11 17:18
    * @Params: data(表格内单文本插入) picData(表格内图片) index(默认:1,即批量插入文本数据的表格) tableList(批量插入文本数据集)
    * @Return void
    */
    public static void operateWord(String modelWord,String replaceWord,Map<String, Object> data,
                                   Map<String, Object> picData,
                                   int index,List<List<String>> tableList){
        try {
            //读取模板word的文件路径
            FileInputStream is = new FileInputStream(modelWord);
            XWPFDocument document = new XWPFDocument(is);
            if (data.size() > 0) {
                // 替换掉表格之外的文本(仅限文本)
                ReplaceWordService.changeText(document, data);
                // 替换表格内的文本对象
                ReplaceWordService.changeTableText(document, data);
            }
            if (picData.size() > 0) {
                // 替换内容图片
                ReplaceWordService.changePic(document, picData);
                // 替换表格内的图片对象
                ReplaceWordService.changeTablePic(document, picData);
            }
            if (tableList.size() > 0) {
                //往表格中批量插入文本
                ReplaceWordService.replaceTable(document,index,tableList);
            }
            //写入数据后的模板存储文件路径
            FileOutputStream out = new FileOutputStream(replaceWord);
            document.write(out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Author: chongchong
     * @Description: 通过获取网络链接图片存储到本地,然后选择插入数据
     * @DateTime: 2023/10/13 9:47
     * @Params: imageUrl:网络链接 localImagePath:本地存储地址
     * @Return void
     */
    public static void UrlImg(String imageUrl,String localImagePath) throws IOException {
        URL url = new URL(imageUrl);
        InputStream in = url.openStream();
        FileOutputStream out = new FileOutputStream(localImagePath);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
    }

}

word文档格式转换pdf方法参考上一篇文章word转pdf:https://www.cnblogs.com/chongchongstyle/p/17761878.html

标签:word,String,表格,picData,void,paragraph,POI,Apache,document
From: https://www.cnblogs.com/chongchongstyle/p/17761889.html

相关文章

  • word转pdf文档
    word转pdf文档1.依赖其中的aspose-words依赖地址:https://releases.aspose.com/java/repo/com/aspose/<!--word文档转化为pdf文档--><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId&g......
  • python实现ppt内容输出为word形式
    一、只输出文本内容frompptximportPresentationfromdocximportDocumentwordfile=Document()#给定ppt文件所在的路径filepath=r"C:\Users\18703\Desktop\智家经分\智家经分v2.pptx"pptx=Presentation(filepath)#遍历ppt文件的所有幻灯片页forslideinppt......
  • python实现docx转pptx(word文档转幻灯片)
    以前都是手工将word内容复制粘贴到ppt中,实在受够了。文心一言真是大忽悠,给的转换方案是用docx2pptx库,然而根本没有这个库,倒是可以用我下面的代码生成这个库:-)网上很多方案是转成图片形式插入ppt,导致无法正常编辑ppt.于是研究出以下方案:1.先将word文档的页面设置改为自定义大小......
  • 使用NPOI修改Excel数据
    读取excel文件阿松大读取excel文件读取excel文件读取excel文件publicvoidSignIn(){Useruser=_userService.GetUserByName(Username);if(user!=null&&user.Password==Password){#region记住登录信息//将当前的配置序列化为j......
  • 2023-10-13 (error) ERR Client sent AUTH, but no password is set ==》redis访问密
    当你尝试在redis终端输入authxxx(auth是固定值,xxx是你的密码),然后终端报错:(error)ERRClientsentAUTH,butnopasswordisset意思:(错误)ERR客户端发送了AUTH,但未设置密码。原因:你没有设置redis访问密码。当然如果你非要设置访问密码,那么你可以在redis根目录找到redis.windo......
  • phpstudy apache跨域访问设置
    phpstudyapache跨域访问设置 HeaderaddAccess-Control-Allow-Origin*HeaderaddAccess-Control-Allow-Methods*HeaderaddAccess-Control-Allow-Headers"Origin,X-Requested-With,Content-Type,Accept,Authorization" ......
  • [论文精读][基于点云的蛋白-配体亲和力]A Point Cloud-Based Deep Learning Strategy
    我需要的信息代码,论文不考虑共价键,每个点包括了六种原子信息,包括xyz坐标,范德华半径,原子重量以及来源(1是蛋白质,-1是配体)。原子坐标被标准化,其它参数也被标准化。对不足1024个原子的的复合体,补0到1024。增加考虑的原子从1024到2048,没有提升,增加原子信息通道,没有提升(见resul......
  • 洛谷P3576 [POI2014] MRO-Ant colony 题解
    MRO-Antcolony根据下取整除法的性质\((\left\lfloor\dfrac{\left\lfloor\dfrac{x}{y}\right\rfloor}{z}\right\rfloor=\left\lfloor\dfrac{x}{yz}\right\rfloor)\),我们可以反向考虑,即从特殊边开始,计算出从每个叶子到特殊边的路径上,要除以的那个分母是什么。这个可以直接一遍df......
  • vue中下载excel文件4种方法,2、通过 a 标签 download 属性结合 blob 构造函数下载发送p
    vue中下载excel文件4种方法,2、通过a标签download属性结合blob构造函数下载发送post请求和后台poi返回文件流实现下载1、通过url下载即后端提供文件的地址,直接使用浏览器去下载通过window.location.href=文件路径下载window.location.href=`${location.origin}/opera......
  • CMD和ENTRYPOINT同时使用会如何?
    一问题CMD和ENTRYPOINT同时使用会如何? 二解答ENTRYPOINT会将CMD中的值作为参数使用 验证如下:dockerfile文件如下:FROMcentos:7ENTRYPOINT["cal"]CMD["cal"]打包成镜像,随后run,结果如下: 三备注可以在run后,添加参数,将CMD中的值覆盖,覆盖后的值,会给ENTERPOINT......