springboot對(duì)接poi實(shí)現(xiàn)導(dǎo)出excel并動(dòng)態(tài)生成折線圖
在Spring Boot項(xiàng)目中,使用Apache POI庫(kù)可以實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出為Excel并嵌入動(dòng)態(tài)生成的折線圖。下面為您詳細(xì)介紹具體的實(shí)現(xiàn)步驟、核心代碼以及注意事項(xiàng)。
環(huán)境準(zhǔn)備:添加依賴
首先,在您的pom.xml文件中添加必要的依賴。推薦使用較新版本的POI以確保功能穩(wěn)定。
<dependencies>
<!-- Spring Boot Web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Apache POI 核心庫(kù) -->
<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>
定義數(shù)據(jù)模型
為了清晰管理圖表數(shù)據(jù)和在Excel中的位置,建議先定義兩個(gè)實(shí)體類。
??1. 折線圖數(shù)據(jù)模型 (LineChart):?? 這個(gè)類用于封裝折線圖的所有元素,包括標(biāo)題、數(shù)據(jù)系列和X軸標(biāo)簽。
@Data
@Accessors(chain = true)
public class LineChart {
/**
* 圖表的名稱(主標(biāo)題)
*/
private String chartTitle;
/**
* 每條折線的名稱(圖例)
*/
private List<String> titleList;
/**
* 每條折線對(duì)應(yīng)的數(shù)據(jù)值
*/
private List<List<Double>> dataList;
/**
* X軸的數(shù)據(jù)點(diǎn)標(biāo)簽(如:月份、季度)
*/
private List<Object> xAxisList;
}
??2. 圖表位置模型 (ChartPosition):?? 這個(gè)類用于精確定義圖表在Excel工作表中的位置和大小。
@Data
@Accessors(chain = true)
public class ChartPosition {
/** 圖表左上角所在的列索引(從0開始) */
private int col1;
/** 圖表左上角所在的行索引(從0開始) */
private int row1;
/** 圖表右下角所在的列索引 */
private int col2;
/** 圖表右下角所在的行索引 */
private int row2;
// 以下偏移量通??稍O(shè)為0
private int dx1 = 0;
private int dy1 = 0;
private int dx2 = 0;
private int dy2 = 0;
}
核心工具類:創(chuàng)建折線圖
這是最關(guān)鍵的步驟,我們將創(chuàng)建一個(gè)工具類ChartUtils,其中的createLine方法負(fù)責(zé)在指定的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. 獲取數(shù)據(jù)
List<Object> xAxisList = lineChart.getXAxisList();
List<String> chartTitleList = lineChart.getTitleList();
List<List<Double>> chartDataList = lineChart.getDataList();
String chartTitle = lineChart.getChartTitle();
// 2. 創(chuàng)建繪圖對(duì)象和圖表錨點(diǎn)
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0,
chartPosition.getCol1(), chartPosition.getRow1(),
chartPosition.getCol2(), chartPosition.getRow2());
// 3. 創(chuàng)建圖表并設(shè)置標(biāo)題
XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText(chartTitle);
chart.setTitleOverlay(false);
// 4. 設(shè)置圖例位置
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP);
// 5. 創(chuàng)建坐標(biāo)軸
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
// 6. 準(zhǔn)備數(shù)據(jù)源
// 6.1 X軸數(shù)據(jù)(類別)
XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(
Arrays.copyOf(xAxisList.toArray(), xAxisList.size(), String[].class));
// 6.2 創(chuàng)建折線圖數(shù)據(jù)對(duì)象
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
// 7. 為每個(gè)數(shù)據(jù)系列創(chuàng)建折線
for (int i = 0; i < chartDataList.size(); i++) {
List<Double> values = chartDataList.get(i);
// 創(chuàng)建Y軸數(shù)據(jù)源
XDDFNumericalDataSource<Double> dataSource = XDDFDataSourcesFactory.fromArray(
values.toArray(new Double[0]));
// 將數(shù)據(jù)系列添加到圖表
XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, dataSource);
series.setTitle(chartTitleList.get(i), null);
series.setSmooth(false); // 設(shè)置為折線,非平滑曲線
series.setMarkerSize((short) 2); // 設(shè)置數(shù)據(jù)點(diǎn)標(biāo)記的大小
// (可選)特殊樣式處理,例如為"警戒值"設(shè)置虛線
if ("警戒值".equals(chartTitleList.get(i))) {
XDDFLineProperties lineProps = new XDDFLineProperties();
lineProps.setPresetDash(new XDDFPresetLineDash(PresetLineDash.DOT));
series.setLineProperties(lineProps);
}
}
// 8. 繪制圖表
chart.plot(data);
}
}
業(yè)務(wù)層整合與導(dǎo)出接口
最后,在Spring Boot的Controller中,將數(shù)據(jù)導(dǎo)出和圖表生成功能整合起來(lái),提供一個(gè)HTTP接口供前端調(diào)用。
@RestController
public class ExcelExportController {
@GetMapping("/export/excel-with-chart")
public void exportExcelWithChart(HttpServletResponse response) throws IOException {
// 1. 設(shè)置響應(yīng)頭,告訴瀏覽器這是一個(gè)要下載的Excel文件
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename="data_with_chart.xlsx"");
// 2. 創(chuàng)建工作簿和工作表
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("數(shù)據(jù)報(bào)表");
// 3. (可選)向工作表填充數(shù)據(jù)行...
// 例如:createDataRows(sheet);
// 4. 準(zhǔn)備折線圖數(shù)據(jù)
LineChart lineChart = new LineChart()
.setChartTitle("銷售趨勢(shì)圖")
.setXAxisList(Arrays.asList("1月", "2月", "3月", "4月", "5月"))
.setTitleList(Arrays.asList("產(chǎn)品A", "產(chǎn)品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列結(jié)束)
ChartPosition position = new ChartPosition()
.setCol1(0).setRow1(10).setCol2(10).setRow2(25);
// 6. 調(diào)用工具類創(chuàng)建折線圖
ChartUtils.createLine(sheet, position, lineChart);
// 7. 將工作簿寫入HTTP響應(yīng)流
OutputStream out = response.getOutputStream();
workbook.write(out);
workbook.close();
out.flush();
}
}
關(guān)鍵要點(diǎn)與優(yōu)化建議
在實(shí)際使用中,請(qǐng)注意以下幾點(diǎn)以確保最佳效果:
- ??版本兼容性??:確保所有POI相關(guān)依賴(如
poi,poi-ooxml,poi-ooxml-schemas)的版本一致,以避免潛在的沖突。 - ??圖表位置規(guī)劃??:在插入圖表前,最好先規(guī)劃好數(shù)據(jù)表格的布局。
ChartPosition中的行索引應(yīng)考慮表格已占用的行數(shù),防止圖表覆蓋數(shù)據(jù)。 - ??大數(shù)據(jù)量?jī)?yōu)化??:當(dāng)需要導(dǎo)出的數(shù)據(jù)量非常大時(shí),建議使用
SXSSFWorkbook來(lái)代替XSSFWorkbook,它以流式處理方式工作,可以顯著降低內(nèi)存消耗。 - ??前端調(diào)用??:前端Vue或React應(yīng)用可以使用
axios等庫(kù)調(diào)用此導(dǎo)出接口,并通過(guò)處理返回的Blob對(duì)象實(shí)現(xiàn)文件下載。
通過(guò)以上步驟,您就可以在Spring Boot應(yīng)用中靈活地導(dǎo)出包含專業(yè)折線圖的Excel報(bào)表了。這套方法可以根據(jù)實(shí)際業(yè)務(wù)需求,輕松調(diào)整以生成柱狀圖或餅圖等其他圖表類型。
到此這篇關(guān)于springboot對(duì)接poi實(shí)現(xiàn)導(dǎo)出excel并動(dòng)態(tài)生成折線圖的文章就介紹到這了,更多相關(guān)springboot導(dǎo)出excel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+EasyPOI實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)導(dǎo)出Excel實(shí)戰(zhàn)指南
- SpringBoot整合EasyPoi實(shí)現(xiàn)復(fù)雜多級(jí)表頭Excel導(dǎo)出的完整方案
- SpringBoot集成EasyExcel實(shí)現(xiàn)百萬(wàn)級(jí)別的數(shù)據(jù)導(dǎo)入導(dǎo)出實(shí)踐指南
- SpringBoot后臺(tái)使用EasyExcel實(shí)現(xiàn)數(shù)據(jù)報(bào)表導(dǎo)出(含模板、樣式、美化)
- SpringBoot導(dǎo)出Excel的四種方式小結(jié)
- SpringBoot集成Apache POI實(shí)現(xiàn)Excel的導(dǎo)入導(dǎo)出
相關(guān)文章
詳細(xì)聊聊RabbitMQ竟無(wú)法反序列化List問(wèn)題
這篇文章主要給大家介紹了關(guān)于RabbitMQ竟無(wú)法反序列化List的相關(guān)資料,文中通過(guò)示例代碼將問(wèn)題以及解決的過(guò)程介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-09-09
解析Java的InputStream類并借助其讀取ppt文件
這篇文章主要介紹了Java的InputStream類并借助其讀取ppt文件,講到了InputStream類中一些常用的方法的問(wèn)題,需要的朋友可以參考下2015-11-11
Json傳輸出現(xiàn)中文亂碼問(wèn)題的解決辦法
最近遇到一個(gè)問(wèn)題,就是將中文消息以json格式推給微信服務(wù)器時(shí),收到的消息是亂碼,所以下面這篇文章主要給大家介紹了關(guān)于Json傳輸出現(xiàn)中文亂碼問(wèn)題的解決辦法,需要的朋友可以參考下2023-05-05
springboot執(zhí)行延時(shí)任務(wù)之DelayQueue的使用詳解
DelayQueue是一個(gè)無(wú)界阻塞隊(duì)列,只有在延遲期滿時(shí),才能從中提取元素。這篇文章主要介紹了springboot執(zhí)行延時(shí)任務(wù)-DelayQueue的使用,需要的朋友可以參考下2019-12-12
如何實(shí)現(xiàn)Java線程安全問(wèn)題
這篇文章主要介紹了如何實(shí)現(xiàn)Java線程安全問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
使用ScheduledThreadPoolExecutor踩過(guò)最痛的坑
這篇文章主要介紹了使用ScheduledThreadPoolExecutor踩過(guò)最痛的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Java中TimedCache緩存對(duì)象的詳細(xì)使用教程
TimedCache是一個(gè)泛型類,它的主要作用通常是在一定時(shí)間范圍內(nèi)對(duì)特定鍵值對(duì)進(jìn)行緩存,并且能夠根據(jù)設(shè)定的時(shí)間策略來(lái)自動(dòng)清理過(guò)期的緩存項(xiàng),本文給大家介紹了Java中TimedCache緩存對(duì)象的詳細(xì)使用教程,需要的朋友可以參考下2024-12-12

