EasyExcel实现Excel数据的可视化展示
引言:从Excel到可视化的困境与解决方案
你是否还在为Excel数据的可视化展示而烦恼?当面对海量Excel数据时,手动整理、导入数据库再进行可视化的过程是否让你感到效率低下?本文将详细介绍如何利用阿里巴巴开源的EasyExcel工具,结合Java可视化库,实现Excel数据的高效读取与多样化可视化展示,帮助你轻松解决这一痛点。
读完本文,你将能够:
- 了解EasyExcel的核心优势及其在数据处理中的应用
- 掌握使用EasyExcel读取不同格式Excel文件的方法
- 学会将Excel数据转换为适合可视化的格式
- 实现多种常见图表的绘制,如折线图、柱状图、饼图等
- 了解高级可视化技巧,如动态刷新和交互式图表
EasyExcel简介:高效处理Excel的利器
EasyExcel的核心优势
EasyExcel是阿里巴巴开源的一款Java处理Excel工具,它具有以下核心优势:
-
内存占用低:采用逐行读取的方式,避免将整个文件加载到内存中,解决了传统Excel处理工具在处理大文件时容易出现内存溢出的问题。
-
操作简便:提供简洁的API,通过少量代码即可实现Excel文件的读写操作。
-
功能强大:支持Excel文件的读写、格式转换、数据验证等多种功能。
-
扩展性好:支持自定义转换器、监听器等,可根据需求进行功能扩展。
EasyExcel的基本架构
EasyExcel的核心架构主要包括以下几个部分:
classDiagram
class EasyExcel {
+read()
+write()
}
class ExcelReader {
+read()
+doRead()
}
class ExcelWriter {
+write()
+finish()
}
class AnalysisEventListener {
+invoke()
+doAfterAllAnalysed()
}
EasyExcel --> ExcelReader
EasyExcel --> ExcelWriter
ExcelReader --> AnalysisEventListener
- EasyExcel:提供静态方法,简化Excel读写操作的入口类。
- ExcelReader:负责Excel文件的读取,支持多种读取方式。
- ExcelWriter:负责Excel文件的写入,支持多种写入方式。
- AnalysisEventListener:读取监听器,用于处理读取到的数据。
准备工作:环境搭建与依赖配置
环境要求
- JDK 1.8及以上
- Maven 3.0及以上
依赖配置
在Maven项目的pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 可视化依赖 -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.3</version>
</dependency>
EasyExcel读取Excel数据:从基础到进阶
基础读取:使用监听器读取数据
EasyExcel采用监听器模式处理读取到的数据,通过实现AnalysisEventListener接口来处理Excel数据。
定义数据模型
@Data
public class SalesData {
@ExcelProperty("日期")
private String date;
@ExcelProperty("销售额")
private Double sales;
@ExcelProperty("产品类别")
private String category;
}
实现监听器
public class SalesDataListener extends AnalysisEventListener<SalesData> {
private List<SalesData> dataList = new ArrayList<>();
@Override
public void invoke(SalesData data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据读取完成后的操作
}
public List<SalesData> getDataList() {
return dataList;
}
}
读取Excel文件
public class ExcelReaderDemo {
public static void main(String[] args) {
String fileName = "sales_data.xlsx";
SalesDataListener listener = new SalesDataListener();
EasyExcel.read(fileName, SalesData.class, listener).sheet().doRead();
List<SalesData> dataList = listener.getDataList();
System.out.println("读取到数据:" + dataList.size() + "条");
}
}
进阶读取:分页读取与条件过滤
分页读取
使用PageReadListener实现分页读取:
public class PageReadDemo {
public static void main(String[] args) {
String fileName = "large_data.xlsx";
// 每页读取100条数据
EasyExcel.read(fileName, LargeData.class, new PageReadListener<LargeData>(dataList -> {
System.out.println("读取到一页数据:" + dataList.size() + "条");
// 处理当前页数据
}, 100)).sheet().doRead();
}
}
条件过滤
在监听器中实现数据过滤:
public class FilterDataListener extends AnalysisEventListener<SalesData> {
private List<SalesData> filteredData = new ArrayList<>();
private String targetCategory;
public FilterDataListener(String targetCategory) {
this.targetCategory = targetCategory;
}
@Override
public void invoke(SalesData data, AnalysisContext context) {
if (targetCategory.equals(data.getCategory())) {
filteredData.add(data);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
public List<SalesData> getFilteredData() {
return filteredData;
}
}
数据可视化:从数据到图表
数据转换:为可视化准备数据
在进行可视化之前,需要将读取到的原始数据转换为适合图表展示的格式。
按类别汇总销售额
public class DataProcessor {
public static Map<String, Double> aggregateByCategory(List<SalesData> dataList) {
Map<String, Double> categorySales = new HashMap<>();
for (SalesData data : dataList) {
String category = data.getCategory();
Double sales = data.getSales();
categorySales.put(category, categorySales.getOrDefault(category, 0.0) + sales);
}
return categorySales;
}
public static Map<String, Double> aggregateByDate(List<SalesData> dataList) {
Map<String, Double> dateSales = new TreeMap<>();
for (SalesData data : dataList) {
String date = data.getDate();
Double sales = data.getSales();
dateSales.put(date, dateSales.getOrDefault(date, 0.0) + sales);
}
return dateSales;
}
}
使用JFreeChart实现可视化
JFreeChart是一个功能强大的Java图表库,支持多种图表类型的绘制。
饼图:展示各产品类别的销售额占比
public class PieChartDemo {
public static void createPieChart(Map<String, Double> data, String title, String filePath) {
// 创建数据集
DefaultPieDataset dataset = new DefaultPieDataset();
for (Map.Entry<String, Double> entry : data.entrySet()) {
dataset.setValue(entry.getKey(), entry.getValue());
}
// 创建图表
JFreeChart chart = ChartFactory.createPieChart(
title, // 图表标题
dataset, // 数据集
true, // 是否显示图例
true, // 是否显示工具提示
false // 是否支持URL
);
// 设置图表样式
PiePlot plot = (PiePlot) chart.getPlot();
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {1} ({2})"));
// 保存图表
try {
ChartUtils.saveChartAsPNG(new File(filePath), chart, 800, 600);
System.out.println("饼图已保存至:" + filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 假设已经通过EasyExcel读取到数据
List<SalesData> dataList = new ArrayList<>();
// ... 添加数据 ...
Map<String, Double> categorySales = DataProcessor.aggregateByCategory(dataList);
createPieChart(categorySales, "产品类别销售额占比", "pie_chart.png");
}
}
柱状图:比较不同产品类别的销售额
public class BarChartDemo {
public static void createBarChart(Map<String, Double> data, String title, String xLabel, String yLabel, String filePath) {
// 创建数据集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (Map.Entry<String, Double> entry : data.entrySet()) {
dataset.addValue(entry.getValue(), "销售额", entry.getKey());
}
// 创建图表
JFreeChart chart = ChartFactory.createBarChart(
title, // 图表标题
xLabel, // X轴标签
yLabel, // Y轴标签
dataset, // 数据集
PlotOrientation.VERTICAL, // 图表方向
true, // 是否显示图例
true, // 是否显示工具提示
false // 是否支持URL
);
// 设置图表样式
CategoryPlot plot = chart.getCategoryPlot();
plot.getRangeAxis().setNumberFormatOverride(new DecimalFormat("#,##0.00"));
// 保存图表
try {
ChartUtils.saveChartAsPNG(new File(filePath), chart, 800, 600);
System.out.println("柱状图已保存至:" + filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 假设已经通过EasyExcel读取到数据
List<SalesData> dataList = new ArrayList<>();
// ... 添加数据 ...
Map<String, Double> categorySales = DataProcessor.aggregateByCategory(dataList);
createBarChart(categorySales, "产品类别销售额对比", "产品类别", "销售额(元)", "bar_chart.png");
}
}
折线图:展示销售额随时间的变化趋势
public class LineChartDemo {
public static void createLineChart(Map<String, Double> data, String title, String xLabel, String yLabel, String filePath) {
// 创建数据集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (Map.Entry<String, Double> entry : data.entrySet()) {
dataset.addValue(entry.getValue(), "销售额", entry.getKey());
}
// 创建图表
JFreeChart chart = ChartFactory.createLineChart(
title, // 图表标题
xLabel, // X轴标签
yLabel, // Y轴标签
dataset, // 数据集
PlotOrientation.VERTICAL, // 图表方向
true, // 是否显示图例
true, // 是否显示工具提示
false // 是否支持URL
);
// 设置图表样式
CategoryPlot plot = chart.getCategoryPlot();
LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
renderer.setShapesVisible(true); // 显示数据点
plot.getRangeAxis().setNumberFormatOverride(new DecimalFormat("#,##0.00"));
// 保存图表
try {
ChartUtils.saveChartAsPNG(new File(filePath), chart, 800, 600);
System.out.println("折线图已保存至:" + filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 假设已经通过EasyExcel读取到数据
List<SalesData> dataList = new ArrayList<>();
// ... 添加数据 ...
Map<String, Double> dateSales = DataProcessor.aggregateByDate(dataList);
createLineChart(dateSales, "每日销售额趋势", "日期", "销售额(元)", "line_chart.png");
}
}
完整案例:Excel数据可视化展示系统
系统架构
flowchart TD
A[Excel文件] -->|EasyExcel读取| B[数据处理]
B --> C[数据聚合]
C --> D[生成饼图]
C --> E[生成柱状图]
C --> F[生成折线图]
D --> G[可视化报告]
E --> G
F --> G
实现代码
主程序
public class ExcelVisualizationSystem {
public static void main(String[] args) {
String excelFilePath = "sales_data.xlsx";
String outputDir = "visualization_report/";
// 创建输出目录
File dir = new File(outputDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 步骤1:使用EasyExcel读取Excel数据
SalesDataListener listener = new SalesDataListener();
EasyExcel.read(excelFilePath, SalesData.class, listener).sheet().doRead();
List<SalesData> dataList = listener.getDataList();
System.out.println("成功读取Excel数据:" + dataList.size() + "条");
if (dataList.isEmpty()) {
System.out.println("没有读取到数据,程序退出");
return;
}
// 步骤2:数据聚合处理
Map<String, Double> categorySales = DataProcessor.aggregateByCategory(dataList);
Map<String, Double> dateSales = DataProcessor.aggregateByDate(dataList);
// 步骤3:生成可视化图表
PieChartDemo.createPieChart(categorySales, "产品类别销售额占比", outputDir + "pie_chart.png");
BarChartDemo.createBarChart(categorySales, "产品类别销售额对比", "产品类别", "销售额(元)", outputDir + "bar_chart.png");
LineChartDemo.createLineChart(dateSales, "每日销售额趋势", "日期", "销售额(元)", outputDir + "line_chart.png");
// 步骤4:生成可视化报告
generateReport(outputDir);
System.out.println("可视化报告已生成至:" + outputDir);
}
private static void generateReport(String outputDir) {
// 简单生成一个HTML报告
StringBuilder html = new StringBuilder();
html.append("<html><head><title>Excel数据可视化报告</title></head><body>");
html.append("<h1>Excel数据可视化报告</h1>");
html.append("<h2>产品类别销售额占比</h2>");
html.append("<img src='pie_chart.png' width='800' height='600'><br>");
html.append("<h2>产品类别销售额对比</h2>");
html.append("<img src='bar_chart.png' width='800' height='600'><br>");
html.append("<h2>每日销售额趋势</h2>");
html.append("<img src='line_chart.png' width='800' height='600'><br>");
html.append("</body></html>");
try {
FileWriter writer = new FileWriter(outputDir + "report.html");
writer.write(html.toString());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
执行程序后,将在visualization_report目录下生成以下文件:
pie_chart.png:产品类别销售额占比饼图bar_chart.png:产品类别销售额对比柱状图line_chart.png:每日销售额趋势折线图report.html:可视化报告HTML文件
打开report.html文件,可以看到整合了所有图表的可视化报告。
性能优化:处理大数据量Excel文件
内存优化
-
使用分页读取:对于超大Excel文件,采用分页读取的方式,避免一次性加载过多数据到内存。
-
增量处理:读取一部分数据后立即进行处理和可视化,然后释放内存。
public class IncrementalProcessingListener extends AnalysisEventListener<SalesData> {
private static final int BATCH_SIZE = 1000; // 每批处理1000条数据
private List<SalesData> batchData = new ArrayList<>(BATCH_SIZE);
private String outputDir;
public IncrementalProcessingListener(String outputDir) {
this.outputDir = outputDir;
}
@Override
public void invoke(SalesData data, AnalysisContext context) {
batchData.add(data);
if (batchData.size() >= BATCH_SIZE) {
processBatch();
batchData.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (!batchData.isEmpty()) {
processBatch();
}
System.out.println("所有数据处理完成");
}
private void processBatch() {
System.out.println("处理一批数据:" + batchData.size() + "条");
// 增量处理逻辑,例如按时间段生成图表
// ...
}
}
时间优化
-
多线程处理:对于数据量大、处理复杂的场景,可以考虑使用多线程进行数据处理和图表生成。
-
图表缓存:如果需要多次生成相同类型的图表,可以考虑对结果进行缓存。
总结与展望
本文总结
本文详细介绍了如何使用EasyExcel读取Excel数据,并结合JFreeChart实现数据的可视化展示。主要内容包括:
- EasyExcel的基本概念和核心优势
- 使用EasyExcel读取Excel数据的方法,包括基础读取和进阶读取
- 如何将读取到的数据转换为适合可视化的格式
- 使用JFreeChart生成常见的图表,如饼图、柱状图和折线图
- 一个完整的Excel数据可视化展示系统案例
- 处理大数据量Excel文件的性能优化技巧
未来展望
-
交互式可视化:结合Web技术,实现交互式的数据可视化展示,如使用ECharts、D3.js等前端可视化库。
-
自动化报告生成:集成模板引擎,实现可视化报告的自动化生成和导出。
-
实时数据可视化:结合实时数据处理技术,实现Excel数据的实时可视化展示。
-
AI辅助分析:引入人工智能算法,对Excel数据进行深度分析,提供更有价值的可视化结果和决策建议。
通过本文的学习,相信你已经掌握了使用EasyExcel和JFreeChart实现Excel数据可视化的基本方法。希望这些知识能够帮助你在实际工作中更高效地处理和展示Excel数据,提升数据分析和决策的效率。
如果你对本文内容有任何疑问或建议,欢迎在评论区留言讨论。同时,也欢迎点赞、收藏本文,关注作者获取更多数据分析和可视化相关的技术文章。
下期预告:《使用EasyExcel和ECharts实现Web端Excel数据可视化》
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00
GLM-4.7-FlashGLM-4.7-Flash 是一款 30B-A3B MoE 模型。作为 30B 级别中的佼佼者,GLM-4.7-Flash 为追求性能与效率平衡的轻量化部署提供了全新选择。Jinja00
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
compass-metrics-modelMetrics model project for the OSS CompassPython00