New file |
| | |
| | | package com.ots.project.tool.report.CIAQ.chart; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ots.common.utils.StringUtils; |
| | | import com.ots.project.tool.report.CIAQ.CIAQReport; |
| | | import com.ots.project.tool.report.MAQ.base.RowData; |
| | | import com.ots.project.tool.report.MAQ.base.SeriesData; |
| | | import com.ots.project.tool.report.reportCalculation.response.ReportCIAQAPIResult; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ooxml.POIXMLDocument; |
| | | import org.apache.poi.ooxml.POIXMLDocumentPart; |
| | | import org.apache.poi.ss.usermodel.CellType; |
| | | 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.FileOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.util.*; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * @description: CIAQ图表 散点图跟柱形图数据变更 |
| | | * @author: zhijie |
| | | * @create: 2023-04-23 16:31 |
| | | **/ |
| | | @Slf4j |
| | | public class CIAQChart { |
| | | |
| | | private static Double PR_Dim01, PR_Dim02, PR_Dim03, PR_Dim04, PR_Dim05, PR_Dim06, PR_Dim07, PR_Dim08; |
| | | |
| | | public static void main(String[] args) throws IOException { |
| | | String str = "{\"occ1L\":\"地质勘探工程技术人员(比如地质矿产调查工程技术人员)\",\"occ3L\":\"矿山工程技术人员(比如选矿与矿物加工工程技术人员)\",\"PR_Dim01\":\"56\",\"PR_Dim02\":\"78\",\"PR_Dim03\":\"40\",\"PR_Dim04\":\"67\",\"occ5H\":\"音乐指挥与演员(比如电影电视演员、乐器演奏员)\",\"occ9L\":\"信息通信网络运行管理人员(比如信息通信网络运行管理员)\",\"occ7H\":\"工艺美术与创意设计专业人员(比如服装设计人员、环境设计人员)\",\"occ1H\":\"绿化与园艺服务人员(比如盆景师、插花花艺师)\",\"occ5L\":\"机械工程技术人员(比如机械设计工程技术人员、自动控制工程技术人员)\",\"occ3H\":\"文学、艺术学研究人员\",\"occ7L\":\"工业机器人操作运维人员(比如工业机器人系统运维员、)\",\"occ10H\":\"酒类饮品调制师(比如酿酒师、酒体设计师)\",\"occ10L\":\"地质勘查人员(比如物探工、地质调查员)\",\"occ8H\":\" 陶瓷制品制造人员(比如陶瓷装饰工、古建琉璃工)\",\"PR_Dim05\":\"89\",\"PR_Dim06\":\"12\",\"PR_Dim07\":\"57\",\"PR_Dim08\":\"33\",\"occ2L\":\"测绘和地理信息工程技术人员(比如工程测量工程技术人员)\",\"occ4H\":\"文艺创作与编导人员(比如文学作家、舞蹈编导)\",\"occ8L\":\"电子工程技术人员(比如电子材料/电子元器件工程技术人员)\",\"occ6H\":\"美术专业人员(比如画家、雕塑家)\",\"occ4L\":\"冶金工程技术人员(比如冶金热能工程技术人员、稀土工程技术人员)\",\"occ2H\":\"舞台专业人员(比如灯光师、化妆师)\",\"occ6L\":\"航空工程技术人员(比如飞行器制造工程技术人员)\",\"condition\":\"1\",\"occ9H\":\"摄影扩印服务人员(比如商业摄影师)\"}"; |
| | | Map<String ,Object> textMap = JSON.parseObject(str, HashMap.class); |
| | | try (OutputStream os = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\CIAQ1.docx");XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage("C:\\Users\\Administrator\\Desktop\\CIAQ.docx"))){ |
| | | changeChart(document,textMap); |
| | | document.write(os); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 替换CIAQ图表数据 |
| | | * @param document 文档对象 |
| | | * @param textMap 报告字典键值对 |
| | | * @return |
| | | */ |
| | | public static boolean changeChart(XWPFDocument document, Map<String, Object> textMap){ |
| | | List<SeriesData> seriesDatas = initData(textMap); |
| | | if(seriesDatas == null){ |
| | | log.error("替换CIAQ图表数据,初始化数据失败!"); |
| | | return false; |
| | | } |
| | | //CIAQ图表数据 |
| | | changeCIAQChart(document,seriesDatas); |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 判断是否为空 |
| | | * @param value |
| | | * @return |
| | | */ |
| | | public static boolean checkParamsIsNull(Double... value) { |
| | | for (int i = 0; i < value.length; i++) { |
| | | if (Objects.isNull(value[i])) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 初始化报告数据 |
| | | * @param textMap |
| | | * @return |
| | | */ |
| | | public static List<SeriesData> initData(Map<String, Object> textMap){ |
| | | //获取命中数值 |
| | | PR_Dim01 = Double.valueOf((String) textMap.get("PR_Dim01")); |
| | | PR_Dim02 = Double.valueOf((String) textMap.get("PR_Dim02")); |
| | | PR_Dim03 = Double.valueOf((String) textMap.get("PR_Dim03")); |
| | | PR_Dim04 = Double.valueOf((String) textMap.get("PR_Dim04")); |
| | | PR_Dim05 = Double.valueOf((String) textMap.get("PR_Dim05")); |
| | | PR_Dim06 = Double.valueOf((String) textMap.get("PR_Dim06")); |
| | | PR_Dim07 = Double.valueOf((String) textMap.get("PR_Dim07")); |
| | | PR_Dim08 = Double.valueOf((String) textMap.get("PR_Dim08")); |
| | | |
| | | //判断是否为空 |
| | | if (checkParamsIsNull(PR_Dim01, PR_Dim02, PR_Dim03, PR_Dim04, PR_Dim05, PR_Dim06, PR_Dim07, PR_Dim08)) { |
| | | return null; |
| | | } |
| | | |
| | | // 测试数据 |
| | | List<SeriesData> seriesDatas = Arrays.asList( |
| | | new SeriesData(" ", Arrays.asList( |
| | | new RowData(" ", 0,"健康科学"), |
| | | new RowData(" ", 0,"创造性表达"), |
| | | new RowData(" ", 0,"科技"), |
| | | new RowData(" ", 0,"人"), |
| | | new RowData(" ", 0,"组织"), |
| | | new RowData(" ", 0,"影响"), |
| | | new RowData(" ", 0,"自然"), |
| | | new RowData(" ", 0,"事物") |
| | | )), |
| | | new SeriesData("价值观分数", Arrays.asList( |
| | | new RowData("价值观分数", PR_Dim01), |
| | | new RowData("价值观分数", PR_Dim02), |
| | | new RowData("价值观分数", PR_Dim03), |
| | | new RowData("价值观分数", PR_Dim04), |
| | | new RowData("价值观分数", PR_Dim05), |
| | | new RowData("价值观分数", PR_Dim06), |
| | | new RowData("价值观分数", PR_Dim07), |
| | | new RowData("价值观分数", PR_Dim08) |
| | | )) |
| | | ); |
| | | return seriesDatas; |
| | | } |
| | | |
| | | /** |
| | | * 替换word图表 雷达图带标记图表 |
| | | * @param doc |
| | | * @param seriesDatas |
| | | */ |
| | | public static void changeCIAQChart(XWPFDocument doc,List<SeriesData> seriesDatas) { |
| | | try { |
| | | //动态刷新图表 |
| | | List<POIXMLDocumentPart> relations = doc.getRelations(); |
| | | for (POIXMLDocumentPart part : relations) { |
| | | if (part instanceof XWPFChart) { |
| | | // 图表元素 |
| | | XWPFChart chart = (XWPFChart) part; |
| | | |
| | | // 查看里面的图表数据,才能知道是什么图表 |
| | | CTPlotArea plot = chart.getCTChart().getPlotArea(); |
| | | // excel内置表格 |
| | | XSSFWorkbook workbook = chart.getWorkbook(); |
| | | XSSFSheet sheet = workbook.getSheetAt(0); |
| | | |
| | | // 查看图表类型 |
| | | // getChartType(part); |
| | | // 遍历数据 |
| | | //printData(sheet); |
| | | |
| | | // 雷达图 |
| | | if (!plot.getRadarChartList().isEmpty()) { |
| | | CTRadarChart radarChart = plot.getRadarChartArray(0); |
| | | //刷新内置excel数据 |
| | | refreshExcel(seriesDatas, workbook, sheet); |
| | | workbook.write(chart.getPackagePart().getOutputStream()); |
| | | |
| | | //雷达图数据源 散点坐标 |
| | | for (CTRadarSer ser : radarChart.getSerList()) { |
| | | //更新雷达图缓存 |
| | | updateRadarChart(seriesDatas, ser.getCat(),ser.getVal()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("CIAQGS替换word图表 散点图跟柱形图组合图形失败:{}",e); |
| | | } |
| | | } |
| | | |
| | | private static void printData(XSSFSheet sheet){ |
| | | //先要遍历行 |
| | | for(int rowNum=0;rowNum<=sheet.getLastRowNum();rowNum++) { |
| | | XSSFRow hssRow = sheet.getRow(rowNum); |
| | | if (hssRow == null) { |
| | | continue; |
| | | } |
| | | for (int cellNum = 0; cellNum <= hssRow.getLastCellNum(); cellNum++) { |
| | | XSSFCell hssfCell = hssRow.getCell(cellNum); |
| | | if (hssfCell == null) { |
| | | continue; |
| | | } |
| | | System.out.print("--" + getValue(hssfCell)); |
| | | } |
| | | System.out.println(); |
| | | } |
| | | } |
| | | |
| | | private static String getValue(XSSFCell hssfCell){ |
| | | if(hssfCell.getCellType()== CellType.BOOLEAN){ |
| | | return String.valueOf(hssfCell.getBooleanCellValue()); |
| | | }else if(hssfCell.getCellType()==CellType.NUMERIC){ |
| | | return String.valueOf(hssfCell.getNumericCellValue()); |
| | | }else{ |
| | | return String.valueOf(hssfCell.getStringCellValue()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 更新图表的关联 excel |
| | | * |
| | | * @param seriesDatas |
| | | * @param workbook |
| | | * @param sheet |
| | | */ |
| | | protected static void refreshExcel(List<SeriesData> seriesDatas, XSSFWorkbook workbook, 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); |
| | | } |
| | | //优先使用字符串值 CIAQ第一列是中文 |
| | | if(StringUtils.isNotEmpty(cellValu.valueStr)){ |
| | | cell.setCellValue(cellValu.valueStr); |
| | | }else{ |
| | | cell.setCellValue(cellValu.value); |
| | | } |
| | | } |
| | | //删除多余行数 |
| | | int lastRowNum = sheet.getLastRowNum(); |
| | | if (lastRowNum > size) { |
| | | for (int idx = lastRowNum; idx > size; idx--) { |
| | | sheet.removeRow(sheet.getRow(idx)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 更新 雷达图 缓存数据 |
| | | * |
| | | * @param seriesDatas 数据 |
| | | * @param xDataSource X坐标数据缓存 |
| | | * @param yDataSource Y坐标数据缓存 |
| | | */ |
| | | protected static void updateRadarChart(List<SeriesData> seriesDatas, CTAxDataSource xDataSource, |
| | | CTNumDataSource yDataSource) { |
| | | |
| | | //获取xy坐标数据条数 |
| | | long xStrCnt = xDataSource.getStrRef().getStrCache().getPtCount().getVal(); |
| | | long yNumCnt = yDataSource.getNumRef().getNumCache().getPtCount().getVal(); |
| | | |
| | | //获取XY最新数据 |
| | | List<RowData> xRowDatas = seriesDatas.get(0).getValue(); |
| | | int xRowDataSize = xRowDatas.size(); |
| | | List<RowData> yRowDatas = seriesDatas.get(1).getValue(); |
| | | int yRowDataSize = yRowDatas.size(); |
| | | |
| | | //更新X坐标缓存 |
| | | for (int i = 0; i < xRowDatas.size(); i++) { |
| | | RowData cellValu = xRowDatas.get(i); |
| | | CTStrVal val = xStrCnt > i ? xDataSource.getStrRef().getStrCache().getPtArray(i) |
| | | : xDataSource.getStrRef().getStrCache().addNewPt(); |
| | | val.setIdx(i); |
| | | val.setV(cellValu.valueStr); |
| | | } |
| | | |
| | | //更新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); |
| | | val.setV(String.format("%.0f", cellValu.value)); |
| | | } |
| | | |
| | | // 更新对应excel的范围 |
| | | xDataSource.getStrRef().setF( |
| | | replaceRowEnd(xDataSource.getStrRef().getF(), |
| | | xStrCnt, |
| | | xRowDataSize)); |
| | | yDataSource.getNumRef().setF( |
| | | replaceRowEnd(yDataSource.getNumRef().getF(), |
| | | yNumCnt, |
| | | yRowDataSize)); |
| | | |
| | | // 删除多的 |
| | | if (xStrCnt > xRowDataSize) { |
| | | for (int idx = xRowDataSize; idx < xStrCnt; idx++) { |
| | | xDataSource.getStrRef().getStrCache().removePt(xRowDataSize); |
| | | } |
| | | } |
| | | if (yNumCnt > yRowDataSize) { |
| | | for (int idx = yRowDataSize; idx < yNumCnt; idx++) { |
| | | yDataSource.getNumRef().getNumCache().removePt(yRowDataSize); |
| | | } |
| | | } |
| | | // 更新个数 |
| | | xDataSource.getStrRef().getStrCache().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()+"}"); |
| | | } |
| | | if (!plotArea.getRadarChartList().isEmpty()) { |
| | | System.out.println("雷达图{"+plotArea.getRadarChartList().size()+"}"); |
| | | } |
| | | } |
| | | |
| | | } |