使用Apache POI操作EXCEL03版本及EXCEL07以上版本表格

Apache POI 是什么

Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。
Apache POI 解析链接:Apache POI .

使用

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>excel</artifactId>
        <groupId>com.jsxl</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>excel_poi</artifactId>

    <dependencies>
        <!--xls(03)-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>

        <!--xlsx(07)-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>

        <!--日期格式化工具-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.1</version>
        </dependency>

        <!--test-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

excel表格解析
在这里插入图片描述
Workbook接口的几个实现类以及xls和区别
在这里插入图片描述
HSSF 可操作EXCEL03版本
SXSSF和XSSF可操作EXCEL07以上版本

POI-Excel写操作

package com.jsxl.excel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelWrite {

    private String PATH="D:\\github\\excel\\excel_poi";

    @Test
    public void write03() throws IOException {
        // 1、创建工作薄
        Workbook workbook = new HSSFWorkbook();
        //2、创建工作表
        Sheet sheet = workbook.createSheet("test1");

        //3、创建行(0:第一行)
        Row row1 = sheet.createRow(0);
        //4、创建单元格(0:第一行的第一个格子)
        Cell cell00 = row1.createCell(0);
        cell00.setCellValue("测试数据");
        //第一行的第二个格子
        Cell cell01 = row1.createCell(1);
        cell01.setCellValue("testData");

        //第二行
        Row row2 = sheet.createRow(1);
        //第二行的第一个格子
        Cell cell10 = row2.createCell(0);
        cell10.setCellValue("时间");
        //第二行的第二个格子
        Cell cell11 = row2.createCell(1);
        cell11.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));

        //生成Excel(IO流)
        //03版本的Excel是使用 .xls 结尾!!!
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "POI03测试.xls");

        workbook.write(fileOutputStream);

        //关闭流
        fileOutputStream.close();

        System.out.println("03Excel输出完毕");
    }

    @Test
    public void write07() throws IOException {
        // 1、创建工作薄
        Workbook workbook = new XSSFWorkbook();
        //2、创建工作表
        Sheet sheet = workbook.createSheet("test1");

        //3、创建行(0:第一行)
        Row row1 = sheet.createRow(0);
        //4、创建单元格(0:第一行的第一个格子)
        Cell cell00 = row1.createCell(0);
        cell00.setCellValue("测试数据");
        //第一行的第二个格子
        Cell cell01 = row1.createCell(1);
        cell01.setCellValue("testData");

        //第二行
        Row row2 = sheet.createRow(1);
        //第二行的第一个格子
        Cell cell10 = row2.createCell(0);
        cell10.setCellValue("时间");
        //第二行的第二个格子
        Cell cell11 = row2.createCell(1);
        cell11.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));

        //生成Excel(IO流)
        //03版本的Excel是使用 .xlsx 结尾!!!
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "POI07测试.xlsx");

        workbook.write(fileOutputStream);

        //关闭流
        fileOutputStream.close();

        System.out.println("07Excel输出完毕");
    }
}

效率比较

