Java生成Excel中的组合图
使用Java+poi生成 依赖
▼js复制代码<!--poi--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency>
实体类:
▼js复制代码@Data @AllArgsConstructor @NoArgsConstructor public class ChartExcelDto implements Serializable { /** * 图表数据 */ private Map<String, List<Object>> data; /** * 折线图和柱状图共用指定的x轴值 */ private String categories; /** * 指定的折线图y轴 */ private List<String> valueList; /** * 指定的柱状图y轴 */ private String barValue; }
代码,中间的雪花id,需要自己引入hutool依赖,这里是将json数据作为画图数据源,其实也可以改写为上传excel,根据excel中的数据生成组合图,看自己需求改造。
▼js复制代码public String createChartExcel(ChartExcelDto chartExcelDto) { Map<String, List<Object>> data = chartExcelDto.getData(); // x轴 List<Object> categoryList = data.get(chartExcelDto.getCategories()); String[] categories = categoryList.stream() .map(Object::toString) .toArray(String[]::new); // 折线图y轴 List<String> valueKeyList = chartExcelDto.getValueList(); List<List<Object>> valueList = new ArrayList<>(); for (String key : valueKeyList) { List<Object> value = data.get(key); valueList.add(value); } // 支持 Integer、Float 等 List<Double[]> values = new ArrayList<>(); for (List<Object> list : valueList) { Double[] value = list.stream() .map(obj -> ((Number) obj).doubleValue()) .toArray(Double[]::new); values.add(value); } // 柱状图y轴 Double[] barValue = data.get(chartExcelDto.getBarValue()).stream() .map(obj -> ((Number) obj).doubleValue()) .toArray(Double[]::new); // 创建数据源 XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories); List<XDDFNumericalDataSource<Double>> lineValuesDataList = new ArrayList<>(); for (Double[] value : values) { lineValuesDataList.add(XDDFDataSourcesFactory.fromArray(value)); } XDDFNumericalDataSource<Double> barValuesData = XDDFDataSourcesFactory.fromArray(barValue); // 创建一个新的工作簿 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("数据表"); // 合并单元格并居中显示标题 XSSFRow headerRow = sheet.createRow(0); sheet.addMergedRegion(new CellRangeAddress(0, 0, 3, 7)); XSSFCell titleCell = headerRow.createCell(3); titleCell.setCellValue("趋势图"); XSSFCellStyle centerStyle = workbook.createCellStyle(); centerStyle.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER); centerStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER); titleCell.setCellStyle(centerStyle); // 创建绘图工具 XSSFDrawing drawingPatriarch = sheet.createDrawingPatriarch(); XSSFClientAnchor anchor = workbook.getCreationHelper().createClientAnchor(); anchor.setCol1(3); anchor.setRow1(1); anchor.setCol2(8); anchor.setRow2(20); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); XSSFChart chart = drawingPatriarch.createChart(anchor); // 配置坐标轴 XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFValueAxis valueAxisLeft = chart.createValueAxis(AxisPosition.LEFT); // 柱状图 XDDFBarChartData barData = (XDDFBarChartData) chart.createData(ChartTypes.BAR, categoryAxis, valueAxisLeft); barData.setBarDirection(BarDirection.COL); XDDFChartData.Series barSeries = barData.addSeries(categoriesData, barValuesData); barSeries.setTitle(chartExcelDto.getBarValue(), null); // 折线图 XDDFLineChartData lineData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, categoryAxis, valueAxisLeft); for (int i = 0; i < lineValuesDataList.size(); i++) { XDDFChartData.Series lineSeries = lineData.addSeries(categoriesData, lineValuesDataList.get(i)); lineSeries.setTitle(valueKeyList.get(i), null); } chart.plot(barData); chart.plot(lineData); // 定义保存路径(Linux 路径) // 定义 Linux 下的文件保存路径 String basePath = "/opt/excel/output/"; String fileName = IdUtil.getSnowflakeNextIdStr() + ".xlsx"; String filePath = basePath + fileName; File dir = new File(basePath); if (!dir.exists()) { boolean mkdirSuccess = dir.mkdirs(); if (!mkdirSuccess) { log.error("创建目录失败: {}", basePath); return "创建文件目录失败"; } } // 保存文件到 Linux 服务器 try (FileOutputStream fileOut = new FileOutputStream(filePath)) { workbook.write(fileOut); } catch (IOException e) { log.error("写入Excel文件失败: {}", e.getMessage(), e); return "生成文件失败"; } finally { try { workbook.close(); } catch (IOException e) { log.error("关闭Excel工作簿失败: {}", e.getMessage(), e); } } log.info("生成excel图表成功"); return filePath; }
参数:
▼js复制代码{ "data": { "Series1": [ 10, 20, 30, 40, 50 ], "Series2": [ 40, 20, 100 ], "Series3": [ 10, 20, 80, 70, 60 ], "bar": [ 20, 40, 60, 70, 10 ], "Month": [ "2025-01", "2025-02", "2025-03", "2025-04", "2025-05" ] }, "categories": "Month", "valueList": [ "Series1", "Series2", "Series3" ], "barValue": "bar" }
实现效果:

评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
作者分享
唉,感觉用了AI过后,自己代码能力就下降了好多,不太会写代码了都。
1
发个内推
3
Spring AI mcp的baseUrl问题解决了
4
Ai智能体项目关于MCP部分的问题有人知道吗?
1.Ai智能体项目的mcp,通过sse方式如果服务端不启用或者挂了,客户端也会崩掉,有没有啥配置即使服务端崩掉了,客户端也可以正常使用只是不用这个智能体接口或者工具。
2.如果服务端配置了server.servlet.context-path,客户端即使在sse-endpoint里面带上了context-path,比如/api,但是还是会重定向错误302
2
java有什么关于图表生成的工具吗?搜了一下JFreeChart感觉图像样式有点老旧啊。
1
