栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

poi 导出word文档,替换域(邮件合并)占位符

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

poi 导出word文档,替换域(邮件合并)占位符

java+poi导出word文档,替换占位符
  • 实现步骤目录
    • 1.maven 导入依赖坐标
    • 2.设置邮件合并域(占位符)以WPS为例
      • 2.1 设置域文字及图片展示
    • 3. 工具类,本地测试,浏览器导出下载展示
      • 3.1 main方法代码实现
      • 3.2 浏览器导出实现
      • 3.3 效果展示
    • 4 异常问题描述

实现步骤目录 1.maven 导入依赖坐标
	
		org.apache.poi
		poi
		3.14
	
	
		org.apache.poi
		poi-ooxml
		3.14
	
	
		org.apache.poi
		poi-ooxml-schemas
		3.14
	
	
		org.apache.xmlbeans
		xmlbeans
		2.6.0
	
2.设置邮件合并域(占位符)以WPS为例

配置成功后的图片

2.1 设置域文字及图片展示

WPS文档页面,点击插入,文档部件;再选择域如上图所示,会弹出如下图片:

以上步骤,就实现自定义域的占位符;其他不特别说明,惯例一样的;主要是表格,顾名思义就是表格每一行的数据都存在相同的占位符;且后台必须是List>类型。

3. 工具类,本地测试,浏览器导出下载展示


public static void replaceForm(List paragraphList, Map formData) {
for (XWPFParagraph par : paragraphList) {
List runs = par.getRuns();//获取段落的文本对象
for (XWPFRun run : runs) {
String text = run.getText(0);//获取文本的域的名称
if (text != null) {
for (Map.Entry entry : formData.entrySet()) {//遍历formData
String key = entry.getKey();
Object value = entry.getValue();
if (text.indexOf(key) != -1) {//获取formData的key值是否和域名称相同,相同则替换值
if (value == null) {
run.setText(“”, 0);
} else {
text = text.replace(key, value.toString());
run.setText(text, 0);
break;
}
}
}
}
}
}
}

public static void replaceTable(List tables, List> listMap) {
    for (int tableCount = 1; tableCount < listMap.size(); tableCount++) { //复制添加listMap行数的值
        
        DocumentUtil.insertRow(tables.get(0), 1, tableCount + 1);
    }
    for (XWPFTable xwpfTable : tables) {
        //获取表格行数
        int count = xwpfTable.getNumberOfRows();
        //遍历行
        for (int i = 1; i < count; i++) {
            //获取表格的第i行数
            XWPFTableRow row = xwpfTable.getRow(i);
            //遍历的数据
            Map map = listMap.get(i - 1);
            //获取该行的所有列
            List cells = row.getTableCells();
            //遍历每一列
            for (int j = 0; j < cells.size(); j++) {
                //获取每一列的段落内容
                List paragraphs = cells.get(j).getParagraphs();
                //替换每个段落的占位符
                replaceForm(paragraphs, map);
            }
        }
    }
}

public static Map dataFormat(Map formData) {
    Map map = new HashMap<>();
    for (Map.Entry e : formData.entrySet()) { //格式化参数
        map.put("«" + e.getKey() + "»", e.getValue());
    }
    return map;
}


public static void insertRow(XWPFTable table, int copyRowLIne, int newRowLIne) {
    // 在表格中指定的位置新增一行
    XWPFTableRow targetRow = table.insertNewTableRow(newRowLIne);
    // 获取需要复制行对象
    XWPFTableRow copyRow = table.getRow(copyRowLIne);
    //复制行对象
    targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
    //需要复制的行的列
    List copyCells = copyRow.getTableCells();
    //复制列对象
    XWPFTableCell targetCell = null;
    for (int i = 0; i < copyCells.size(); i++) {
        XWPFTableCell copyCell = copyCells.get(i);
        targetCell = targetRow.addNewTableCell();
        targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
        if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
            targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
            if (copyCell.getParagraphs().get(0).getRuns() != null && copyCell.getParagraphs().get(0).getRuns().size() > 0) {
                List runs = copyCell.getParagraphs().get(0).getRuns();
                String text = "";
                for (XWPFRun xwpfRun : runs) {
                    if (!IsEmptyUtil.isEmpty(xwpfRun.getText(0))) {
                        text = xwpfRun.getText(0);
                        break;
                    }
                }
                XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
                cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
                //获取到复制行的文本,加复制到列的占位符
                cellR.setText(text);
            }
        }
    }
}
3.1 main方法代码实现


