Java在excel中導出動態曲線圖DEMO

1、環境

JDK8

POI 5.2.3

Springboot2.7

2、DEMO

pom

        <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency>

java

    @GetMapping("/export")public ResponseEntity<byte[]> exportExcel() throws IOException {// 創建工作簿和工作表XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet("Chart");// 自定義數據源List<String> xValues = Arrays.asList("A", "B", "C", "D", "E");List<Double> line1Values = Arrays.asList(10.0, 15.0, 20.0, 25.0, 30.0);List<Double> line2Values = Arrays.asList(5.0, 7.0, 9.0, 11.0, 13.0);XSSFSheet hiddenSheet = workbook.createSheet("Hidden Data");workbook.setSheetHidden(workbook.getSheetIndex(hiddenSheet), true);Row hiddenRow = hiddenSheet.createRow(0);for (int i = 0; i < xValues.size(); i++) {Cell cell = hiddenRow.createCell(i);cell.setCellValue(xValues.get(i));}for (int i = 0; i < 10; i++) {createChart("title" + i, sheet,hiddenSheet,i,xValues,line1Values,i%2 == 0 ? line2Values: null);}// 將工作簿寫入字節數組ByteArrayOutputStream outputStream = new ByteArrayOutputStream();workbook.write(outputStream);workbook.close();// 設置響應頭HttpHeaders headersResponse = new HttpHeaders();headersResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM);headersResponse.setContentDispositionFormData("attachment", "chart.xlsx");return new ResponseEntity<>(outputStream.toByteArray(), headersResponse, HttpStatus.OK);}private void createChart(String title, XSSFSheet sheet, XSSFSheet hiddenSheet, int index, List<String> xValues, List<Double> line1Values, List<Double> line2Values) {XSSFDrawing drawing = sheet.createDrawingPatriarch();XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, index * 21, 15, index * 21 + 20);XSSFChart chart = drawing.createChart(anchor);chart.setTitleText(title);chart.setTitleOverlay(false);XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);xAxis.setTitle(" ");XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);yAxis.setTitle(" ");XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(hiddenSheet,new CellRangeAddress(0, 0, 0,  xValues.size() - 1));XDDFLineChartData lineChartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);XDDFNumericalDataSource<Double> line1 = XDDFDataSourcesFactory.fromArray(line1Values.toArray(new Double[0]));XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) lineChartData.addSeries(xs, line1);if (CollUtil.isNotEmpty(line2Values)) {XDDFNumericalDataSource<Double> line2 = XDDFDataSourcesFactory.fromArray(line2Values.toArray(new Double[0]));XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) lineChartData.addSeries(xs, line2);}chart.plot(lineChartData);}

說明,封裝了一個方法,createChart。

圖表位置

XSSFClientAnchor anchor = drawing.createAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2);

參數說明:

  • dx1dy1

    • 表示圖表左上角相對于單元格左上角的偏移量(以 EMU 為單位)。
    • 1 EMU = 1/360000 厘米。
    • 如果你不需要精確控制偏移量,可以將這兩個值設置為?0
  • dx2dy2

    • 表示圖表右下角相對于單元格右下角的偏移量(以 EMU 為單位)。
    • 同樣,如果你不需要精確控制偏移量,可以將這兩個值設置為?0
  • col1row1

    • 表示圖表左上角所在的單元格列號和行號(從 0 開始計數)。
    • 例如,col1 = 5?表示圖表左上角位于第 6 列(F 列),row1 = 0?表示圖表左上角位于第 1 行。
  • col2row2

    • 表示圖表右下角所在的單元格列號和行號(從 0 開始計數)。
    • 例如,col2 = 15?表示圖表右下角位于第 16 列(P 列),row2 = 20?表示圖表右下角位于第 21 行。

hiddenSheet存在的目的是

1.?Apache POI 的圖表數據綁定機制

Apache POI 的圖表功能是基于 Excel 的底層結構設計的。在 Excel 中,圖表的數據源通常是從工作表中的單元格范圍(CellRangeAddress)中讀取的。也就是說,圖表的 X 軸和 Y 軸數據必須綁定到某個單元格范圍,即使這些單元格并不直接顯示在工作表中。

核心原因:

  • Apache POI 的?XDDFDataSourcesFactory.fromStringCellRange()?方法要求傳入一個有效的單元格范圍。
  • 如果沒有單元格范圍,POI 不知道如何為圖表提供數據源,因此會導致圖表無法正確顯示。

