【随笔】详解Java POI及其使用方法

news2024/11/13 15:09:47
引言

随着企业和开发者对数据处理需求的不断增加,操作Excel文件已经成为日常编程工作的重要部分。在Java中,Apache POI(Poor Obfuscation Implementation)库虽然首页其貌不扬,但它绝对是处理Excel文件的强大工具。本文将详细介绍Java POI的使用方法,分析其优缺点,并对比其他同类产品。
其貌不扬的POI首页

文章目录

        • 引言
        • 一、Java POI简介
        • 二、Java POI的安装和配置
        • 三、Java POI的基本使用
          • 1. 创建Excel文件
          • 2. 读取Excel文件
          • 3. 更新Excel文件
        • 四、Java POI的优缺点
          • 优点
          • 缺点
        • 五、同类型产品
          • 1. JExcelAPI
          • 2. Aspose.Cells for Java
          • 3. EasyExcel
        • 六、对Java POI的看法
        • 七、二次封装的工具类
        • 八、Java POI的使用示例
          • 1. 创建复杂的Excel文件
        • 九、总结与展望
          • 展望
          • 个人见解

一、Java POI简介

Apache POI是Apache Software Foundation开发的一套开源库,用于操作Microsoft Office文件。POI提供了对Excel文件(HSSF和XSSF)、Word文件(HWPF和XWPF)、PowerPoint文件(HSLF和XSLF)以及Outlook文件(HSMF)的支持。在本文中,我们重点介绍如何使用POI操作Excel文件。

  • HSSF(Horrible Spreadsheet Format):用于操作Excel 97-2003文件(.xls)。
  • XSSF(XML Spreadsheet Format):用于操作Excel 2007及以上版本文件(.xlsx)。
二、Java POI的安装和配置

在开始使用POI之前,我们需要将POI库添加到项目中。以Maven项目为例,添加以下依赖即可:

<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>
<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>5.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.21</version>
</dependency>
三、Java POI的基本使用
1. 创建Excel文件

创建一个新的Excel文件是使用POI的基本功能之一。以下是一个简单的示例,展示如何创建一个包含多个工作表的Excel文件:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;

