【随手记录】POI操作excel及word场景

最近有个需求,需要从多个excel表格源数据里读取内容,输出到word里,形式一份报告。以下是相关操作记录:

1、POM引用:

1
2
3
4
5
6
7
8
9
10
11
<!-- poi 操作word、excel、文档 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.2</version>
</dependency>

2、需要从excel里读取内容有:单元格、表格、图表 这几类,于是定义以下规则:

1
2
3
4
1、${cell,s2,12,27} 获取excel第二个sheet的 12,27单元格值
2、${table,s2,1,3,4,32} 获取excel第二个sheet的 1,3 4,32处表格内容
3、${chart,s2,2} 获取exc第二个sheet的第二个图表数据
4、 运算符,如加、减、乘、除 这种放到里面最后面,${cell,s5,6,8,/10000}

3、读取word和excel数据源

4、遍历word模板,获取段落、表格、图表对象,分别执行替换

1
2
3
4
5
6
// 获取段落
doc.getParagraphs()
// 获取表格
doc.getTables();
// 获取图表
doc..getCharts()

4.1、段落文本替换

通过XWPFParagraph段落对象,获取XWPFRun对象,XWPFRun为段落内一段文字,这里最坑的是目标字符${cell,s2,12,27}会因为在word里多次操作而拆分为多个XWPFRun,

这里采取XWPFParagraph.getText()方法,获取完整段落,判断段落里有没有目标字符,如果有,通过遍历XWPFParagraph包含的XWPFRun,如果XWPFRun包含$,则寻找${cell,s2,12,27}等目标操作符,直到遇到结束符}后,拼接为一个完整目标操作符,通过XWPFRun对象可以替换word模板内容  XWPFRun.setText("xx", 0);

4.2、处理table表格

遇到table对象,则通过遍历循环,获取每一个单元格值,填充到word模板里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List<XWPFParagraph> paragraphs = xwpfTableCell.getParagraphs();
if (paragraphs != null && paragraphs.size() > 0) {
    for (XWPFParagraph paragraph : paragraphs) {
        List<XWPFRun> runs = paragraph.getRuns();
        if (runs != null && runs.size() > 0) {
            for (XWPFRun run : runs) {
                run.setText("", 0);
            }
        }
    }
    // run可以设定字体,cell不行
    XWPFRun run = paragraphs.get(0).createRun();
    run.setFontSize(11);
    run.setText(cellExcelTxt);
} else {
    XWPFRun run = xwpfTableCell.addParagraph().createRun();
    run.setFontSize(11);
    run.setText(cellExcelTxt);
}

 如果直接在word通过POI创建XWPFTable对象,则会出现有一栏多余空白列,需要在word输出前删除掉

4.3、处理chart图表

一开始想从excel把chart输出为图片,然后保存到word里,但是找了一圈发现poi不支持把chart导出为图片,后来发现XSSFChart、XWPFChart对象继承同一个抽象类XDDFChart,可以直接通过以下方法

1
xwpfCharts.get(chartNumInWord++).importContent(chart);

直接从excel把图表复制到word

1
2
3
4
5
6
7
8
for (int i = 0; i < xwpfCharts.size(); i++) {
    XWPFChart xwpfChart = xwpfCharts.get(i);<br>    //针对XWPFChart 在word里面无序的情况,可以通过名称里面的序号排序
    String partName = xwpfChart.getPackagePart().getPartName().toString();
    if (partName != null && partName.contains("chart" + (chartNumInWord))) {
        xwpfChart.importContent(chart);
        break;
    }
}

如果world里排序还是无效,可以给图表加个标题,通过标题唯一性,建立映射关系

1
2
3
4
5
6
7
8
9
10
11
CTChart chartData = xwpfChart.getCTChart();
if (chartData != null && chartData.isSetTitle()) {
    CTTitle title = chartData.getTitle();
    if (title != null && title.isSetTx() && title.getTx().isSetRich()) {
        String partName = title.getTx().getRich().getPArray(0).getRArray(0).getT();
        // 编号比较
        if (partName != null && partName.equals("chart" + (chartNumInWord + 1))) {
            xwpfChart.importContent(chart);
        }
    }
}

5、除此之外,通过XWPFDocument还可以获取以下信息:

1
2
3
4
5
6
.getAllPictures() //获取图片
.getComments() //获取批注
.getEndnotes()   //获取尾注
.getHeaderList() //获取页头
.getStyles()       //获取风格设置
.getFooterList() //获取页脚<br><br>POIXMLProperties poixmlProperties = doc.getProperties();<br>POIXMLProperties.CoreProperties coreProperties = poixmlProperties.getCoreProperties();<br>coreProperties.getCategory(); //分类<br>coreProperties.getCreator(); //创建者,Microsoft Office User<br>coreProperties.getCreated(); //创建时间<br>coreProperties.getTitle(); //标题

 

posted @   空知大仙人  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示