poi编辑word中的chart,对图表数据替换,并刷新图表

最近工作需要做报表导出,再次接触poi,上次用poi的时候还是上次(在前司编辑excel的时候)。

而word呢,数据结构上感觉又比excel复杂,至少我处理的时候认为是这样。

首先看一下要处理的word模板:

 引入依赖:

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

我们首先将word文件读入内存中:

        final String inputUrl = "D:/testCheck/ReportTemp.docx";
        final String outputUrl = "D:/testCheck/ReportDemo.docx";
        InputStream is = new FileInputStream(inputUrl);
        XWPFDocument doc = new XWPFDocument(is);

然后看一下poi读取word的结构。

XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档
XWPFParagraph代表文档、表格、标题等种的段落,由多个XWPFRun组成
XWPFRun代表具有同样风格的一段文本
XWPFTable代表一个表格
XWPFTableRow代表表格的一行
XWPFTableCell代表表格的一个单元格
XWPFChart 表示.docx文件中的图表
XWPFHyperlink 表示超链接
XWPFPicture 代表图片

我所用的样例里面没有图片超链接等,所以没有XWPFPicture XWPFHyperlink 这些东西

这篇要讲的主要是处理chart,文本替换和表格等内容留到下篇,所以我们先获取该word文件中的所有图表:

List<XWPFChart> charts= doc.getCharts();

看下poi在内存中获取到的内容:

 我们成功的获取到了三个图表。

下一步,对图表内嵌的excel中数据进行替换,首先获取第一个,空心的饼图中的excel。

        XWPFChart chart0 = charts.get(0);
        XSSFWorkbook workbook =  chart0.getWorkbook();
        XSSFSheet sheet0 =  workbook.getSheetAt(0);

然后我们观察sheet0对象,可以看到我们已经获取到了内嵌表格的数据。

 与模板中的数据对比

发现他们是一样一样的,然后我们依次修改这些数据

        int grade = 95;
        XSSFCell cell01 = sheet0.getRow(1).getCell(1);
        cell01.setCellValue(grade);
        XSSFCell cell02 = sheet0.getRow(2).getCell(1);
        cell02.setCellValue(100-grade);

到此,保存 通过文件流写入磁盘新的文件。打开生成的新文件后发现,该图表依然没变,但是点击图标编辑数据的一瞬间,发现内嵌excel数据是我们写入的了,图表变成了我们想要的样子!为什么会这样呢?查阅很多资料后明白了,修改数据之后还要替换图表中的数据并且重新画图。

        //获取横轴纵轴
        XDDFChartData chartData0 = chart0.getChartSeries().get(0);
        XDDFChartData.Series s0 = chartData0.getSeries().get(0);
        //设置图表中的数据,从内嵌的表格sheet0中获取
        XDDFDataSource cat0 = XDDFDataSourcesFactory.fromStringCellRange(sheet0,
                new CellRangeAddress(1, 2, 0, 0));
        XDDFNumericalDataSource val0 = XDDFDataSourcesFactory.fromNumericCellRange(sheet0,
                new CellRangeAddress(1,2,1,1));
        //替换原有的数据
        s0.replaceData(cat0,val0);
        //设置标题
        chart0.setTitleText("图1 总分" + grade);
        //重新绘图
        chart0.plot(chartData0);

其中CellRangeAddress方法可以从其定义看出,四个参数的含义分别是首行,终行,首列,终列。

CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)

这样我们就可以得到想要的空心饼图。

柱形图和实心饼图类似,不再赘述,代码如下:

       //第二个图表,各科分数
        XWPFChart chart1 = charts.get(1);
        XSSFWorkbook workbook1 = chart1.getWorkbook();
        XSSFSheet sheet1 = workbook1.getSheetAt(0);
        XSSFCell cell10 = sheet1.getRow(1).getCell(0);
        cell10.setCellValue("数学");
        XSSFCell cell11 = sheet1.getRow(1).getCell(1);
        cell11.setCellValue(80);
        //因为原模板中 只插入了一行数据,所以这里需要用createCell方法新建一个单元格,直接getCell会报空指针
        XSSFCell cell20 = sheet1.getRow(2).createCell(0);
        cell20.setCellValue("英语");
        XSSFCell cell21 = sheet1.getRow(2).createCell(1);
        cell21.setCellValue(38);

        XDDFChartData chartData1 = chart1.getChartSeries().get(0);
        XDDFChartData.Series s1 = chartData1.getSeries().get(0);
        XDDFDataSource cat1 = XDDFDataSourcesFactory.fromStringCellRange(sheet1,
                new CellRangeAddress(1, 6, 0, 0));
        XDDFNumericalDataSource val1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1,
                new CellRangeAddress(1,6,1,1));
        s1.replaceData(cat1,val1);

        chart1.setTitleText("图2 各科分数");
        chart1.plot(chartData1);


        //修改第三个图
        XWPFChart chart2 = charts.get(2);
        XSSFWorkbook workbook2 = chart2.getWorkbook();
        XSSFSheet sheet2 = workbook2.getSheetAt(0);

        sheet2.getRow(1).getCell(0).setCellValue("数学");
        sheet2.getRow(1).getCell(1).setCellValue(80);
        XSSFCell cell220 = sheet2.getRow(2).createCell(0);
        cell220.setCellValue("英语");
        XSSFCell cell221 = sheet2.getRow(2).createCell(1);
        cell221.setCellValue(38);
        XDDFChartData chartData2 = chart2.getChartSeries().get(0);
        XDDFChartData.Series s2 = chartData2.getSeries().get(0);
        XDDFDataSource cat2 = XDDFDataSourcesFactory.fromStringCellRange(sheet2,
                new CellRangeAddress(1, 3, 0, 0));
        XDDFNumericalDataSource val2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet2,
                new CellRangeAddress(1,3,1,1));
        s2.replaceData(cat2,val2);
        chart2.setTitleText("图3 各科占比");
        chart2.plot(chartData2);

