在Spring Boot项目中,使用Apache POI库可以实现将数据导出为Excel并嵌入动态生成的折线图。下面为您详细介绍具体的实现步骤、核心代码以及注意事项。
环境准备:添加依赖
首先,在您的pom.xml
文件中添加必要的依赖。推荐使用较新版本的POI以确保功能稳定。
<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轴标签。
@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工作表中的位置和大小。
@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工作表中绘制折线图。
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接口供前端调用。
@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();
}
}
关键要点与优化建议
在实际使用中,请注意以下几点以确保最佳效果:
- 版本兼容性:确保所有POI相关依赖(如
poi
,poi-ooxml
,poi-ooxml-schemas
)的版本一致,以避免潜在的冲突。 - 图表位置规划:在插入图表前,最好先规划好数据表格的布局。
ChartPosition
中的行索引应考虑表格已占用的行数,防止图表覆盖数据。 - 大数据量优化:当需要导出的数据量非常大时,建议使用
SXSSFWorkbook
来代替XSSFWorkbook
,它以流式处理方式工作,可以显著降低内存消耗。 - 前端调用:前端Vue或React应用可以使用
axios
等库调用此导出接口,并通过处理返回的Blob对象实现文件下载。
通过以上步骤,您就可以在Spring Boot应用中灵活地导出包含专业折线图的Excel报表了。这套方法可以根据实际业务需求,轻松调整以生成柱状图或饼图等其他图表类型。
到此这篇关于springboot对接poi实现导出excel并动态生成折线图的文章就介绍到这了,更多相关springboot导出excel内容请搜索QQ沐编程以前的文章或继续浏览下面的相关文章希望大家以后多多支持QQ沐编程!
© 版权声明
本站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!
THE END