HSSF- 提供读写Microsoft Excel XLS格式档案的功能。

  • 缺点:最多只能处理 65536 行,否则会抛出异常
  • 优点:过程中写入缓存,不操作磁盘,最后一次性写入磁盘,速度快
    @Test
    public void write03BigData() throws IOException {
        long begin = System.currentTimeMillis();
        //创建簿
        Workbook workbook = new HSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写数据
        for (int rowNum = 0; rowNum < 65536; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        System.out.println("over");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "TestWrite03BigData.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();

        long end = System.currentTimeMillis();

        System.out.println((double) (end-begin)/1000);

耗时

XSSF- 提供读写Microsoft Excel OOXML XLSX格式档案的功能。

  • 缺点:写数据时速度非常慢,非常耗内存,可能发生内存溢出OOM
  • 优点:可以写较大的数据量
 @Test
    public void write07BigData() throws IOException {
        long begin = System.currentTimeMillis();
        //创建簿
        Workbook workbook = new XSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写数据
        for (int rowNum = 0; rowNum < 100000; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        System.out.println("over");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "TestWrite07BigData.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();

        long end = System.currentTimeMillis();

        System.out.println((double) (end-begin)/1000);
    }

在这里插入图片描述
SXSSF - 也是对Microsoft Excel OOXML XLSX操作,速度更快但是会产出临时文件
SXSSF - 通过一个滑动窗口来限制访问Row的数量从而达到低内存占用的目录,XSSF可以访问所有行。旧的行数据不再出现在滑动窗口中并变得无法访问,与此同时写到磁盘上。
在自动刷新的模式下,可以指定窗口中访问Row的数量,从而在内存中保持一定数量的Row。当达到这一数量时,在窗口中产生新的Row数据,并将低索引的数据从窗口中移动到磁盘中。
或者,滑动窗口的行数可以设定成自动增长的。它可以根据需要周期的根据一次明确的flushRow(int keepRows)调用来进行修改。

@Test
public void write07BigDataS() throws IOException {
    long begin = System.currentTimeMillis();
 
    //创建簿
    Workbook workbook = new SXSSFWorkbook();
    //创建表
    Sheet sheet = workbook.createSheet();
    //写数据
    for (int rowNum = 0; rowNum < 100000; rowNum++) {
        Row row = sheet.createRow(rowNum);
        for (int cellNum = 0; cellNum < 10; cellNum++) {
            Cell cell = row.createCell(cellNum);
            cell.setCellValue(cellNum);
        }
    }
    System.out.println("over");
    FileOutputStream fileOutputStream = new FileOutputStream(PATH + "TestWrite07BigDataS.xlsx");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    //清除临时文件
    ((SXSSFWorkbook) workbook).dispose();
 
    long end = System.currentTimeMillis();
    System.out.println((double) (end-begin)/1000);
}

在这里插入图片描述
SXSSFWorkbook 官方解释:实现“BigGridDemo”策略的流式XSSFWorkbook版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。
请注意,仍然可能会消耗大量内存,这些内存基于正在使用的功能,例如合并区域,注释…仍然只存储在内存中,因此如果广泛使用,可能需要大量内存。

POI-Excel读操作

读操作时需要注意数据的类型,源码类型有如下几种

public interface Cell {

    /**
     * Numeric Cell type (0)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_NUMERIC = 0;

    /**
     * String Cell type (1)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_STRING = 1;

    /**
     * Formula Cell type (2)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_FORMULA = 2;

    /**
     * Blank Cell type (3)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_BLANK = 3;

    /**
     * Boolean Cell type (4)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_BOOLEAN = 4;

    /**
     * Error Cell type (5)
     * @see #setCellType(int)
     * @see #getCellType()
     */
    public final static int CELL_TYPE_ERROR = 5;
}

HSSF

    @Test
    public void testRead03() throws IOException {
        //获取文件流
        FileInputStream fileInputStream = new FileInputStream(PATH + "POI03测试.xls");

        //1、获取工作簿
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        //2、得到表
        Sheet sheet = workbook.getSheetAt(0);
        //3、得到行
        Row row = sheet.getRow(0);
        //4、得到列
        Cell cell = row.getCell(0);

        //读取值时一定要注意类型
        System.out.println(cell.getStringCellValue());

        fileInputStream.close();
    }

XSSF

@Test
public void testRead07() throws IOException {
    //获取文件流
    FileInputStream fileInputStream = new FileInputStream(PATH + "POI07测试.xlsx");
 
    //1、获取工作簿
    Workbook workbook = new XSSFWorkbook(fileInputStream);
    //2、得到表
    Sheet sheet = workbook.getSheetAt(0);
    //3、得到行
    Row row = sheet.getRow(0);
    //4、得到列
    Cell cell = row.getCell(0);
 
    //读取值时一定要注意类型
    System.out.println(cell.getStringCellValue());
 
    fileInputStream.close();
}

读取不同的数据类型

在这里插入图片描述

@Test
public void testCellType() throws Exception {
    //获取文件
    FileInputStream fileInputStream = new FileInputStream(PATH + "会员消费商品明细表.xls");
 
    //获取工作薄
    Workbook workbook = new HSSFWorkbook(fileInputStream);
    //得到表
    Sheet sheet = workbook.getSheetAt(0);
 
    //获取标题内容
    Row rowTitle = sheet.getRow(0);
    if (rowTitle != null){
        //获取一行中有多少个单元格
        int cellCount = rowTitle.getPhysicalNumberOfCells();
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            //获取单元
            Cell cell = rowTitle.getCell(cellNum);
            if (cell != null){
                //获取类型
                int cellType = cell.getCellType();
                String cellValue = cell.getStringCellValue();
                System.out.print(cellValue + " | ");
            }
        }
        System.out.println();
    }
 
    //获取表中的内容
    int rowCount = sheet.getPhysicalNumberOfRows();
    for (int rowNum = 1; rowNum < rowCount; rowNum++) {
        Row rowData = sheet.getRow(rowNum);
        if (rowData != null){
            //读取列
            int cellCout = rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellCout; cellNum++) {
                System.out.print("【" + (rowNum+1) + "-" + (cellNum+1) + "】");
 
                Cell cell = rowData.getCell(cellNum);
                //匹配列的数据类型
                if (cell != null){
                    int cellType = cell.getCellType();
                    String cellValue = "";
 
                    switch (cellType){
                        case HSSFCell.CELL_TYPE_STRING://字符串
                            System.out.print("【STRING】");
                            cellValue = cell.getStringCellValue();
                            break;
                        case HSSFCell.CELL_TYPE_BOOLEAN://布尔值
                            System.out.print("【BOOLEAN】");
                            cellValue = String.valueOf(cell.getBooleanCellValue());
                            break;
                        case HSSFCell.CELL_TYPE_NUMERIC://数字类型
                            System.out.print("【NUMERIC】");
 
                            if (HSSFDateUtil.isCellDateFormatted(cell)){//日期
                                System.out.print("【日期】");
                                Date date = cell.getDateCellValue();
                                cellValue = new DateTime().toString("yyyy-MM-dd");
                            }else{
                                // 不是日期格式,则防止当数字过长时以科学计数法显示
                                System.out.print("【转换成字符串】");
                                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                cellValue = cell.toString();
                            }
                            break;
                        case HSSFCell.CELL_TYPE_BLANK://System.out.print("【BLANK】");
                            break;
                        case Cell.CELL_TYPE_ERROR:
                            System.out.print("【数据类型错误】");
                            break;
                    }
                    System.out.println(cellValue);
                }
            }
        }
    }
    fileInputStream.close();
}

在这里插入图片描述
计算公式

    @Test
    public void testFormula() throws Exception {
        FileInputStream fileInputStream = new FileInputStream(PATH + "数据类型测试表.xls");
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        Sheet sheetAt = workbook.getSheetAt(0);

        //获取计算公式所在的行
        Row row = sheetAt.getRow(1);
        //计算公式的第几个单元格
        Cell cell = row.getCell(5);

        //拿到计算公式
        FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);

        //输出单元格内容
        int cellType = cell.getCellType();
        switch (cellType){
            case Cell.CELL_TYPE_FORMULA://公式
                //获取单元格的计算公式
                String formula = cell.getCellFormula();
                System.out.println(formula);

                //计算
                CellValue evaluate = formulaEvaluator.evaluate(cell);
                String cellValue = evaluate.formatAsString();
                System.out.println(cellValue);
                break;
        }
    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Apache POI 是一个用于读写 Microsoft Office 格式文件(如 Excel、Word、PowerPoint 等)的 Java 库。下面是使用 Apache POI 读取 Excel 表格数据的步骤: 1. 添加 Apache POI 依赖包。 在项目的 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 2. 创建 Workbook 对象。 使用 FileInputStream 类加载 Excel 文件,然后创建 Workbook 对象。Workbook 对象可以是 HSSFWorkbook(处理 .xls 格式)或 XSSFWorkbook(处理 .xlsx 格式)。 ```java FileInputStream file = new FileInputStream(new File("path/to/excel/file.xlsx")); XSSFWorkbook workbook = new XSSFWorkbook(file); ``` 3. 获取 Sheet 对象。 Sheet 对象代表一个 Excel 表格,可以通过 Workbook 对象的 getSheet() 方法获取。也可以通过 Sheet 对象的名字获取,如 getSheet("Sheet1")。 ```java Sheet sheet = workbook.getSheetAt(0); // 获取第一个表格 ``` 4. 遍历行和单元格。 遍历行和单元格,读取数据。 ```java Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); Iterator<Cell> cellIterator = row.iterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); switch (cell.getCellType()) { case STRING: System.out.print(cell.getStringCellValue() + "\t"); break; case NUMERIC: System.out.print(cell.getNumericCellValue() + "\t"); break; case BOOLEAN: System.out.print(cell.getBooleanCellValue() + "\t"); break; default: } } System.out.println(); } ``` 完整代码示例: ```java import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ReadExcel { public static void main(String[] args) throws IOException { FileInputStream file = new FileInputStream(new File("path/to/excel/file.xlsx")); XSSFWorkbook workbook = new XSSFWorkbook(file); Sheet sheet = workbook.getSheetAt(0); Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); Iterator<Cell> cellIterator = row.iterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); switch (cell.getCellType()) { case STRING: System.out.print(cell.getStringCellValue() + "\t"); break; case NUMERIC: System.out.print(cell.getNumericCellValue() + "\t"); break; case BOOLEAN: System.out.print(cell.getBooleanCellValue() + "\t"); break; default: } } System.out.println(); } workbook.close(); file.close(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jsxllht

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值