最终结果: 

周末更新,修改表格数据,和文本替换。

参考:使用POI导出Word(含表格)的实现方式及操作Word的工具类 - 黄小葱 - 博客园使用POI导出Word(含表格)的实现方式及操作Word的工具类https://www.cnblogs.com/sun-flower1314/p/10128796.htmljava使用poi在word中生成柱状图、折线图、饼图、柱状图+折线图组合图、动态表格、文本替换、图片替换、更新内置Excel数据、更新插入的文本框内容、合并表格单元格;_u014427811的博客-CSDN博客_java word 图表本文参考地址:https://blog.csdn.net/wangxiaoyingWXY/article/details/95377533在参考文章的基础上,增加了扩展。感谢被参考的老哥。代码直接从日记中复制过来的,不方便复制的可以私信发示例代码,不知道怎么上传附件了。代码有的地方写的不合理或者错误的,请原谅没有检查仔细;说明:在poi3.x的版本中,没有对图表的支持,至少目前为止没...https://blog.csdn.net/u014427811/article/details/100771314

项目想实现excel图表POI不支持所以想到了这个方法。放上来抛砖引玉,感兴趣的欢迎大家交流 注:-------------------------------------------------------------------------- 其实现原理和利用JavaScript实现客户端绘图完全一样。后台代码将输入 写入特定区域,前端脚本在页面载入时执行脚本绘图。大家都是做B/S开发 的,这方面的只是不需要我多说了吧。 如果我们让一个HTML页面在载入时显示一个提示框用后台编程是不现实的 所以我们就动态生成一段JS: window.onload=function(){ ...... } 用Java输出图表的场景和这个一样,POI、JXL对操作Excel图表无能为力 但Excel支持脚本的,也有工作表载入事件,所以也可以用同样的原理实现 只不过这次客户端不再是浏览器而是Excel应用程序。 这样交代的应该比较明白了吧,请不要再留言抱怨没有Java代码了,因为 这根本跟java代码没多大关系,后台的代码所做的工作仅仅是写入必要的 数据数据的解析和绘图操作是在VBA完成的 ---2009-12-18 今天查找资料翻出来了这段代码,发现里边的类确实是空的,我说怎么总挨骂 呢,当时肯定打包的时候晕透了把另一个本该删除的类打包进去了。我无法 替换文件只能把java代码贴上来了,请自己修改模板文件的路径。 package com.test.poi; import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; public class PoiChart { public static void main(String[] args){ try{ POIFSFileSystem fs=new POIFSFileSystem(new FileInputStream("E:/王建波_bak/我的练习/Module.xls")); HSSFWorkbook wb=new HSSFWorkbook(fs); HSSFSheet sheet=wb.getSheetAt(0); HSSFRow row; //写入表头 String[] aTblHeaders=new String[]{ "姓名","语文","数学","英语" }; row=sheet.createRow(0); for(int i=0,len=aTblHeaders.length;i<len;i++){ row.createCell((short)i).setCellValue(aTblHeaders[i]); } //向模板写入数据 String[] aNames=new String[]{ "张飞","刘备","关羽","曹操","孙权","吕布" }; for(int i=0,nRowLen=aNames.length;i<nRowLen;i++){ row=sheet.createRow(i+1); row.createCell((short)0).setCellValue(aNames[i]); for(int j=1,nColLen=aTblHeaders.length;j<nColLen;j++){ row.createCell((short)j).setCellValue(Math.floor(Math.random()*100)); } } //输出文件 FileOutputStream fout=new FileOutputStream("d:/chart.xls"); wb.write(fout); fout.close(); }catch(Exception e){ e.printStackTrace(); } } }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值