所以我采用了還是用了隱藏的方式。對于整個sheet的布局

3、效果

有個小bug

這個系列1這幾個字去不掉,圖表工具提示中的“系列名稱”(如“系列1”)是由 Excel 自動生成的。雖然 Apache POI 不支持直接修改或自定義工具提示的內容

一下方法可以一試。

  // 隱藏圖例(可選)XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.TOP); // 將圖例移出可視區域

對于目前項目而言,影響不大。不改動了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80319.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80319.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80319.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android APP 爬蟲操作

工具 夜神模擬器、charles、mitm 等 mitm的使用參考:Mitmproxy對Android進行抓包&#xff08;真機&#xff09;_mitmproxy 安卓-CSDN博客 charles的使用參考&#xff1a;【全網最詳細】手把手教學Charles抓包工具詳細自學教程&#xff0c;完整版安裝教程&#xff0c;詳細介紹…

Redis的LFU策略具體怎么工作?

Redis的LFU&#xff08;Least Frequently Used&#xff09;策略通過動態跟蹤鍵的訪問頻率實現淘汰決策&#xff0c;其核心工作邏輯可分為以下四個部分&#xff1a; 數據結構設計? 字段拆分?&#xff1a;每個Redis對象&#xff08;redisObject&#xff09;的lru字段&#xff…

Redis 及其在系統設計中的作用

什么是Redis Redis 是一個開源的內存數據結構存儲系統&#xff0c;可用作數據庫、緩存和消息代理。它因其快速的性能、靈活性和易用性而得到廣泛應用。 Redis 數據存儲類型 Redis 允許開發人員以各種數據結構&#xff08;例如字符串、位圖、位域、哈希、列表、集合、有序集合…

MySQL:如何用關系型數據庫征服NoSQL核心戰場?

寫在前面&#xff1a;當SQL遇見NoSQL的十年之變 2012年MongoDB掀起文檔數據庫革命時&#xff0c;開發者們不得不在靈活性與事務一致性之間做痛苦抉擇。十年后的今天&#xff0c;MySQL 8.0的JSON功能已實現&#xff1a; ? 二進制存儲效率超越傳統BLOB 40% ? 多值索引使JSON查…

Dart Flutter數據類型詳解 int double String bool list Map

