POI操作PowerPoint自动生成报表

1、需求

接到一个很蛋疼的需求:每天自动查询前一天的运营数据,生成power point图表,发送给相关领导。

ppt有固定模板,只需要变更每张报表的数据源即可。

2、初步思路

操作office组件,第一个能想到的肯定是POI。

但实际上POI对于power point的操作封装的还是很差的,毕竟没谁闲的蛋疼用代码来操作ppt。

POI操作power point更像是在操作XML的每个节点,逐个取值、写入(pptx文件格式本身就是xml)。

POI的maven依赖如下:

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>5.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>5.0.0</version>
		</dependency>

注意要用5.0版本,网上大多数资料里提到的3.17版本,无法读取到图表关联的数据源。

3、Java实现

3-1、获取图表对象
        // 读PPT模板
        File fileIn = new File(PPT_TEMPLATE);
        FileInputStream fin = new FileInputStream(fileIn);
        XMLSlideShow ppt = new XMLSlideShow(fin);
        fin.close();
        // 幻灯片对象
        XSLFSlide slide = ppt.getSlides().get(0);

        // ==============================================
        // 处理下部图表(下idx=4)
        XSLFChart chart = slide.getRelationParts().get(4).getDocumentPart();
        CTPlotArea plot = chart.getCTChart().getPlotArea();
        CTBarChart barChart = plot.getBarChartArray(0);

至于为什么是slide.getRelationParts().get(4)?
呵呵,我特么也不知道我要操作的这个图表的index是几!

方法是debug一下,看slide.getRelationParts()对象的内容,看它下面每一个item的documentPart的Name,是不是“/ppt/charts/chartn.xml”,这对应的是图表。

至于plot、barChart都是啥对象,鬼才知道,反正xml里面节点就是这样的,就一层一层往下找吧,后面要用到。

3-2、更新图表关联的Excel数据源

要修改power point中报表的内容,本质上是修改跟报表绑定的Excel表的数据。

        // 更新图表关联的Excel数据源
        XSSFWorkbook workbook = chart.getWorkbook();
        // "sheet1"
        XSSFSheet sheet = workbook.getSheetAt(0);
        for (int i = 0; i < 10; i++) {
            sheet.getRow(i + 2).getCell(0).setCellValue(mapChartTitle.get(i));
            sheet.getRow(i + 2).getCell(1).setCellValue(mapChartData.get(i));
        }
        workbook.write(chart.getPackagePart().getOutputStream());
3-3、更新ppt缓存

power point这玩意,最x蛋的就是只变更数据源没用,它自己有缓存!幻灯片上展示的数据从缓存来读,如果只改变Excel数据源中的数据,必须点“编辑数据”以后才能触发页面刷新。

        // 更新chart缓存数据
        CTBarSer ser = barChart.getSerList().get(0);
        // 变更坐标轴标题
        for (int i = 0; i < 10; i++) {
            CTStrVal cat = ser.getCat().getStrRef().getStrCache().getPtArray(i);
            cat.setIdx(i);
            cat.setV(mapChartBTitle.get(i));
        }
        // 变更数据
        for (int i = 0; i < 10; i++) {
            CTNumVal val = ser.getVal().getNumRef().getNumCache().getPtArray(i);
            val.setIdx(i);
            val.setV(mapChartBData.get(i).toString());
        }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值