public static void main(String[] args) {
String docPath = “D:测试文档.docx”; //io读取路径
Map formData = new HashMap(); //表单数据
formData.put(“«userName»”, “张三”);
formData.put(“«gender»”, “男”);
formData.put(“«hobby»”, “喜欢篮球”);
formData.put(“«address»”, “天桥底下”);
List> listMap = new ArrayList>();//表格列表数据
Map map = new HashMap();
map.put(“«index»”, “1”);
map.put(“«number»”, “3次”);
map.put(“«competition»”, “2020年世界篮球赛”);
map.put(“«result»”, “险胜,没有FMVP”);
map.put(“«remark»”, “要不是王五这个老六裁判,FMVP绝对是我的”);
listMap.add(map);
Map map1 = new HashMap();
map1.put(“«index»”, “2”);
map1.put(“«number»”, “2次”);
map1.put(“«competition»”, “2021年世界杯篮球赛”);
map1.put(“«result»”, “完胜,FMVP”);
map1.put(“«remark»”, “李四,被我张三打自闭”);
listMap.add(map1);
Map map2 = new HashMap();
map2.put(“«index»”, “3”);
map2.put(“«number»”, “4次”);
map2.put(“«competition»”, “2022年世界杯篮球赛”);
map2.put(“«result»”, “完胜,FMVP,三连霸”);
map2.put(“«remark»”, “李四,再次被我张三打自闭”);
listMap.add(map2);
try {
//读取文件
InputStream in = new FileInputStream(docPath);
//加载文档
XWPFDocument doc = new XWPFDocument(in);
//段落标记字符替换
List paragraphList = doc.getParagraphs();
//获取所有表格标记字符替换
List tables = doc.getTables();
//替换段落占位符
DocumentUtil.replaceForm(paragraphList,formData);
//替换表格列表的占位符
DocumentUtil.replaceTable(tables,listMap);
// 输出文档
doc.write(new FileOutputStream(“D:测试文档1.docx”));
doc.close();
} catch (Exception e) { //导出word通常出现的报错,null ,找不到文件,读取不到文件较为多;因此异常捕获;避免html页面停顿或者未响应的不友好出现
System.out.println(“导出word文档错误” + e.getMessage());
}
}

3.2 浏览器导出实现


@RequestMapping(value = “/exportDocument”,method = RequestMethod.GET)
public void exportDocument(HttpServletRequest request, HttpServletResponse response) {
//为了便捷,手动造数据看结果;需要拿真实业务数据的小伙伴,可以根据前端id 查询得出 fromData,listMap,docPath即可
String docPath = “D:测试文档.docx”;
Map formData = new HashMap(); //表单数据
formData.put(“«userName»”, “张三”);
formData.put(“«gender»”, “男”);
formData.put(“«hobby»”, “喜欢篮球”);
formData.put(“«address»”, “天桥底下”);
List> listMap = new ArrayList>();//表格列表数据
Map map = new HashMap();
map.put(“«index»”, “1”);
map.put(“«number»”, “3次”);
map.put(“«competition»”, “2020年世界篮球赛”);
map.put(“«result»”, “险胜,没有FMVP”);
map.put(“«remark»”, “要不是王五这个老六裁判,FMVP绝对是我的”);
listMap.add(map);
Map map1 = new HashMap();
map1.put(“«index»”, “2”);
map1.put(“«number»”, “2次”);
map1.put(“«competition»”, “2021年世界杯篮球赛”);
map1.put(“«result»”, “完胜,FMVP”);
map1.put(“«remark»”, “李四,被我张三打自闭”);
listMap.add(map1);
Map map2 = new HashMap();
map2.put(“«index»”, “3”);
map2.put(“«number»”, “4次”);
map2.put(“«competition»”, “2022年世界杯篮球赛”);
map2.put(“«result»”, “完胜,FMVP,三连霸”);
map2.put(“«remark»”, “李四,再次被我张三打自闭”);
listMap.add(map2);
OutputStream outputStream = null;
try {
//读取文件
InputStream in = new FileInputStream(docPath);
//加载文档
XWPFDocument doc = new XWPFDocument(in);
//段落标记字符替换
List paragraphList = doc.getParagraphs();
//获取所有表格标记字符替换
List tables = doc.getTables();
//替换段落占位符
DocumentUtil.replaceForm(paragraphList,formData);
//替换表格列表的占位符
DocumentUtil.replaceTable(tables,listMap);
String docName = “测试文档”;
String fileName = new String((docName).getBytes(“GB2312”), “ISO-8859-1”) + “.docx”;
outputStream = response.getOutputStream();
response.reset();
response.setHeader(“Content-disposition”, “attachment;fileName=” + fileName);
response.setContentType(“application/x-msdownload”);
doc.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
System.out.println(“导出word文档错误” + e.getMessage());
}
}

3.3 效果展示

4 异常问题描述

输入输出流,常见的异常:读取文件占用、解析替换文件有换行时会报:“null”;
常见的读取文件路径不正确导出替换失败的情况,需要用到的小伙伴们,需要多注意观察。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/961736.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号