0


Java 解析 /生成 Excel文件

一.概述

    在程序的开发过程中,通常会使用Excel文件来进行数据的导入和导出,在使用Java实现此类需求时也要经理Excel文件的解析或生成

    在Java技术中,能实现此类需求的技术主要有:Apache POI, Alibaba EasyExcel 和 JXL。

其中,JXL只支持Excel2003以下版本,所以现在不太常见,那简单学习一下另外两种技术吧

二.Apache POI

    Apache POI是基于DOM方式进行解析,将文件直接加载内存,速度较快,适合文件数据量不大的应用场景,它提供Java编写的免费开源跨平台的Java API,Apache POI提供给Java程序对Microsoft Office格式档案进行读写功能的API开源类库。

它分别对不同格式的文件提供不同的文件解析:

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

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

    HWPF-提供读写Microsoft Word格式档案的功能。

    HSLF-提供读写Microsoft PowerPoint格式档案的功能。

    HDGF-提供读写Microsoft Visio格式档案的功能。

最常用的是HSSF和XSSF,其中HSSF主要用于解析.xls格式的Excel文件,而XSSF主要用于解析.xlsx格式的Excel文件。前一种格式的Excel文件所能存储的数据较小。我们重点要了解的是XSSF解析和生成文件的方法

1.XSSF解析文件

首先我们要知道每个对象所代表的是什么:

    1. Workbook对象:Excel文件
     2. Sheet对象:电子工作簿
     3. Row对象:数据行
     4. Cell对象:单元格

 1.   我们首先要创建一个输入流,用于传入所要解析的Excel文件,还要创建一个Workbook对象,用于解析所传入的文件:(传入的地址是所需要解析的Excel文件地址)(ps:输入流用完是需要关闭的,参考下文生成excel方法)

  1. 使用getNumberOfSheets()方法获取工作部的数量:

  1. 根据传入的下标或工作簿的名称获取工作簿:

以上实现代码如下:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //通过输入流传入excel文件
        FileInputStream in = new FileInputStream("C:\\text Java\\1627356552686.xlsx");
        
        //将输入流传入Workbook对象并完成解析
        Workbook workbook = new XSSFWorkbook(in);

        //获取工作簿数量
        int sheetNumber = workbook.getNumberOfSheets();
        System.out.println("工作簿数量:" + sheetNumber);

        //按照名称或下标获取工作簿
        Sheet sheet0 = workbook.getSheet("sheet0");
        Sheet sheet1 = workbook.getSheetAt(1);
        System.out.println("工作簿1:" + sheet0.getLastRowNum());
        System.out.println("工作簿2:" + sheet1.getLastRowNum());
    }
}

4.此外我们还需要获取单元格信息,或许其信息的方式有两种,一种是使用遍历下标的方法遍历所有行,来获取单元格信息

另外一种是使用foreach遍历,能使用这种方法,是因为在Sheet接口中实现了iterator迭代器

实现代码如下:

import java.io.FileInputStream;
import java.io.IOException;

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;

