package com.ots.project.tool.report.LAQ.chart; import com.ots.common.utils.StringUtils; import com.ots.common.utils.poi.ExcelUtil; import com.ots.project.tool.report.LAQ.LAQTemplate; import com.ots.project.tool.report.MAQ.base.RowData; import com.ots.project.tool.report.MAQ.base.SeriesData; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ooxml.POIXMLDocument; import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xwpf.usermodel.XWPFChart; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.openxmlformats.schemas.drawingml.x2006.chart.*; import java.io.*; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @Slf4j public class LAQTest { //这里是用来测试的 public static void main(String[] args) throws Exception { System.out.println("启动测试.."); // Map textMap = new HashMap(); // textMap.put("%boxgrid1%","易紫轩、邵诗悦"); // textMap.put("%boxgrid2%","叶诗悦"); // textMap.put("%boxgrid3%","刘晨涵"); // textMap.put("%boxgrid4%","段国贤"); // textMap.put("%boxgrid5%","贺瑞辰"); // textMap.put("%boxgrid6%","赵翔"); // textMap.put("%boxgrid7%","钱佳毅"); // textMap.put("%boxgrid8%","卢文轩"); // textMap.put("%boxgrid9%","唐忠林"); String dataPath = "D:\\桌面文件\\LAQ全景图报告\\LAQ导入测试数据.xlsx"; // 获取导入数据 File file = new File(dataPath); InputStream in = new FileInputStream(file); ExcelUtil util = new ExcelUtil<>(LAQTemplate.class); List laqTemplateList = util.importExcel(in); // 生成文件集合 List fileNameList = new ArrayList<>(); List deleteStrList = new ArrayList<>(); // for (int i = 0; i < laqTemplateList.size(); i++) { // LAQTemplate laqTemplate = laqTemplateList.get(i); // //组装报告所用数据 // Map textMap = new HashMap<>(); // textMap.put("olas", "85"); // textMap.put("ca", "32"); // textMap.put("bla", "34"); // textMap.put("nr", "3"); // textMap.put("ar", "45"); // textMap.put("open", "67"); // textMap.put("cons", "12"); // textMap.put("extra", "48"); // textMap.put("agree", "90"); // textMap.put("emosta", "23"); // textMap.put("perfomance", "60"); // // // LAQReport report = new LAQReport(); // // ZipSecureFile.setMinInflateRatio(0.001); // try (OutputStream os = new FileOutputStream("D:\\桌面文件\\LAQ英文报告"+UUID.randomUUID().toString()+".docx"); // XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage("D:\\桌面文件\\LAQ英文报告-叠加版本.docx"))) { // Map> seriesDatas = initData(textMap); // Map lableDatas = initLables(); // changeChart(document, seriesDatas, textMap,lableDatas); // document.write(os); // } catch (Exception e) { // e.printStackTrace(); // } // } ZipSecureFile.setMinInflateRatio(0.001); try (OutputStream os = new FileOutputStream("D:\\桌面文件\\可删除\\LAQ英文报告"+UUID.randomUUID().toString()+".docx"); XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage("D:\\桌面文件\\LAQ英文报告-叠加版本.docx"))) { changeChartNew(document,laqTemplateList); document.write(os); } catch (Exception e) { e.printStackTrace(); } System.out.println("处理完成..."); } /** * 初始化数据 * @param list * @return */ public static Map> initNewData(List list) { Map> seriesDataMap = new HashMap<>(); for (int i = 0; i < list.size(); i++) { LAQTemplate laqTemplate = list.get(i); Double olas = Double.valueOf(laqTemplate.getOlas().toString()); Double perfomance; if(laqTemplate.getPerfomance()!= null) { perfomance = Double.valueOf(laqTemplate.getPerfomance().toString()); } else { perfomance = 0.0; } List seriesDatas = new ArrayList<>(); seriesDatas = Arrays.asList( new SeriesData("X 值", Arrays.asList( new RowData("X 值", olas) )), new SeriesData("Y 值", Arrays.asList( new RowData("Y 值", perfomance) )) ); Integer box = laqTemplate.getBox(); if(olas>=66) { seriesDataMap.put(100+i+1,seriesDatas); } else if(olas>33&&olas<66) { seriesDataMap.put(200+i+1,seriesDatas); } else { seriesDataMap.put(300+i+1,seriesDatas); } } return seriesDataMap; } public static Map> initData(Map textMap){ Map> seriesDataMap = new HashMap<>(); //获取命中数值 Double olas = Double.valueOf((String)textMap.get("olas")); Double ca = Double.valueOf((String)textMap.get("ca")); Double bla = Double.valueOf((String)textMap.get("bla")); Double nr = Double.valueOf((String)textMap.get("nr")); Double ar = Double.valueOf((String)textMap.get("ar")); Double open = Double.valueOf((String)textMap.get("open")); Double cons = Double.valueOf((String)textMap.get("cons")); Double extra = Double.valueOf((String)textMap.get("extra")); Double agree = Double.valueOf((String)textMap.get("agree")); Double emosta = Double.valueOf((String)textMap.get("emosta")); Double perfomance; if(textMap.get("perfomance") != null){ perfomance = Double.valueOf((String)textMap.get("perfomance")); }else{ perfomance = -1D; } // 图表1 List seriesDatas = new ArrayList<>(); // 图表1 seriesDatas = Arrays.asList( new SeriesData("X 值", Arrays.asList( new RowData("X 值", perfomance.doubleValue() == -1 ? perfomance.doubleValue() : olas.doubleValue()) )), new SeriesData("Y 值", Arrays.asList( new RowData("Y 值", perfomance.doubleValue()) )) ); seriesDataMap.put(1,seriesDatas); seriesDatas = Arrays.asList( new SeriesData("X 值", Arrays.asList( new RowData("X 值", 95) )), new SeriesData("Y 值", Arrays.asList( new RowData("Y 值", 87) )) ); seriesDataMap.put(2,seriesDatas); seriesDatas = Arrays.asList( new SeriesData("X 值", Arrays.asList( new RowData("X 值", 96) )), new SeriesData("Y 值", Arrays.asList( new RowData("Y 值", 90) )) ); seriesDataMap.put(3,seriesDatas); return seriesDataMap; } /** * 获取指定类型的SeriesData。 * @param list * @param type * @return */ public static Map> getSeriesDataByType(List list,Integer type) { Map> seriesDataMap = new HashMap<>(); int dataIndex =1; for (int i = 0; i < list.size(); i++) { LAQTemplate laqTemplate = list.get(i); Double olas = Double.valueOf(laqTemplate.getOlas().toString()); Double perfomance; if(laqTemplate.getPerfomance()!= null) { perfomance = Double.valueOf(laqTemplate.getPerfomance().toString()); } else { perfomance = 0.0; } List seriesDatas = new ArrayList<>(); seriesDatas = Arrays.asList( new SeriesData("X 值", Arrays.asList( new RowData("X 值", olas) )), new SeriesData("Y 值", Arrays.asList( new RowData("Y 值", perfomance) )) ); if(type==1) { if(olas>67) { seriesDataMap.put(dataIndex,seriesDatas); dataIndex++; } } if(type==2) { if(olas<=67 && olas>33) { seriesDataMap.put(dataIndex,seriesDatas); dataIndex++; } } if(type==3) { if(olas<=33) { seriesDataMap.put(dataIndex,seriesDatas); dataIndex++; } } } return seriesDataMap; } public static Map getSeriesDataLablesByType(List list,Integer type) { Map seriesDataMapLables = new HashMap<>(); int dataIndex =1; for (int i = 0; i < list.size(); i++) { LAQTemplate laqTemplate = list.get(i); Double olas = Double.valueOf(laqTemplate.getOlas().toString()); Double perfomance; if(laqTemplate.getPerfomance()!= null) { perfomance = Double.valueOf(laqTemplate.getPerfomance().toString()); } else { perfomance = 0.0; } String olasStr = olas.toString(); String perfomanceStr = perfomance.toString(); // 判断小数部分是否为0 if (Math.abs(olas - Math.floor(olas)) < 1e-9) { // 如果小数部分接近于0,则取整数部分 olasStr = String.valueOf(olas.intValue()); } if (Math.abs(perfomance - Math.floor(perfomance)) < 1e-9) { // 如果小数部分接近于0,则取整数部分 perfomanceStr = String.valueOf(perfomance.intValue()); } if(type==1) { if(olas>67) { seriesDataMapLables.put(dataIndex,laqTemplate.getName()+"("+olasStr+"-"+perfomanceStr+")"); dataIndex++; } } if(type==2) { if(olas<=67 && olas>33) { seriesDataMapLables.put(dataIndex,laqTemplate.getName()+"("+olasStr+"-"+perfomanceStr+")"); dataIndex++; } } if(type==3) { if(olas<=33) { seriesDataMapLables.put(dataIndex,laqTemplate.getName()+"("+olasStr+"-"+perfomanceStr+")"); dataIndex++; } } } return seriesDataMapLables; } public static void changeChartNew(XWPFDocument document,List list) { if(list.size()<=0){ return; } try { //获取数据 Map> seriesDataMapTop = getSeriesDataByType(list,1); Map> seriesDataMapMiddle = getSeriesDataByType(list,2); Map> seriesDataMapBottom = getSeriesDataByType(list,3); //获取标签 Map seriesDataLablesTop = getSeriesDataLablesByType(list,1); Map seriesDataLablesMiddle = getSeriesDataLablesByType(list,2); Map seriesDataLablesBottom = getSeriesDataLablesByType(list,3); List relations = document.getRelations(); int barIndex = 1; //三个图表的个数 int topIndex =1; int middleIndex =1; int bottomIndex =1; for (POIXMLDocumentPart part : relations) { if (part instanceof XWPFChart) { // 图表元素 XWPFChart chart = (XWPFChart) part; // 查看里面的图表数据,才能知道是什么图表 CTPlotArea plot = chart.getCTChart().getPlotArea(); getChartType(chart); // excel内置表格 XSSFWorkbook workbook = chart.getWorkbook(); XSSFSheet sheet = workbook.getSheetAt(0); //散点图 if (!plot.getScatterChartList().isEmpty()) { CTScatterChart scatterChart = plot.getScatterChartArray(0); //第一个散点图1-90,第二个91-180,第三个181-270 System.out.println("第"+barIndex+"个散点图"); String lables = ""; List seriesDatas = new ArrayList<>(); // 获取图表的值轴,并把最小值设置为-0, // chart.getAxes().get(1) 获取的纵坐标,chart.getAxes().get(0) 获取的是横坐标 chart.getAxes().get(1).setMinimum(0); Double maximum = chart.getAxes().get(0).getMaximum(); Double minimum = chart.getAxes().get(0).getMinimum(); // System.out.println("X轴最小值是:"+minimum+",最大值是:"+maximum); //判断图表所在位置 if(minimum>=67) { seriesDatas = seriesDataMapTop.get(topIndex); lables = seriesDataLablesTop.get(topIndex); topIndex++; // System.out.println("第一页图表个数:"+topIndex+",标签:"+lables+";"+"X轴最小值是:"+minimum+",最大值是:"+maximum); } else if(minimum>=33) { seriesDatas = seriesDataMapMiddle.get(middleIndex); lables = seriesDataLablesMiddle.get(middleIndex); // System.out.println("第二页图表个数:"+middleIndex); middleIndex++; } else { seriesDatas = seriesDataMapBottom.get(bottomIndex); lables = seriesDataLablesBottom.get(bottomIndex); bottomIndex++; // System.out.println("第三页图表个数:"+bottomIndex); } barIndex++; if(seriesDatas==null) { for (CTScatterSer ser : scatterChart.getSerList()) { ser.getTx().getStrRef().getStrCache().getPtArray(0).setV(""); } continue; } //刷新内置excel数据 refreshExcel(seriesDatas, sheet); workbook.write(chart.getPackagePart().getOutputStream()); int i = 0; for (CTScatterSer ser : scatterChart.getSerList()) { //更新散点图缓存 updateScatterChart(seriesDatas, ser.getXVal(), ser.getYVal()); ser.getTx().getStrRef().getStrCache().getPtArray(0).setV(lables); ++i; } } } } System.out.println("第一页图表个数:"+(topIndex-1)); System.out.println("第二页图表个数:"+(middleIndex-1)); System.out.println("第三页图表个数:"+(bottomIndex-1)); } catch (Exception e) { e.printStackTrace(); log.error("LAQ.替换word图表 散点图图形失败:{}",e); } } public static void changeChart(XWPFDocument document, Map> seriesDataMap, Map textMap,Map lableDatas) { if(StringUtils.isEmpty(textMap)){ return; } try { List relations = document.getRelations(); int barIndex = 1; int chartIndex =1;//散点图表的数量 for (POIXMLDocumentPart part : relations) { if (part instanceof XWPFChart) { // 图表元素 XWPFChart chart = (XWPFChart) part; // 查看里面的图表数据,才能知道是什么图表 CTPlotArea plot = chart.getCTChart().getPlotArea(); getChartType(chart); // excel内置表格 XSSFWorkbook workbook = chart.getWorkbook(); XSSFSheet sheet = workbook.getSheetAt(0); //散点图 if (!plot.getScatterChartList().isEmpty()) { if(chartIndex>=1&&chartIndex<=90) { } List seriesDatas = seriesDataMap.get(barIndex); CTScatterChart scatterChart = plot.getScatterChartArray(0); System.out.println("散点图{"+plot.getScatterChartList().size()+"}"); if(seriesDatas==null) { for (CTScatterSer ser : scatterChart.getSerList()) { ser.getTx().getStrRef().getStrCache().getPtArray(0).setV(""); } continue; } // 获取图表的值轴,并把最小值设置为-0, // chart.getAxes().get(1) 获取的纵坐标,chart.getAxes().get(0) 获取的是横坐标 chart.getAxes().get(1).setMinimum(0); Double maximum = chart.getAxes().get(1).getMaximum(); Double minimum = chart.getAxes().get(1).getMinimum(); System.out.println("【开始】最大:"+maximum+",最小:"+minimum); //刷新内置excel数据 refreshExcel(seriesDatas, sheet); workbook.write(chart.getPackagePart().getOutputStream()); int i = 0; for (CTScatterSer ser : scatterChart.getSerList()) { //更新散点图缓存 updateScatterChart(seriesDatas, ser.getXVal(), ser.getYVal()); String lables = lableDatas.get(barIndex); ser.getTx().getStrRef().getStrCache().getPtArray(0).setV(lables); // updateDLbls(ser); ++i; } barIndex++; chartIndex++; } } } } catch (Exception e) { e.printStackTrace(); log.error("LAQ.替换word图表 散点图图形失败:{}",e); } } /** * 更新标签 * @param ser */ private static void updateDLbls(CTScatterSer ser) { // 设置散点的大小 // CTMarkerSize ctMarkerSize = CTMarkerSize.Factory.newInstance(); // ctMarkerSize.setVal((short)0); // ser.getMarker().setSize(ctMarkerSize); ser.getTx().getStrRef().getStrCache().getPtArray(0).setV(UUID.randomUUID().toString()); } /** * 更新图表的关联 excel * * @param seriesDatas * @param sheet */ protected static void refreshExcel(List seriesDatas, XSSFSheet sheet) { XSSFRow title = sheet.getRow(0); //遍历数据数组进行excel赋值 for (int i = 0; i < seriesDatas.size(); i++) { SeriesData data = seriesDatas.get(i); if (data.name != null && !data.name.isEmpty()) { // 第一行标题 XSSFCell cell = title.getCell(i); if (cell == null) { cell = title.createCell(i + 1); } cell.setCellValue(data.name); } int size = data.value.size(); //遍历数据进行赋值 for (int j = 0; j < size; j++) { //从第二行开始赋值 XSSFRow row = sheet.getRow(j + 1); if (row == null) { row = sheet.createRow(j + 1); } RowData cellValu = data.value.get(j); //第一列开始赋值 XSSFCell cell = row.getCell(i); if (cell == null) { cell = row.createCell(i); } //优先使用字符串值 if(StringUtils.isNotEmpty(cellValu.valueStr)){ cell.setCellValue(cellValu.valueStr); }else{ if(cellValu.value != -1){ cell.setCellValue(cellValu.value); }else{ cell.setCellValue((String) null); } } } //删除多余行数 int lastRowNum = sheet.getLastRowNum(); //log.error("lastRowNum:{},size:{}",lastRowNum,size); if (lastRowNum > size) { for (int idx = lastRowNum; idx > size; idx--) { if(sheet.getRow(idx) == null){ continue; } sheet.removeRow(sheet.getRow(idx)); } } } } /** * 更新 散点图 缓存数据 * * @param seriesDatas 数据 * @param xDataSource X坐标数据缓存 * @param yDataSource Y坐标数据缓存 */ protected static void updateScatterChart(List seriesDatas, CTAxDataSource xDataSource, CTNumDataSource yDataSource) { //获取xy坐标数据条数 long xNumCnt = xDataSource.getNumRef().getNumCache().getPtCount().getVal(); long yNumCnt = yDataSource.getNumRef().getNumCache().getPtCount().getVal(); System.out.println("[有数据]条数 x:"+xNumCnt+" y:"+yNumCnt); //获取XY最新数据 List xRowDatas = seriesDatas.get(0).getValue(); int xRowDataSize = xRowDatas.size(); List yRowDatas = seriesDatas.get(1).getValue(); int yRowDataSize = yRowDatas.size(); //更新X坐标缓存 for (int i = 0; i < xRowDatas.size(); i++) { RowData cellValu = xRowDatas.get(i); CTNumVal val = xNumCnt > i ? xDataSource.getNumRef().getNumCache().getPtArray(i) : xDataSource.getNumRef().getNumCache().addNewPt(); val.setIdx(i); if(cellValu.value == -1){ val.setV(null); }else { val.setV(String.format("%.0f", cellValu.value)); } } //更新Y坐标缓存 for (int i = 0; i < yRowDatas.size(); i++) { RowData cellValu = yRowDatas.get(i); CTNumVal val = yNumCnt > i ? yDataSource.getNumRef().getNumCache().getPtArray(i) : yDataSource.getNumRef().getNumCache().addNewPt(); val.setIdx(i); if(cellValu.value == -1){ val.setV(null); }else { val.setV(String.format("%.0f", cellValu.value)); } } // 更新对应excel的范围 xDataSource.getNumRef().setF( replaceRowEnd(xDataSource.getNumRef().getF(), xNumCnt, xRowDataSize)); yDataSource.getNumRef().setF( replaceRowEnd(yDataSource.getNumRef().getF(), yNumCnt, yRowDataSize)); // 删除多的 if (xNumCnt > xRowDataSize) { for (int idx = xRowDataSize; idx < xNumCnt; idx++) { xDataSource.getNumRef().getNumCache().removePt(xRowDataSize); } } if (yNumCnt > yRowDataSize) { for (int idx = yRowDataSize; idx < yNumCnt; idx++) { yDataSource.getNumRef().getNumCache().removePt(yRowDataSize); } } // 更新个数 xDataSource.getNumRef().getNumCache().getPtCount().setVal(xRowDataSize); // 更新个数 yDataSource.getNumRef().getNumCache().getPtCount().setVal(yRowDataSize); } /** * 替换 形如: Sheet1!$A$2:$A$4 的字符 * * @param range * @return */ public static String replaceRowEnd(String range, long oldSize, long newSize) { Pattern pattern = Pattern.compile("(:\\$[A-Z]+\\$)(\\d+)"); Matcher matcher = pattern.matcher(range); if (matcher.find()) { long old = Long.parseLong(matcher.group(2)); return range.replaceAll("(:\\$[A-Z]+\\$)(\\d+)", "$1" + Long.toString(old - oldSize + newSize)); } return range; } /** * 获取图表有哪些类型 * @param part */ public static void getChartType(POIXMLDocumentPart part){ XWPFChart chart = (XWPFChart) part; //根据属性第一列名称切换数据类型 CTChart ctChart = chart.getCTChart(); CTPlotArea plotArea = ctChart.getPlotArea(); if (!plotArea.getBarChartList().isEmpty()) { System.out.println("柱状图{"+plotArea.getBarChartList().size()+"}"); } if (!plotArea.getPieChartList().isEmpty()) { System.out.println("饼图{"+plotArea.getPieChartList().size()+"}"); } if (!plotArea.getLineChartList().isEmpty()) { System.out.println("线形图{"+plotArea.getLineChartList().size()+"}"); } if (!plotArea.getBar3DChartList().isEmpty()) { System.out.println("柱状图3D{"+plotArea.getBar3DChartList().size()+"}"); } if (!plotArea.getScatterChartList().isEmpty()) { // System.out.println("散点图类型{"+plotArea.getScatterChartList().size()+"}"); } } }