public class CreateExcelExample {
    public static void main(String[] args) {
        Workbook workbook = new XSSFWorkbook(); // 创建工作簿
        Sheet sheet1 = workbook.createSheet("Sheet1"); // 创建工作表1
        Sheet sheet2 = workbook.createSheet("Sheet2"); // 创建工作表2

        // 在Sheet1中创建行和单元格
        Row row = sheet1.createRow(0); // 创建第一行
        Cell cell = row.createCell(0); // 创建第一个单元格
        cell.setCellValue("Hello, POI!"); // 设置单元格值

        // 写入Excel文件
        try (FileOutputStream fos = new FileOutputStream("example.xlsx")) {
            workbook.write(fos);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 关闭工作簿
        try {
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2. 读取Excel文件

读取Excel文件同样是POI库的基本功能。以下示例展示了如何读取Excel文件中的数据:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;

public class ReadExcelExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.xlsx")) {
            Workbook workbook = new XSSFWorkbook(fis); // 打开工作簿
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表

            // 读取数据
            for (Row row : sheet) {
                for (Cell cell : row) {
                    switch (cell.getCellType()) {
                        case STRING:
                            System.out.print(cell.getStringCellValue() + "\t");
                            break;
                        case NUMERIC:
                            System.out.print(cell.getNumericCellValue() + "\t");
                            break;
                        default:
                            System.out.print("Unknown type" + "\t");
                            break;
                    }
                }
                System.out.println();
            }

            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
3. 更新Excel文件

POI还提供了更新已有Excel文件的功能。以下示例展示了如何在已有的Excel文件中更新数据:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class UpdateExcelExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.xlsx")) {
            Workbook workbook = new XSSFWorkbook(fis); // 打开工作簿
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表

            // 更新数据
            Row row = sheet.getRow(0);
            if (row == null) {
                row = sheet.createRow(0);
            }
            Cell cell = row.getCell(0);
            if (cell == null) {
                cell = row.createCell(0);
            }
            cell.setCellValue("Updated value!");

            // 写入Excel文件
            try (FileOutputStream fos = new FileOutputStream("example.xlsx")) {
                workbook.write(fos);
            }

            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
四、Java POI的优缺点
优点
  1. 功能强大:POI支持对Excel文件的各种操作,包括创建、读取、更新、格式化单元格等。
  2. 跨平台性:作为Java库,POI可以在任何支持Java的平台上运行。
  3. 社区支持:POI是Apache基金会的项目,拥有活跃的开发社区和丰富的文档资源。
  4. 开源免费:POI是开源项目,完全免费使用。
缺点
  1. 性能问题:在处理大文件时,POI可能会遇到性能问题,特别是在内存使用方面。
  2. 复杂性:POI的API相对复杂,对于初学者来说有一定的学习曲线。
  3. 功能限制:虽然POI功能强大,但在处理Excel文件的某些高级特性时可能存在功能限制。
五、同类型产品
1. JExcelAPI

JExcelAPI(JXL)是另一个用于操作Excel文件的Java库。它主要支持Excel 97-2003文件(.xls)。

  • 优点

    • API简单易用,适合初学者。
    • 性能较好,适合处理较小的Excel文件。
  • 缺点

    • 不支持Excel 2007及以上版本文件(.xlsx)。
    • 开发维护不活跃,功能相对POI较少。
2. Aspose.Cells for Java

Aspose.Cells for Java是一个商业的Excel操作库,提供了非常丰富的功能。

  • 优点

    • 功能强大,支持所有Excel文件格式及其高级特性。
    • 性能优化好,适合处理大文件。
    • 提供商业支持和文档。
  • 缺点

    • 费用高昂,不适合预算有限的项目。
    • 商业库,开源社区支持有限。
3. EasyExcel

EasyExcel是阿里巴巴开源的用于操作Excel文件的Java库,专注于高性能和简单易用性。

  • 优点

    • 性能极佳,适合处理大文件。
    • API设计简洁,易于上手。
    • 开源且免费。
  • 缺点

    • 功能相对较少,主要集中在读取和写入简单的Excel文件。
    • 社区和文档支持相对较弱。
六、对Java POI的看法

Java POI是一个功能强大且成熟的Excel操作库,尤其适合处理复杂的Excel操作需求。通过我的使用经验,POI在以下几个方面表现尤为突出:

  1. 功能覆盖全面:无论是简单的读写操作,还是复杂的格式设置和公式计算,POI都能胜任。
  2. 良好的文档和社区支持:官方提供了详细的文档和示例代码,社区也很活跃,这对于解决使用中的问题非常有帮助。
  3. 跨平台性强:作为纯Java实现的库,POI可以在各种操作系统和环境中使用,具备很好的跨平台性。

尽管Java POI有许多优点,但在使用过程中也遇到了一些挑战,尤其是在处理大文件和内存管理方面。此外,POI的学习曲线较为陡峭,初学者可能需要花费更多时间来掌握其复杂的API。

七、二次封装的工具类

为了简化POI的使用,我们可以对其进行二次封装,创建一个工具类,方便日常操作。下面是一个封装了常用操作的工具类示例:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class ExcelUtils {

    // 创建新的Excel文件
    public static void createExcel(String filePath, String sheetName, List<String[]> data) {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(sheetName);

        for (int i = 0; i < data.size(); i++) {
            Row row = sheet.createRow(i);
            String[] rowData = data.get(i);
            for (int j = 0; j < rowData.length; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(rowData[j]);
            }
        }

        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            workbook.write(fos);
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取Excel文件
    public static void readExcel(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            Workbook workbook = new XSSFWorkbook(fis);
            Sheet sheet = workbook.getSheetAt(0);

            for (Row row : sheet) {
                for (Cell cell : row) {
                    switch (cell.getCellType()) {
                        case STRING:
                            System.out.print(cell.getStringCellValue() + "\t");
                            break;
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(cell)) {
                                System.out.print(cell.getDateCellValue() + "\t");
                            } else {
                                System.out.print(cell.getNumericCellValue() + "\t");
                            }
                            break;
                        case FORMULA:
                            System.out.print(cell.getCellFormula() + "\t");
                            break;
                        default:
                            System.out.print("Unknown type" + "\t");
                            break;
                    }
                }
                System.out.println();
            }

            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 更新Excel文件
    public static void updateExcel(String filePath, int sheetIndex, int rowIndex, int cellIndex, String newValue) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            Workbook workbook = new XSSFWorkbook(fis);
            Sheet sheet = workbook.getSheetAt(sheetIndex);

            Row row = sheet.getRow(rowIndex);
            if (row == null) {
                row = sheet.createRow(rowIndex);
            }
            Cell cell = row.getCell(cellIndex);
            if (cell == null) {
                cell = row.createCell(cellIndex);
            }
            cell.setCellValue(newValue);

            try (FileOutputStream fos = new FileOutputStream(filePath)) {
                workbook.write(fos);
            }

            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 添加新行
    public static void addRow(String filePath, int sheetIndex, List<String> rowData) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            Workbook workbook = new XSSFWorkbook(fis);
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            int lastRowNum = sheet.getLastRowNum();
            Row newRow = sheet.createRow(lastRowNum + 1);

            for (int i = 0; i < rowData.size(); i++) {
                Cell cell = newRow.createCell(i);
                cell.setCellValue(rowData.get(i));
            }

            try (FileOutputStream fos = new FileOutputStream(filePath)) {
                workbook.write(fos);
            }

            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

通过上述工具类,我们可以轻松完成创建Excel文件、读取Excel文件、更新Excel文件和添加新行的操作。这种封装大大简化了POI的使用,提高了代码的可读性和维护性。

八、Java POI的使用示例
1. 创建复杂的Excel文件

以下示例展示了如何使用POI创建一个包含多个工作表、不同格式单元格和公式的复杂Excel文件:

import java.util.Arrays;

public class ComplexExcelExample {
    public static void main(String[] args) {
        String filePath = "complex_example.xlsx";
        String sheetName = "Data";
        List<String[]> data = Arrays.asList(
                new String[]{"ID", "Name", "Age", "Salary"},
                new String[]{"1", "John Doe", "30", "4000.50"},
                new String[]{"2", "Jane Smith", "25", "3500.75"},
                new String[]{"3", "Emily Johnson", "40", "4500.00"}
        );

        // 创建Excel文件
        ExcelUtils.createExcel(filePath, sheetName, data);

        // 更新数据
        ExcelUtils.updateExcel(filePath, 0, 4, 3, "SUM(D2:D4)");

        // 添加新行
        ExcelUtils.addRow(filePath, 0, Arrays.asList("4", "Michael Brown", "35", "5000.25"));

        // 读取Excel文件
        ExcelUtils.readExcel(filePath);
    }
}

通过上述示例代码,我们可以看到如何使用封装好的工具类来创建、读取和更新复杂的Excel文件。

九、总结与展望

Java POI作为一个开源的Java库,提供了操作Excel文件的强大功能,广泛应用于各种项目中。在工作中通过对POI的学习和使用,我深刻体会到其在数据处理和报表生成中的价值,但它偶尔会产生性能瓶颈,并且读取数据时需要指定读取什么类型的数据,在实际工作中面对各种需求情况,一般都得另加一个封装类进行二次封装才能更加方便的使用,总体来说在Java中是个很优秀的库了。
PS:在使用POI读取excel时,一定不要打开要读取内容的excel,否则会报错。

展望
  1. 性能优化:希望POI在处理大文件时能进一步优化内存使用和执行效率。
  2. 简化API:虽然POI功能强大,但某些API相对复杂(比如取值),期望能有更加简洁易用的API设计。
  3. 系统化教学和汉化:官方文档和示例虽然已经很丰富,但对于初学者而言,更多系统化的教程和案例分析将更有助于上手,同时POI官方好像没有中文文档(我没找到),学习成本会更高。
个人见解

我认为POI在功能和跨平台性上具有显著优势,是处理Excel文件的首选工具之一。但是在面对大数据处理和复杂报表的不同情况下,开发者还需综合考虑性能优化和学习成本,选择最适合项目需求的工具。

以我的个人使用而言,对于企业级应用,POI与其他商业库(如Aspose.Cells for Java)结合使用,可以充分发挥各自优势,满足不同场景的需求。而在开源项目和预算有限的情况下,POI无疑是一个值得信赖的选择。

最后,作为Java开发者,我们应保持对新技术的关注,不断学习和实践,以应对不断变化的技术需求和挑战。希望这篇随笔对你了解和使用Java POI有所帮助,也欢迎你分享你的使用经验和心得。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1990569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb之servlet关于Ajax实现前后端分离

一、什么是Ajax: AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部…

proteus仿真c51单片机(四)双机串口通信(电路设计及代码)

实验要求 1.通过甲机的按键给乙机发送控制字符&#xff0c;同时也可以实现乙机给甲机发送控制字符 2&#xff0e;用PROTEUS软件根据所给电路画出电路图&#xff0c;用KEIL软件调试程序和编译&#xff0c;最后在PROTEUS软件中实现仿真。 3.甲乙两个单片机通过串口进行通信&am…

Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N]……解决

一、问题 Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.二、解决方案 1、当打包构建的时候出现这个问题&#xff0c;如果你只是打包部署&#xff0c;那么就是将maven的test禁止可以成功打包 2、当你是本地服务器启动…

前端模块化-理解Tapable与Webpack中的Hooks

前言 Webpack 中的核心架构是基于 Tapable 实现的&#xff0c;Tapable 是一个类似于 Node.js 的 EventEmitter 的库&#xff0c;专门用于实现发布-订阅模式。Webpack 中的核心组件 Compiler、Compilation、Module、Chunk、ChunkGroup、Dependency、Template 都是通过 Tapable …

Fiddler安装与使用

下载Fiddler 访问Fiddler官方网站&#xff0c;下载适用于您操作系统的最新版本Fiddler。目前&#xff0c;Fiddler支持Windows、macOS和Linux平台。 Web Debugging Proxy and Troubleshooting Tools|Fiddler (telerik.com) 安装Fiddler&#xff0c;以Windows为例 Windows用户…

gitlab给用户添加项目权限

1.进入管理员界面 2.进入群组 3.添加用户

【RISC-V设计-04】- RISC-V处理器设计K0A之架构

【RISC-V设计-04】- RISC-V处理器设计K0A之架构 文章目录 【RISC-V设计-04】- RISC-V处理器设计K0A之架构1. 简介2. 主要特点3. 结构框图4. 指令列表5. CSR指令集6. 中断返回指令7. 总结 1. 简介 在前几篇文章中&#xff0c;介绍了RISC-V处理器的结构和指令集&#xff0c;从本…

Animate软件基本概念:视频及音频

视频和音频是ANimate软件中比较重要的素材类型。 FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&#xff1a;A…

DSP如何进行竞价

下面根据DSP的系统构成还拆解讲解里面的各个模块&#xff0c;这一节将竞价系统&#xff0c;也就是竞价流程 0、负载均衡 增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。 1、ADX发起竞价请求 上面会携带User ID等用户信息和广告信息一大堆信息。 2、解析竞价…

fastadmin 表单添加默认搜索条件

项目场景&#xff1a;员工列表&#xff0c;查看员工邀约客户明细&#xff0c;在 dialog 窗口中的 table怎么获取当前员工的数据呢&#xff1f;看似简单的需求&#xff0c;实际操作起来还是有点考究的&#xff0c;记录一下实现步骤。 页面1&#xff1a;员工列表 页面2&#xff…

sql_day14(获取各门店的面积)

描述&#xff1a;获取各门店的面积 获取各门店的面积 门店面积信息可以从分店面积明细表中获取。 先取实际经营面积(8)&#xff0c; 如果取不到&#xff08;实际经营面积为空&#xff09;再取经营面积(7)。 如果取不到&#xff08;经营面积为空&#xff09;再取合同面积(1)。…

AI大模型赋能开发者|海云安创始人谢朝海受邀在ISC.AI 2024大会就“大模型在软件开发安全领域的应用”主题发表演讲

近日&#xff0c;ISC.AI 2024 第十二届互联网安全大会在北京国家会议中心盛大开幕。作为全球规格最高、规模最大、影响力最深远的安全峰会之一&#xff0c;本次大会以“打造安全大模型 引领安全行业革命”为主题&#xff0c;聚焦安全与AI两大领域&#xff0c;吸引了众多行业领袖…

您知道Jmeter中Redirect Automatically 和 Follow Redirects的使用场景吗?

相信很多使用过jmeter的同学都没有关注过请求中的Redirect Automatically 和 Follow Redirects选项&#xff0c;如下图&#xff1a; 在 JMeter 中&#xff0c;Redirect Automatically 和 Follow Redirects 是与 HTTP 请求重定向相关的两个选项&#xff0c;它们之间是有很大区别…

Ubuntu小键盘消失,并且安装好搜狗输入法后无法打出中文的问题

Ubuntu右上角的键盘图标不见了_ubuntu虚拟机键盘选项消失了-CSDN博客解决Ubuntu18.04安装好搜狗输入法后无法打出中文的问题_ubuntu18.04 搜狗输入法无法输入中文-CSDN博客 sudo apt install libqt5qml5 libqt5quick5 libqt5quickwidgets5 qml-module-qtquick2sudo apt instal…

小智常见报表-自由报表

概述 自由报表&#xff1a;具有自由设计、修改、完善的能力的报表。 应用场景 如下图所示&#xff0c;简单展示数据 示例说明 数据准备 在数据面板中添加数据集&#xff0c;可选择Json数据集和API服务数据集。Json数据集输入如下图所示&#xff1a; [{"姓名"…

Keytool:Uniapp 云打包需要生成证书的操作笔记

文章目录 背景操作步骤概述安装 Java 并检测版本生成证书 xxx.keystore问题&#xff1a;报错&#xff0c;没有权限使用证书 背景 我用 uniapp 想要用云打包&#xff0c;但是需要本机生成一个证书 操作步骤概述 安装 Java在终端输入 /usr/libexec/java_home -V 之后&#xff…

2024华为数通HCIP-datacom最新题库(H12-831变题更新⑨)

请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 请注意&#xff0c;华为HCIP-Datacom考试831已变题 近期打算考HCIP的朋友注意了&#xff0c;如果你准备去考试&#xff0c;还是用的之前的题库&#xff0c;切记暂缓。 如…

【Python学习笔记】序列化

【Python学习笔记】序列化 文章目录 【Python学习笔记】序列化1.python使用pickle序列化数据1.1. 环境准备1.2. 序列化datetime对象1.3. 序列化DataFrame对象1.3.1 json1.3.2 pickle 1.4 序列化list列表 2. flaskweb接口传输序列化数据2.1. bytes形式传输2.1.1. datetime对象2.…

k8s使用kustomize来部署应用

k8s使用kustomize来部署应用 本文主要是讲述kustomzie的基本用法。首先&#xff0c;我们说一下部署文件的目录结构。 ./ ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml └── overlays└── dev├── kustomization.…

SpringBoot 集成 Sharding-JDBC 实现读写分离、分库分表

文章目录 一、Sharding-JDBC的应用场景二、SpringBoot 集成 Sharding-JDBC2.1、前期准备2.2、导入pom.xml依赖包2.3、结构代码实现2.3.1、MybatisPlusConfig&#xff08;分页插件&#xff09;2.3.2、TOrder&#xff08;订单对象&#xff09;2.3.3、TOrderMapper&#xff08;订单…