感谢以下博客
1.java使用poi操作world生成饼图,柱状图,折线图,组合图:二_不知所终的博客-CSDN博客2.java使用poi在word中生成柱状图、折线图、饼图、柱状图+折线图组合图、动态表格、文本替换、图片替换、更新内置Excel数据、更新插入的文本框内容、合并表格单元格;_u014427811的博客-CSDN博客
本文参考以上两个博客,并做了部分修改做了记录
解决的问题
1.填充数据后,图例却没动态改变,还是模板里的图例。
数据分析时,需要往图形缓存里赋值图例标题
2.动态删除图表,如有要求,图表没有数据时动态删除图表。
通过图形所在段落位置删除的,没找到其他方法。
图形的位置是通过一段文字位置的找到,比如我的图形在“1)到访游客规模”下面,我先找到这个文字的位置,文字的位置+1就是我图形的位置。哈哈,有点牵强,但是没找到其他办法。
获取图片的位置
private Integer getParagraphIndex(List<XWPFParagraph> xwpfParagraphList,String mark) { for (int i=0;i<xwpfParagraphList.size();i++){ XWPFParagraph paragraph=xwpfParagraphList.get(i); List<XWPFRun> xwpfRuns= paragraph.getRuns(); String runStr=""; for (int z=0; z<xwpfRuns.size(); z++) { runStr+=xwpfRuns.get(z).toString(); } if(mark.equals(runStr)){ return i+1; } } return null; }
3.假如我们模板某个折线图有四条数据,但实际我们填充的数据只填充了两条,最后生成的图表里会有四条数据,前两条就是我们实际的数据,后两条我们填充数据,模板数据却保留了。
新增图标数据前,先删除调模板里边的数据,不知道为啥滴倒着删,正着顺序会乱。。。
测试类
说明:dataSource是数据源,可通过调接口获取json格式数据
wordTemplete可配置系统参数里,定义图标位置及类型等,可动态改变word模板里的图形,不用改动代码。
package com.asiainfo.srd.bd.report.controller; import com.alibaba.fastjson.JSONObject; import com.asiainfo.srd.bd.common.utils.StringUtils; import com.asiainfo.srd.bd.report.domain.ChartModel; import com.asiainfo.srd.bd.report.domain.ChartsEnum; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.XWPFChart; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Test { public static void main(String[] args) throws IOException, InvalidFormatException { //获取word模板 InputStream docis = new FileInputStream("E:\\报告新.docx"); //转成word XWPFDocument doc = new XWPFDocument(docis); List<XWPFChart> charts = doc.getCharts(); Map<String, XWPFChart> chartsMap = new HashMap<String, XWPFChart>(); for (XWPFChart chart : charts) { String s = chart.toString(); String key = s.replaceAll("Name: ", "") .replaceAll(" - Content Type: application/vnd\\.openxmlformats-officedocument\\.drawingml\\.chart\\+xml", "").trim(); System.out.println("key:" + key); chartsMap.put(key, chart); } String dataSorce = "{\n" + "\t\"model\": {\n" + "\t\t\"textParams\": {\n" + "\t\t\t\"p1\": \"2020\",\n" + "\t\t\t\"p2\": \"2021\"\n" + "\t\t},\n" + "\t\t\"chartsModel\": [\n" + "\t\t\t[\n" + "\t\t\t\t{\n" + "\t\t\t\t\t\"xAxis\": {\n" + "\t\t\t\t\t\t\"月份\": \"2021年10月1日\"\n" + "\t\t\t\t\t},\n" + "\t\t\t\t\t\"data\": {\n" + "\t\t\t\t\t\t\"到访游客规模\": \"100.0\"\n" + "\t\t\t\t\t}\n" + "\t\t\t\t},\n" + "\t\t\t\t{\n" + "\t\t\t\t\t\"xAxis\": {\n" + "\t\t\t\t\t\t\"月份\": \"2021年10月2日\"\n" + "\t\t\t\t\t},\n" + "\t\t\t\t\t\"data\": {\n" + "\t\t\t\t\t\t\"到访游客规模\": \"200\"\n" + "\t\t\t\t\t}\n" + "\t\t\t\t}\n" + "\t\t\t\t{\n" + "\t\t\t\t\t\"xAxis\": {\n" + "\t\t\t\t\t\t\"月份\": \"2021年10月3日\"\n" + "\t\t\t\t\t},\n" + "\t\t\t\t\t\"data\": {\n" + "\t\t\t\t\t\t\"到访游客规模\": \"300\"\n" + "\t\t\t\t\t}\n" + "\t\t\t\t},\n" + "\t\t\t\t{\n" + "\t\t\t\t\t\"xAxis\": {\n" + "\t\t\t\t\t\t\"月份\": \"2021年10月4日\"\n" + "\t\t\t\t\t},\n" + "\t\t\t\t\t\"data\": {\n" + "\t\t\t\t\t\t\"到访游客规模\": \"400\"\n" + "\t\t\t\t\t}\n" + "\t\t\t\t}\n" + "\t\t\t]\n" + "\t\t]\n" + "\t}\n" + "}"; //格式化系统参数 String wordTemplete = "{\n" + "\t\"textMap\": {\n" + "\t\t\"param1\": \"p1\"\n" + "\t},\n" + "\t\"chartsMap\": [\n" + "\t\t{\n" + "\t\t\t\"dataSourceIndex\": 0,\n" + "\t\t\t\"chartIndex\": 1,\n " + "\t\t\t\"chartType\": 3\n" + "\t\t}" + "\t]\n" + "}"; System.out.println(wordTemplete); Map mapObj = JSONObject.parseObject(wordTemplete, Map.class); Map<String, Object> textMap = (Map<String, Object>) mapObj.get("textMap"); List<Map<String, Object>> chartsList = (List<Map<String, Object>>) mapObj.get("chartsMap"); //格式数据源 Map dataSorceMap = JSONObject.parseObject(dataSorce, Map.class); Map model = (Map) dataSorceMap.get("model"); Map<String, Object> textParams = (Map<String, Object>) model.get("textParams"); List<List<Map<String, Map<String, String>>>> chartsModelSorce = (List<List<Map<String, Map<String, String>>>>) model.get("chartsModel"); for (String key : textMap.keySet()) { //key为文档上变量 //变量对应的值 Object o = textParams.get(textMap.get(key)); } for (Map<String, Object> map : chartsList) { if (StringUtils.isNotEmpty(map.get("chartIndex").toString()) && StringUtils.isNotEmpty(map.get("chartType").toString()) && StringUtils.isNotEmpty(map.get("dataSourceIndex").toString())) { //图形在word模板中的位置 String chartIndex = map.get("chartIndex").toString(); //图形的类型,如折线图,饼形图等 String chartType = map.get("chartType").toString(); //取数据源的位置 int dataSourceIndex = Integer.valueOf(map.get("dataSourceIndex").toString()); //组织数据 List<Map<String, Map<String, String>>> list = chartsModelSorce.get(dataSourceIndex); List<String> titleList = new ArrayList<String>(); List<String> numberList = new ArrayList(); List<Map<String, String>> sourceModelList = new ArrayList<>(); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { Map<String, Map<String, String>> m = list.get(i); Map<String, String> xAxis = m.get("xAxis"); Map<String, String> data = m.get("data"); if (i == 0) { titleList.addAll(new ArrayList(xAxis.keySet())); numberList.addAll(new ArrayList(xAxis.keySet())); titleList.addAll(new ArrayList(data.keySet())); numberList.addAll(new ArrayList(data.keySet())); } Map<String, String> sourceModeMap = new HashMap<>(); sourceModeMap.putAll(xAxis); sourceModeMap.putAll(data); sourceModelList.add(sourceModeMap); } //数据源 ChartModel chartModel = new ChartModel(); chartModel.setNumberList(numberList); chartModel.setTitleList(titleList); chartModel.setSourceModelList(sourceModelList); // chartModel.setSingleChart(chartsMap, chartIndex, 0, ChartsEnum.getInstance(chartType)); chartModel.executeFillModel("sheet1"); } } } try (FileOutputStream fos = new FileOutputStream("E://test.docx")) { doc.write(fos); doc.write(fos); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // System.out.println(textMap.toString()); } }
工具类
1.chartModel.class
package com.asiainfo.srd.bd.report.domain; import lombok.Getter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.XWPFChart; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * @author BM_hyjw * 图表要填充的数据格式 */ @Slf4j @Getter @ToString public class ChartModel { /** * 标记 用来记录当前是否是单元素的图表 */ private Boolean isSingle = true; /** * 内置表格页名 */ private String sheetName; /** * 图表 */ private XWPFChart xwpfChart; /** * 具体图 */ private List<XmlObject> xmlObjectList = new ArrayList<>(); /** * 绘制区域图 */ private CTChart ctChart; /** * 标题 */ private List<String> titleList; /** * 数据源对应的key */ private List<String> numberList; /** * 填充的数据源 */ private List<Map<String, String>> sourceModelList; /** * 目标数据 */ private List<ChartsEnum> chartsEnumList; /** * 赋值 替换目标 * @param numberList */ public void setNumberList(List<String> numberList){ this.numberList = numberList; } /** * 赋值 数据源 * @param sourceModelList */ public void setSourceModelList(List<Map<String, String>> sourceModelList){ this.sourceModelList = sourceModelList; } /** * 赋值 标题 * @param titleList */ public void setTitleList(List<String> titleList){ this.titleList = titleList; } /** * 单个赋值 图表 * @param charts 所有可绘制区域 * @param chartSeat 要操作的图表中可绘制区域位置 * @param xmlObjSeat 图表在可绘制区域中的位置 * @param chartsEnum 目标的表格类型 */ public void setSingleChart(Map<String,XWPFChart> charts,String chartSeat,int xmlObjSeat,ChartsEnum chartsEnum){ List<ChartsEnum> chartsEnumList = Arrays.asList(chartsEnum); /** * 封装基础数据 */ this.packageBasic(charts, chartSeat,chartsEnumList); /** * 获得目标图表 */ XmlObject targetChart = chartsEnum.getTargetChart(chartSeat, this.ctChart, xmlObjSeat); this.xmlObjectList = Arrays.asList(targetChart); //当前是单元素 this.isSingle = true; } /** * 组合赋值 图表 * @param charts 所有可绘制区域 * @param chartSeat 要操作的图表中可绘制区域位置 * @param xmlObjSeat 图表在可绘制区域中的位置 * @param chartsEnumList 目标的表格类型 */ public void setComBiChart(Map<String,XWPFChart> charts,String chartSeat,int xmlObjSeat,List<ChartsEnum> chartsEnumList){ /** * 封装基础数据 */ this.packageBasic(charts, chartSeat,chartsEnumList); /** * 获得目标图表 */ this.xmlObjectList.clear(); chartsEnumList.stream().forEach(x->{ XmlObject targetChart = x.getTargetChart(chartSeat,this.ctChart, xmlObjSeat); this.xmlObjectList.add(targetChart); }); //当前不是单元素 this.isSingle = false; } /** * 封装部分基础数据 * @param charts * @param chartSeat * @param chartsEnumList */ private void packageBasic(Map<String,XWPFChart> charts, String chartSeat,List<ChartsEnum> chartsEnumList) { if(CollectionUtils.isEmpty(charts)){ throw new RuntimeException("模板中图表元素为null; !!!ctChart:null"); } if(CollectionUtils.isEmpty(chartsEnumList)){ throw new RuntimeException("图表目标为null;!!!chartsEnum:null"); } /** * 目标 */ this.chartsEnumList = chartsEnumList; /** * 第N个位置图表 */ this.xwpfChart = charts.get("/word/charts/chart"+chartSeat+".xml"); /** * 第N个位置可绘制区域的图表 */ this.ctChart = this.xwpfChart.getCTChart(); } /** * 执行模板数据源填充 * @param sheetName 展示数据excel页名字 */ public void executeFillModel(String sheetName) throws IOException, InvalidFormatException { this.sheetName = sheetName; //异常校验 String s = this.isSingle ? this.abnormalCheckSingle() : this.abnormalCheckComBi(); //执行填充数据 ChartsEnum.refreshExcel(this); for (int i = 0; i < chartsEnumList.size(); i++) { ChartsEnum chartsEnum = chartsEnumList.get(i); chartsEnum.fillModel(this,this.getXmlObjectList().get(i),i); } // //标题 // List<String> titleList = getTitleList(); } /** * 异常校验 */ private String abnormalCheckSingle() { // if(CollectionUtils.isEmpty(this.numberList)){ // throw new RuntimeException("数据源比对为null; !!!numberList:null"); // } // if(CollectionUtils.isEmpty(this.titleList)){ // throw new RuntimeException("标题为null; !!!titleList:null"); // } // if(CollectionUtils.isEmpty(this.sourceModelList)){ // throw new RuntimeException("数据源为null; !!!sourceModelList:null"); // } if(Objects.isNull(this.xwpfChart)){ throw new RuntimeException("模板中图表元素为null; !!!xwpfChart:null"); } if(CollectionUtils.isEmpty(this.xmlObjectList)){ throw new RuntimeException("模板中具体图表为null;!!!xmlObjectList:null"); } if(CollectionUtils.isEmpty(this.chartsEnumList)){ throw new RuntimeException("图表目标为null;!!!chartsEnum:null"); } if(Objects.isNull(this.ctChart)){ throw new RuntimeException("图表绘制区域为null;!!!chartsEnum:null"); } if(StringUtils.isEmpty(this.sheetName)){ throw new RuntimeException("内置excel页名为null;!!!sheetName:null"); } return null; } /** * 异常校验 */ private String abnormalCheckComBi() { this.abnormalCheckSingle(); if (this.xmlObjectList.size() < 2) { throw new RuntimeException("组合图中【图表】元素不足两个; !!!xmlObjectList.size !> 2"); } if (this.sourceModelList.stream().filter(x->{return x.keySet().size() >= 3;}).collect(Collectors.toList()).size() < 0) { throw new RuntimeException("组合图中【数据源】元素不足两个; !!!sourceModelList.map.keySet.size !>= 3"); } if (this.numberList.size() < 3) { throw new RuntimeException("组合图中【数据源对应的key】元素不足两个; !!!numberList.size !>= 3"); } return null; } }
2.ChartsEnums.java
package com.asiainfo.srd.bd.report.domain; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.usermodel.XWPFChart; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlString; import org.apache.xmlbeans.impl.values.XmlComplexContentImpl; import org.openxmlformats.schemas.drawingml.x2006.chart.*; import org.openxmlformats.schemas.drawingml.x2006.chart.impl.CTBarChartImpl; import org.openxmlformats.schemas.drawingml.x2006.chart.impl.CTLineChartImpl; import org.openxmlformats.schemas.drawingml.x2006.chart.impl.CTPieChartImpl; import org.openxmlformats.schemas.drawingml.x2006.chart.impl.CTScatterChartImpl; import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.util.List; import java.util.Map; /** * @author BM_hyjw * 解析world 中图表 */ @Slf4j @Getter public enum ChartsEnum { /** * 饼图 */ PIE(CTPieChart.class, CTPieChartImpl.class,"1","饼图"){ /** * 填充模板数据 * @param chartModel 图表和数据源 * @param xmlObject 当前元素 * @param bias 偏向值 */ @Override public void fillModel(ChartModel chartModel, XmlObject xmlObject, int bias) { if (!this.chartImplClazz.getName().equals(xmlObject.getClass().getName())) { //当前循环中图表操作不属于当前枚举 ChartsEnum.getEnumByChartImplClazz(((XmlComplexContentImpl)xmlObject).getClass()) .fillModel(chartModel, xmlObject, bias); return; } CTPieChart pieChart = (CTPieChart)xmlObject; List<CTPieSer> serList = pieChart.getSerList(); //更新数据区域 for (int i = 0; i < serList.size(); i++) { //数据填充 // CTPieSer ser = pieChart.getSerArray(i); CTAxDataSource cat = ser.getCat(); CTNumDataSource val = ser.getVal(); // this.dataAnalysisFill(chartModel,i,bias,cat,val); CTSerTx tx = ser.getTx(); this.dataAnalysisFill(chartModel,i,bias,cat,val,tx); } } /** * 得到目标位置的图表 * @param ctChart 可绘制区域图表 * @param xmlObjSeat 目标图标位置位置 * @return */ @Override public XmlObject getTargetChart(String chartSeat, CTChart ctChart, int xmlObjSeat) { try { CTPieChart pieChart = ctChart.getPlotArea().getPieChartArray(xmlObjSeat); return pieChart; }catch (Exception e){ throw new RuntimeException("当前位置【" + chartSeat + "】不存在【饼图】!!!"); } } }, /** * 柱图 */ COLUMN(CTBarChart.class, CTBarChartImpl.class,"2","柱形图") { /** * 填充模板数据 * @param chartModel 图表和数据源 * @param bias 偏向值 */ @Override public void fillModel(ChartModel chartModel,XmlObject xmlObject,int bias) { if (!this.chartImplClazz.getName().equals(xmlObject.getClass().getName())) { //当前循环中图表操作不属于当前枚举 ChartsEnum.getEnumByChartImplClazz(((XmlComplexContentImpl)xmlObject).getClass()) .fillModel(chartModel, xmlObject, bias); return; } CTBarChart chart = (CTBarChart)xmlObject; List<CTBarSer> serList = chart.getSerList(); //更新数据区域 for (int i = 0; i < serList.size(); i++) { //数据填充 // CTBarSer ser = chart.getSerArray(i); CTAxDataSource cat = ser.getCat(); CTNumDataSource val = ser.getVal(); // this.dataAnalysisFill(chartModel,i,bias,cat,val); CTSerTx tx = ser.getTx(); this.dataAnalysisFill(chartModel,i,bias,cat,val,tx); } } /** * 得到目标位置的图表 * @param ctChart 可绘制区域图表 * @param xmlObjSeat 目标图标位置位置 * @return */ @Override public XmlObject getTargetChart(String chartSeat, CTChart ctChart, int xmlObjSeat) { try { CTBarChart barChart = ctChart.getPlotArea().getBarChartArray(xmlObjSeat); return barChart; }catch (Exception e){ throw new RuntimeException("当前位置【" + chartSeat + "】不存在【柱状图】!!!"); } } }, /** * 折线图 */ LINE_CHART(CTLineChart.class, CTLineChartImpl.class,"3","折线图"){ /** * 填充模板数据 * @param chartModel 图表和数据源 * @param xmlObject 当前元素 * @param bias 偏向值 */ @Override public void fillModel(ChartModel chartModel,XmlObject xmlObject,int bias) { if (!this.chartImplClazz.getName().equals(xmlObject.getClass().getName())) { //当前循环中图表操作不属于当前枚举 ChartsEnum.getEnumByChartImplClazz(((XmlComplexContentImpl)xmlObject).getClass()) .fillModel(chartModel, xmlObject, bias); return; } CTLineChart chart = (CTLineChart)xmlObject; List<CTLineSer> serList = chart.getSerList(); //更新数据区域 for (int i = 0; i < serList.size(); i++) { //数据填充 // CTLineSer ser = chart.getSerArray(i); CTAxDataSource cat = ser.getCat(); CTNumDataSource val = ser.getVal(); CTSerTx tx = ser.getTx(); this.dataAnalysisFill(chartModel,i,bias,cat,val,tx); } } /** * 得到目标位置的图表 * @param ctChart 可绘制区域图表 * @param xmlObjSeat 目标图标位置位置 * @return */ @Override public XmlObject getTargetChart(String chartSeat, CTChart ctChart, int xmlObjSeat) { try { CTLineChart lineChart = ctChart.getPlotArea().getLineChartArray(xmlObjSeat); return lineChart; }catch (Exception e){ throw new RuntimeException("当前位置【" + chartSeat + "】不存在【折线图】!!!"); } } }, /** * 散点图 */ SCATTER(CTScatterChart.class, CTScatterChartImpl.class,"4","散点图"){ /** * 填充模板数据 * @param chartModel 图表和数据源 * @param xmlObject 当前元素 * @param bias 偏向值 */ @Override public void fillModel(ChartModel chartModel,XmlObject xmlObject,int bias) { if (!this.chartImplClazz.getName().equals(xmlObject.getClass().getName())) { //当前循环中图表操作不属于当前枚举 ChartsEnum.getEnumByChartImplClazz(((XmlComplexContentImpl)xmlObject).getClass()) .fillModel(chartModel, xmlObject, bias); return; } CTScatterChart chart = (CTScatterChart)xmlObject; List<CTScatterSer> serList = chart.getSerList(); //更新数据区域 for (int i = 0; i < serList.size(); i++) { //数据填充 // CTScatterSer ser = chart.getSerArray(i); CTAxDataSource cat = ser.getXVal(); CTNumDataSource val = ser.getYVal(); CTSerTx tx = ser.getTx(); this.dataAnalysisFill(chartModel,i,bias,cat,val,tx); } } /** * 得到目标位置的图表 * @param ctChart 可绘制区域图表 * @param xmlObjSeat 目标图标位置位置 * @return */ @Override public XmlObject getTargetChart(String chartSeat, CTChart ctChart, int xmlObjSeat) { try { CTScatterChart scatterChart = ctChart.getPlotArea().getScatterChartArray(xmlObjSeat); return scatterChart; }catch (Exception e){ throw new RuntimeException("当前位置【" + chartSeat + "】不存在【散点图】!!!"); } } }, ; /** * 图表对象 */ public Class<? extends XmlObject> chartClazz; private String code; private String msg; /** * 图表实现对象 */ public Class<? extends XmlComplexContentImpl> chartImplClazz; ChartsEnum(Class<? extends XmlObject> chartClazz, Class<? extends XmlComplexContentImpl> chartImplClazz,String code, String msg){ this.chartClazz = chartClazz; this.chartImplClazz = chartImplClazz; this.code = code; this.msg = msg; } /** * 根据code获取枚举实例 * @param code * @return */ public static ChartsEnum getInstance(String code){ for (ChartsEnum each : ChartsEnum.values()){ if (each.getCode().equals(code)){ return each; } } return null; } /** * 填充模板数据 * @param chartModel 图表和数据源 * @param xmlObject 当前元素 * @param bias 偏向值 */ public abstract void fillModel(ChartModel chartModel,XmlObject xmlObject,int bias); /** * 得到目标位置的图表 * @param chartSeat 位置 * @param ctChart 可绘制区域图表 * @param xmlObjSeat 目标图标位置位置 */ public abstract XmlObject getTargetChart(String chartSeat,CTChart ctChart,int xmlObjSeat); /** * 根据值来源得到对应的 图表实现对象 * @param chartImplClazz 图表实现对象 * @return */ public static ChartsEnum getEnumByChartImplClazz(Class<? extends XmlComplexContentImpl> chartImplClazz){ for (ChartsEnum value : ChartsEnum.values()) { if (value.getChartImplClazz().equals(chartImplClazz)){ return value; } } return null; } /** * 根据值来源得到对应的 图表对象 * @param chartClazz 图表对象 * @return */ public static ChartsEnum getEnumByChartClazz(Class<? extends XmlObject> chartClazz){ for (ChartsEnum value : ChartsEnum.values()) { if (value.getChartClazz().equals(chartClazz)){ return value; } } return null; } /** * 刷新内置excel数据 * @return */ public static boolean refreshExcel(ChartModel chartModel) throws IOException, InvalidFormatException { List<String> titleList = chartModel.getTitleList(); List<String> numberList = chartModel.getNumberList(); List<Map<String, String>> sourceModelList = chartModel.getSourceModelList(); XWPFChart xwpfChart = chartModel.getXwpfChart(); boolean result = true; Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet(chartModel.getSheetName()); //根据数据创建excel第一行标题行 if(titleList.size()>0){ //没有数据的建立空表 sheet.createRow(0).createCell(0).setCellValue(""); sheet.getRow(0).createCell(1).setCellValue(""); } for (int i = 0; i < titleList.size(); i++) { if (sheet.getRow(0) == null) { sheet.createRow(0).createCell(i).setCellValue(titleList.get(i) == null ? "" : ""); } else { sheet.getRow(0).createCell(i).setCellValue(titleList.get(i) == null ? "" : titleList.get(i)); } } //遍历数据行 if(titleList.size()<0){ sheet.createRow(1).createCell(0).setCellValue(""); sheet.getRow(1).createCell(1).setCellValue(""); } for (int i = 0; i < sourceModelList.size(); i++) { Map<String, String> baseFormMap = sourceModelList.get(i);//数据行 //fldNameArr字段属性 for (int j = 0; j < numberList.size(); j++) { if (sheet.getRow(i + 1) == null) { if (j == 0) { try { sheet.createRow(i + 1) .createCell(j) .setCellValue(baseFormMap.get(numberList.get(j)) == null ? "" : baseFormMap.get(numberList.get(j))); } catch (Exception e) { if (baseFormMap.get(numberList.get(j)) == null) { sheet.createRow(i + 1).createCell(j).setCellValue(""); } else { sheet.createRow(i + 1) .createCell(j) .setCellValue(baseFormMap.get(numberList.get(j))+""); } } } } else { // String s = baseFormMap.get(numberList.get(j))+""; // Double aDouble = Double.valueOf(baseFormMap.get(numberList.get(j))); BigDecimal b = new BigDecimal(Double.valueOf(baseFormMap.get(numberList.get(j)))); double value = 0D; if (b != null) { value = b.doubleValue(); } sheet.getRow(i + 1).createCell(j).setCellValue(b.doubleValue()); // if (value == 0D) { // sheet.getRow(i + 1).createCell(j); // } else { // sheet.getRow(i + 1).createCell(j).setCellValue(b.doubleValue()); // } } } } // 更新嵌入的workbook List<POIXMLDocumentPart> pxdList = xwpfChart.getRelations(); if(pxdList!=null&&pxdList.size()>0) { for (int i = 0; i < pxdList.size(); i++) { if (pxdList.get(i).toString().contains("sheet")) { POIXMLDocumentPart xlsPart = xwpfChart.getRelations().get(0); OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream(); try { xlsOut.flush(); wb.write(xlsOut); xlsPart.setCommitted(true); // ((XSSFWorkbook) wb).setCommitted(true); xlsOut.close(); } catch (IOException e) { e.printStackTrace(); result = false; } finally { if (wb != null) { try { wb.close(); } catch (IOException e) { e.printStackTrace(); result = false; } } } } } } return result; } /** * 数据分析 * @param chartModel * @param i * @param bias * @param cat * @param val */ public void dataAnalysisFill (ChartModel chartModel, int i, int bias, CTAxDataSource cat, CTNumDataSource val, CTSerTx tx) { //数据源 List<Map<String, String>> sourceModelList = chartModel.getSourceModelList(); //数据源key List<String> numberList = chartModel.getNumberList(); List<String> titleList = chartModel.getTitleList(); // CTStrData strData = cat.getStrRef().getStrCache(); CTNumData numData = val.getNumRef().getNumCache(); long idx = 0; //1、删掉模板里图表缓存数据 long l=strData.getPtCount().getVal(); long z=0; long num=l; while (z!=num){ numData.removePt((int)l-1); strData.removePt((int)l-1); l--; z++; } //2.新增图表数据 for (int j = 0; j < sourceModelList.size(); j++) { //判断获取的值是否为空 String value = "0"; if (new BigDecimal(sourceModelList.get(j).get(numberList.get(i+1))) != null) { value = new BigDecimal(sourceModelList.get(j).get(numberList.get(i + 1))).toString(); } CTNumVal numVal = numData.addNewPt();//序列值 numVal.setIdx(idx); numVal.setV(value); // if (!"0".equals(value)) { // CTNumVal numVal = numData.addNewPt();//序列值 // numVal.setIdx(idx); // numVal.setV(value); // } CTStrVal sVal = strData.addNewPt();//序列名称 sVal.setIdx(idx); sVal.setV(sourceModelList.get(j).get(numberList.get(0))); idx++; } //3.图表没有数据,默认值,以便能显示出图表 int m=sourceModelList.size(); if(titleList.size()==0){ idx=1; m=1; } numData.getPtCount().setVal(idx); strData.getPtCount().setVal(idx); //赋值横坐标数据区域 String axisDataRange = new CellRangeAddress(1, m, 0, 0) .formatAsString(chartModel.getSheetName(), false); cat.getStrRef().setF(axisDataRange); //赋值纵坐标数据区域 String numDataRange = new CellRangeAddress(1, m, i + 1 + bias, i + 1 + bias) .formatAsString(chartModel.getSheetName(), false); val.getNumRef().setF(numDataRange); //更新图例 if(sourceModelList.size()>0){ tx.getStrRef().getStrCache().getPtList().get(0).setV(titleList.get(i+1)); } } }