首页
/ EasyExcel实现Excel数据的可视化展示

EasyExcel实现Excel数据的可视化展示

2026-02-04 04:05:52作者:温玫谨Lighthearted

引言:从Excel到可视化的困境与解决方案

你是否还在为Excel数据的可视化展示而烦恼?当面对海量Excel数据时,手动整理、导入数据库再进行可视化的过程是否让你感到效率低下?本文将详细介绍如何利用阿里巴巴开源的EasyExcel工具,结合Java可视化库,实现Excel数据的高效读取与多样化可视化展示,帮助你轻松解决这一痛点。

读完本文,你将能够:

  • 了解EasyExcel的核心优势及其在数据处理中的应用
  • 掌握使用EasyExcel读取不同格式Excel文件的方法
  • 学会将Excel数据转换为适合可视化的格式
  • 实现多种常见图表的绘制,如折线图、柱状图、饼图等
  • 了解高级可视化技巧,如动态刷新和交互式图表

EasyExcel简介:高效处理Excel的利器

EasyExcel的核心优势

EasyExcel是阿里巴巴开源的一款Java处理Excel工具,它具有以下核心优势:

  1. 内存占用低:采用逐行读取的方式,避免将整个文件加载到内存中,解决了传统Excel处理工具在处理大文件时容易出现内存溢出的问题。

  2. 操作简便:提供简洁的API,通过少量代码即可实现Excel文件的读写操作。

  3. 功能强大:支持Excel文件的读写、格式转换、数据验证等多种功能。

  4. 扩展性好:支持自定义转换器、监听器等,可根据需求进行功能扩展。

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文件

内存优化

  1. 使用分页读取:对于超大Excel文件,采用分页读取的方式,避免一次性加载过多数据到内存。

  2. 增量处理:读取一部分数据后立即进行处理和可视化,然后释放内存。

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() + "条");
        // 增量处理逻辑,例如按时间段生成图表
        // ...
    }
}

时间优化

  1. 多线程处理:对于数据量大、处理复杂的场景,可以考虑使用多线程进行数据处理和图表生成。

  2. 图表缓存:如果需要多次生成相同类型的图表,可以考虑对结果进行缓存。

总结与展望

本文总结

本文详细介绍了如何使用EasyExcel读取Excel数据,并结合JFreeChart实现数据的可视化展示。主要内容包括:

  1. EasyExcel的基本概念和核心优势
  2. 使用EasyExcel读取Excel数据的方法,包括基础读取和进阶读取
  3. 如何将读取到的数据转换为适合可视化的格式
  4. 使用JFreeChart生成常见的图表,如饼图、柱状图和折线图
  5. 一个完整的Excel数据可视化展示系统案例
  6. 处理大数据量Excel文件的性能优化技巧

未来展望

  1. 交互式可视化:结合Web技术,实现交互式的数据可视化展示,如使用ECharts、D3.js等前端可视化库。

  2. 自动化报告生成:集成模板引擎,实现可视化报告的自动化生成和导出。

  3. 实时数据可视化:结合实时数据处理技术,实现Excel数据的实时可视化展示。

  4. AI辅助分析:引入人工智能算法,对Excel数据进行深度分析,提供更有价值的可视化结果和决策建议。

通过本文的学习,相信你已经掌握了使用EasyExcel和JFreeChart实现Excel数据可视化的基本方法。希望这些知识能够帮助你在实际工作中更高效地处理和展示Excel数据,提升数据分析和决策的效率。

如果你对本文内容有任何疑问或建议,欢迎在评论区留言讨论。同时,也欢迎点赞、收藏本文,关注作者获取更多数据分析和可视化相关的技术文章。

下期预告:《使用EasyExcel和ECharts实现Web端Excel数据可视化》

登录后查看全文
热门项目推荐
相关项目推荐