在Spring Boot项目中,使用Apache POI库可以实现将数据导出为Excel并嵌入动态生成的折线图。下面为您详细介绍具体的实现步骤、核心代码以及注意事项。
首先,在您的pom.xml文件中添加必要的依赖。推荐使用较新版本的POI以确保功能稳定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<dependencies> <!-- Spring Boot Web 支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Apache POI 核心库 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.3</version> </dependency> <!-- 处理 xlsx 格式的OOXML支持 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> <!-- 可选的模式支持,某些图表功能需要 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> </dependencies> |
为了清晰管理图表数据和在Excel中的位置,建议先定义两个实体类。
??1. 折线图数据模型 (LineChart):?? 这个类用于封装折线图的所有元素,包括标题、数据系列和X轴标签。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Data @Accessors(chain = true) public class LineChart { /** * 图表的名称(主标题) */ private String chartTitle; /** * 每条折线的名称(图例) */ private List<String> titleList; /** * 每条折线对应的数据值 */ private List<List<Double>> dataList; /** * X轴的数据点标签(如:月份、季度) */ private List<Object> xAxisList; } |
??2. 图表位置模型 (ChartPosition):?? 这个类用于精确定义图表在Excel工作表中的位置和大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Data @Accessors(chain = true) public class ChartPosition { /** 图表左上角所在的列索引(从0开始) */ private int col1; /** 图表左上角所在的行索引(从0开始) */ private int row1; /** 图表右下角所在的列索引 */ private int col2; /** 图表右下角所在的行索引 */ private int row2; // 以下偏移量通常可设为0 private int dx1 = 0; private int dy1 = 0; private int dx2 = 0; private int dy2 = 0; } |
这是最关键的步骤,我们将创建一个工具类ChartUtils,其中的createLine方法负责在指定的Excel工作表中绘制折线图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import org.apache.poi.xssf.usermodel.*; import org.apache.poi.ss.usermodel.charts.*; import org.apache.poi.xddf.usermodel.chart.*;
public class ChartUtils {
public static void createLine(XSSFSheet sheet, ChartPosition chartPosition, LineChart lineChart) { // 1. 获取数据 List<Object> xAxisList = lineChart.getXAxisList(); List<String> chartTitleList = lineChart.getTitleList(); List<List<Double>> chartDataList = lineChart.getDataList(); String chartTitle = lineChart.getChartTitle();
// 2. 创建绘图对象和图表锚点 XSSFDrawing drawing = sheet.createDrawingPatriarch(); XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartPosition.getCol1(), chartPosition.getRow1(), chartPosition.getCol2(), chartPosition.getRow2()); // 3. 创建图表并设置标题 XSSFChart chart = drawing.createChart(anchor); chart.setTitleText(chartTitle); chart.setTitleOverlay(false);
// 4. 设置图例位置 XDDFChartLegend legend = chart.getOrAddLegend(); legend.setPosition(LegendPosition.TOP);
// 5. 创建坐标轴 XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
// 6. 准备数据源 // 6.1 X轴数据(类别) XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray( Arrays.copyOf(xAxisList.toArray(), xAxisList.size(), String[].class)); // 6.2 创建折线图数据对象 XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
// 7. 为每个数据系列创建折线 for (int i = 0; i < chartDataList.size(); i++) { List<Double> values = chartDataList.get(i); // 创建Y轴数据源 XDDFNumericalDataSource<Double> dataSource = XDDFDataSourcesFactory.fromArray( values.toArray(new Double[0]));
// 将数据系列添加到图表 XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, dataSource); series.setTitle(chartTitleList.get(i), null); series.setSmooth(false); // 设置为折线,非平滑曲线 series.setMarkerSize((short) 2); // 设置数据点标记的大小
// (可选)特殊样式处理,例如为"警戒值"设置虚线 if ("警戒值".equals(chartTitleList.get(i))) { XDDFLineProperties lineProps = new XDDFLineProperties(); lineProps.setPresetDash(new XDDFPresetLineDash(PresetLineDash.DOT)); series.setLineProperties(lineProps); } }
// 8. 绘制图表 chart.plot(data); } } |
最后,在Spring Boot的Controller中,将数据导出和图表生成功能整合起来,提供一个HTTP接口供前端调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
@RestController public class ExcelExportController {
@GetMapping("/export/excel-with-chart") public void exportExcelWithChart(HttpServletResponse response) throws IOException { // 1. 设置响应头,告诉浏览器这是一个要下载的Excel文件 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename="data_with_chart.xlsx"");
// 2. 创建工作簿和工作表 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("数据报表");
// 3. (可选)向工作表填充数据行... // 例如:createDataRows(sheet);
// 4. 准备折线图数据 LineChart lineChart = new LineChart() .setChartTitle("销售趋势图") .setXAxisList(Arrays.asList("1月", "2月", "3月", "4月", "5月")) .setTitleList(Arrays.asList("产品A", "产品B", "警戒值")) .setDataList(Arrays.asList( Arrays.asList(120.0, 150.0, 180.0, 160.0, 200.0), Arrays.asList(90.0, 120.0, 140.0, 130.0, 150.0), Arrays.asList(150.0, 150.0, 150.0, 150.0, 150.0) // 警戒线 ));
// 5. 定义图表位置(例如:从第0行第0列开始,到第15行第10列结束) ChartPosition position = new ChartPosition() .setCol1(0).setRow1(10).setCol2(10).setRow2(25);
// 6. 调用工具类创建折线图 ChartUtils.createLine(sheet, position, lineChart);
// 7. 将工作簿写入HTTP响应流 OutputStream out = response.getOutputStream(); workbook.write(out); workbook.close(); out.flush(); } } |
在实际使用中,请注意以下几点以确保最佳效果:
通过以上步骤,您就可以在Spring Boot应用中灵活地导出包含专业折线图的Excel报表了。这套方法可以根据实际业务需求,轻松调整以生成柱状图或饼图等其他图表类型。