public class Demo02 {
    public static void main(String[] args) {
        try (Workbook workbook = new XSSFWorkbook(new FileInputStream("C:\\text Java\\1627356552686.xlsx"))) {
            // 获取工作簿对象
            Sheet sheet = workbook.getSheetAt(0);

            // 遍历工作簿中的所有行
            // 方法一:
            for (int i = 0; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);

                // 按照下标获取单元格
                Cell cell0 = row.getCell(0);
                Cell cell1 = row.getCell(1);
                Cell cell2 = row.getCell(2);
                Cell cell3 = row.getCell(3);
                Cell cell4 = row.getCell(4);

                System.out.println("序号:" + cell0.getNumericCellValue());
                System.out.println("部门:" + cell1.getStringCellValue());
                System.out.println("姓名:" + cell2.getStringCellValue());
                System.out.println("职位:" + cell3.getStringCellValue());
                System.out.println("身份证号:" + cell4.getStringCellValue());
                System.out.println();

            }

            // 方法二:(sheet接口中实现了iterater迭代器)
            for (Row row : sheet) {
                Cell cell0 = row.getCell(0);
                Cell cell1 = row.getCell(1);
                Cell cell2 = row.getCell(2);
                Cell cell3 = row.getCell(3);
                Cell cell4 = row.getCell(4);

                System.out.println("序号:" + cell0.getNumericCellValue());
                System.out.println("部门:" + cell1.getStringCellValue());
                System.out.println("姓名:" + cell2.getStringCellValue());
                System.out.println("职位:" + cell3.getStringCellValue());
                System.out.println("身份证号:" + cell4.getStringCellValue());
                System.out.println();
            }

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

2.XSSF生成文件

既有解析文件,那也就有生成文件,下面说说生成文件的方法

1.创建输出流用于导出所要生成的Excel文件,同时也要创建Workbook对象用于写入文件

2.创建工作簿:

3.创建行

4.创建单元格,即填充内容

5.别忘了调用write方法进行写入:

实现代码如下:

import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;

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;

public class Demo03 {
    public static void main(String[] args) {
        try (Workbook workbook = new XSSFWorkbook();
                FileOutputStream file = new FileOutputStream("C:\\text Java\\test.xlsx")) {
            
            //创建sheet工作簿
            Sheet sheet0 = workbook.createSheet("表1"); 
            Sheet sheet1 = workbook.createSheet("表2"); 
            Sheet sheet2 = workbook.createSheet("表3"); 
            
            //创建row行
            Row row0 = sheet0.createRow(0);
            
            //创建cell单元格并写进内容
            Cell cell0 = row0.createCell(0);
            cell0.setCellValue(UUID.randomUUID().toString());
            Cell cell1 = row0.createCell(1); 
            cell1.setCellValue(Math.random() * 10);
            Cell cell2 = row0.createCell(2); 
            cell2.setCellValue(LocalDateTime.now());

            //写入
            workbook.write(file);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
}

以上是关于Apache POI中XSSF解析和生成文件的方法,下来说说Alibaba EasyExcel

三.Alibaba EasyExcel

    采用逐行读取的解析模式,将每一行解析结果以观察者的模式通知处理,所以比较适合数据体量较大的Excel文件解析,用这种方法生成Excel文件时需要有对应的实现类辅助完成:

1.主函数和返回值为list<>的方法:(doWrtie()方法中需要传入的参数类型为list<>)

    在这里,我们实现了100w条数据的写入,也测试了写入数据所需要的时间,运行结果如下所示
import java.util.ArrayList;
import java.util.List;

import com.alibaba.excel.EasyExcel;

public class Demo01 {
    public static void main(String[] args) {
        
        long begin = System.currentTimeMillis(); //获取当前时间(毫秒)
        
        // 写入100w
        EasyExcel.write("C:\\text Java\\easyexcelTest\\easy.xlsx", Order.class)
                 .sheet("订单列表") //创建工作簿并设置工作簿名称
                 .doWrite(data());
        long end = System.currentTimeMillis();
        System.out.println("用时" + (end-begin) + "毫秒"); //计算时间差
    }
    
    // 创建100w条订单数据
    private static List<Order> data() {
        List<Order> list = new ArrayList<Order>();
        for (int i = 0; i < 1000000; i++) {
            list.add(new Order());
        }
        return list;
    }
}

写入数据所需要的时间与电脑本身的性能也有关系。

2.Order订单实现类:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat;

public class Order {
    @ExcelProperty("订单编号")
    private String orderId; // 订单编号
    
    @ExcelProperty("支付金额")
    @NumberFormat("¥#,###")
    private Double payment; // 支付金额
    
    @ExcelProperty(value = "创建日期",converter = LocalDateTimeConverter.class)
    private LocalDateTime creationTime; // 创建时间

    public Order() {
        this.orderId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddhhmmss"))
                + UUID.randomUUID().toString().substring(0, 5);
        this.payment = Math.random() * 10000;
        this.creationTime = LocalDateTime.now();
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public Double getPayment() {
        return payment;
    }

    public void setPayment(Double payment) {
        this.payment = payment;
    }

    public LocalDateTime getCreationTime() {
        return creationTime;
    }

    public void setCreationTime(LocalDateTime creationTime) {
        this.creationTime = creationTime;
    }

    @Override
    public String toString() {
        return "Order [orderId=" + orderId + ", payment=" + payment + ", creationTime=" + creationTime + "]";
    }
}

四.SXSSF写入文件

SXSSF也是POI写入文件的方法,只不过更适用于超大文件的写入,在这种方法中通过设置SXSSFWorkbook()对象的参数可以防止出现内存不够用的情况

1.下面是写入1万条数据的实现代码及所需时间

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
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.streaming.SXSSFWorkbook;

public class Demo03 {
    public static void main(String[] args) {
        
        long begin = System.currentTimeMillis(); //获取当前时间(毫秒)
        
        //超大excel文件写入使用SXSSFWorkbook对象
        try (Workbook workbook = new SXSSFWorkbook();
                FileOutputStream out = new FileOutputStream("C:\\text Java\\Test-10W.xlsx")) {

            // 创建新的工作簿
            Sheet sheet = workbook.createSheet();

            // 获取格式编码值
            DataFormat format = workbook.createDataFormat();
            short dateFormat = format.getFormat("yyyy年MM月dd日 HH:mm:ss");
            short monyFormat = format.getFormat("¥#,###");

            // 创建日期格式对象
            CellStyle dateCellType = workbook.createCellStyle();
            dateCellType.setDataFormat(dateFormat);

            // 创建红包格式对象
            CellStyle moneyCellType = workbook.createCellStyle();
            moneyCellType.setDataFormat(monyFormat);

            for (int i = 0; i < 10000; i++) {

                String name = "a" + i;
                Row row = sheet.createRow(i + 1);

                Cell cell0 = row.createCell(0); // 序号
                cell0.setCellValue(String.valueOf(i + 1));

                Cell cell1 = row.createCell(1); // 姓名
                cell1.setCellValue(name);

                Cell cell2 = row.createCell(2); // 日期
                cell2.setCellStyle(dateCellType);
                cell2.setCellValue(new Date());

                Cell cell3 = row.createCell(3); // 红包
                cell3.setCellStyle(moneyCellType);
                cell3.setCellValue((int) (Math.random() * 10000));

            }
            workbook.write(out);
            
            long end = System.currentTimeMillis();
            System.out.println("耗时" + (end-begin) + "毫秒"); //计算时间差
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

相比起来SXSSF和EasyExcel虽然都是用于对大数据量文件的写入,但是EasyExcel更适用于此类情况

标签: eclipse java

本文转载自: https://blog.csdn.net/wan25110712/article/details/125831186
版权归原作者 x.y.r 所有, 如有侵权,请联系我们删除。

“Java 解析 /生成 Excel文件”的评论:

还没有评论