目錄 字符串的幾種方式 bool值的判斷 List的定義方式 Map的定義方式 Dart判斷數據類型 (is 關鍵詞來判斷類型) Dart的數據類型詳解 int double String bool list Map 常用數據類型: Numbers(數值): int double Strings(字符串) String Booleans(布爾…

win11中wsl在自定義位置安裝ubuntu20.04 + ROS Noetic

wsl的安裝 環境自定義位置安裝指定ubuntu版本VsCodeROS備份與重載備份重新導入 常用命令參考文章 環境 搜索 啟用或關閉 Windows 功能 勾選這2個功能&#xff0c;然后重啟 自定義位置安裝指定ubuntu版本 從網上找到你所需要的相關wsl ubuntu版本的安裝包&#xff0c;一般直…

得物業務參數配置中心架構綜述

一、背景 現狀與痛點 在目前互聯網飛速發展的今天&#xff0c;企業對用人的要求越來越高&#xff0c;尤其是后端的開發同學大部分精力都要投入在對復雜需求的處理&#xff0c;以及代碼架構&#xff0c;穩定性的工作中&#xff0c;在對比下&#xff0c;簡單且重復的CRUD就顯得…

Nginx 二進制部署與 Docker 部署深度對比

一、核心概念解析 1. 二進制部署 通過包管理器&#xff08;如 apt/yum&#xff09;或源碼編譯安裝 Nginx&#xff0c;直接運行在宿主機上。其特點包括&#xff1a; 直接性&#xff1a;與操作系統深度綁定&#xff0c;直接使用系統庫和內核功能 。定制化&#xff1a;支持通過…

Rust 2025:內存安全革命與異步編程新紀元

Rust 2025 Edition通過區域內存管理、泛型關聯類型和零成本異步框架三大革新&#xff0c;重新定義系統級編程語言的能力邊界。本次升級不僅將內存安全驗證效率提升80%&#xff0c;更通過異步執行器架構優化實現微秒級任務切換。本文從編譯器原理、運行時機制、編程范式轉型三個…

std::unorderd_map 簡介

1. unorderd_map 簡介 1. unorderd_map 簡介 簡介1.1. 實現原理1.2. 函數1.3. 問題集 1.3.1. emplace、emplace_hint、insert 的區別 1.4. 參考鏈接 簡介 unordered_map 是 C 標準庫中的一個容器&#xff0c;它定義在 <unordered_map> 頭文件里。它借助哈希表來存儲鍵…

在線測試來料公差

UI 上圖 V1 上圖 V2 V3 Code import tkinter as tk from tkinter import messagebox, scrolledtext import socket import threading from datetime import datetime import os import logging from PIL import Image, ImageTk import subprocess# 定義文件夾路徑…

【優秀三方庫研讀】【C++基礎知識】odygrd/quill -- 折疊表達式

compute_encoded_size_and_cache_string_lengths 方法中這段代碼是一個C的折疊表達式&#xff08;fold expression&#xff09;的應用&#xff0c;用于計算多個參數編碼后的總大小。下面我將詳細解釋這段代碼的每個部分&#xff0c;并說明為什么這樣寫。 代碼如下&#xff1a; …

數據庫安裝和升級和雙主配置

備份和導入數據 ./mysqldump -u root -p123321 test > test.sql rsync -av test.sql root192.168.0.212:/usr/local/mysql/ ./mysql -uroot -p test < …/test.sql sudo tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ sudo ln -sfn /usr/loca…

【C語言】條件編譯

&#x1f984;個人主頁:修修修也 &#x1f38f;所屬專欄:C語言 ??操作環境:Visual Studio 2022 目錄 條件編譯 常用的預處理指令 核心應用場景 1.防止頭文件重復包含 2.跨平臺兼容性 3.調試模式與發布模式 4.功能開關 5.代碼兼容性處理 結語 條件編譯 一般情況下,源程序中所有…

如何在安卓平板上下載安裝Google Chrome【輕松安裝】

安卓平板可以通過系統內置的應用商店直接搜索并下載谷歌瀏覽器。用戶打開平板上的“Play 商店”&#xff0c;在搜索框輸入Google Chrome。出現結果后&#xff0c;點擊第一個帶有“Google LLC”字樣的應用圖標&#xff0c;然后點“安裝”按鈕。下載和安裝時間和網速有關&#xf…

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7 1、簡介2、功能特點3、知識產權保護功能4、強大的許可系統5、軟件開發工具包6、部署方式7、下載 1、簡介 .NET Reactor是用于為.NET Framework編寫的軟件的功能強大的代碼保護和軟件許可系統&#xff0c;并且支持生成…

利用 SSE 實現文字吐字效果:技術與實踐

利用 SSE 實現文字吐字效果:技術與實踐 引言 在現代 Web 應用開發中,實時交互功能愈發重要。例如,在線聊天、實時數據監控、游戲中的實時更新等場景,都需要服務器能夠及時將數據推送給客戶端。傳統的請求 - 響應模式在處理實時性要求較高的場景時顯得力不從心,而 Server…

一個簡單易用的密碼生成器

基于瀏覽器的確定性密碼生成工具&#xff0c;通過用戶輸入的網站名稱和鹽值生成符合安全要求的密碼。特點&#xff1a; ? 相同輸入始終生成相同密碼 ? 密碼自動包含大小寫字母、數字和特殊符號 ? 以字母開頭&#xff0c;固定8位長度 ? 完全在客戶端運行&#xff0c;保護…

水上與水下遙控技術要點對比

1. 水上無人機遙控器技術要點 (1) 控制方式 多通道控制&#xff1a;通常使用2.4GHz或5.8GHz無線電信號&#xff0c;支持多通道&#xff08;如4通道以上&#xff09;分別控制飛行器的姿態&#xff08;俯仰、橫滾、偏航&#xff09;和油門。 高級飛行模式&#xff1a;如定高模…

Android_SDK鏈接 雷神模擬器(端口問題) --- app筆記

調試環境&#xff1a;JDK&#xff08;java&#xff09; SDK&#xff08;android&#xff09; Node.js 雷神模擬器&#xff08;或 真機&#xff09; Appium&#xff08;Appium Server【內外件&#xff08;dos內件、界面化工具&#xff09;】、Appium Inspector&#xff09; p…