使用Java操作excel的几种方法

2023-11-10

在平时的业务系统开发中,少不了需要用到导出、导入excel功能,今天我们就一起来总结一下!

下面给大家介绍一下几种常用方法:



一、Apache poi

大概在很久很久以前,微软的电子表格软件 Excel 以操作简单、存储数据直观方便,还支持打印报表,在诞生之初,可谓深得办公室里的白领青睐,极大的提升了工作的效率,不久之后,便成了办公室里的必备工具。

随着更多的新语言的崛起,例如我们所熟悉的 java,后来便有一些团队开始开发一套能与 Excel 软件无缝切换的操作工具!

当然,在java生态体系里面,能与Excel无缝衔接的第三方工具还有很多,在开始也给大家列出来三个,因为 apache poi 在业界使用的最广泛,因此其他的工具不做过多介绍!

话不多说,直接开撸!

1.1 首先添加依赖

<dependencies>
    <!--xls(03)-->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>4.1.2</version>
    </dependency>
    <!--xlsx(07)-->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>4.1.2</version>
    </dependency>
    <!--时间格式化工具-->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.10.6</version>
    </dependency>
</dependencies>

1.2 导出excel

导出操作,即使用 Java 写出数据到 Excel 中,常见场景是将页面上的数据导出,这些数据可能是财务数据,也可能是商品数据,生成 Excel 后返回给用户下载文件。

在 poi 工具库中,导出 api 可以分三种方式

HSSF方式: 这种方式导出的文件格式为office 2003专用格式,即.xls,优点是导出数据速度快,但是 最多65536行 数据
XSSF方式: 这种方式导出的文件格式为office 2007专用格式,即.xlsx,优点是导出的数据不受行数限制,缺点导出速度慢
SXSSF方式: SXSSF 是 XSSF API的兼容流式扩展,主要解决当使用 XSSF 方式导出大数据量时,内存溢出的问题,支持导出大批量的excel数据

1.2.1 HSSF方式导出(.xls方式)

HSSF方式,最多只支持65536条数据导出,超过这个条数会报错!

package cn.tedu.excel.test;

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 java.io.FileOutputStream;

/**
 * HSSF方式导出:HSSF方式,最多只支持65536条数据导出,超过这个条数会报错!
 * 就是.xls模式
 */
public class ExcelWrite2003Test {
    private static  String PATH = "/Users/lixin/Desktop/";//自己输出的路径

    public static void main(String[] args) throws Exception {
        //时间
        long begin = System.currentTimeMillis();

        //创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNumber = 0; rowNumber < 65536; rowNumber++) {
            //创建行
            Row row = sheet.createRow(rowNumber);
            for (int cellNumber = 0; cellNumber < 10; cellNumber++) {
                //创建列
                Cell cell = row.createCell(cellNumber);
                cell.setCellValue(cellNumber);
            }
        }
        System.out.println("结束!");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "用户信息表-XLS.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        long end = System.currentTimeMillis();
        System.out.println("时间为:"+(double) (end - begin) / 1000);//2.262s
    }
}

1.2.2 XSSF方式导出(.xlsx)

XSSF方式支持大批量数据导出,所有的数据先写入内存再导出,容易出现内存溢出!

package cn.tedu.excel.test;

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 java.io.FileOutputStream;

/**
 * .xlsx方式
 */
public class ExcelWrite2007Test {
    public static String PATH = "/Users/lixin/Desktop/";

    public static void main(String[] args) throws Exception {
        //时间
        long begin = System.currentTimeMillis();

        //创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNumber = 0; rowNumber < 65537; rowNumber++) {
            Row row = sheet.createRow(rowNumber);
            for (int cellNumber = 0; cellNumber < 10; cellNumber++) {
                Cell cell = row.createCell(cellNumber);
                cell.setCellValue(cellNumber);
            }
        }
        System.out.println("结束");

        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "用户信息表-XLSX.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        long end = System.currentTimeMillis();
        System.out.println((double) (end - begin) / 1000);//5.003s
    }
}

1.2.3、SXSSF方式导出

SXSSF方式是XSSF方式的一种延伸,主要特性是低内存,导出的时候,先将数据写入磁盘再导出,避免报内存不足,导致程序运行异常,缺点是运行很慢!

package cn.tedu.excel.test;

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.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;

public class ExcelWriteSXSSFTest {
    public static String PATH = "/Users/lixin/Desktop/";

    public static void main(String[] args) throws Exception {
        //时间
        long begin = System.currentTimeMillis();

        //创建一个工作簿
        Workbook workbook = new SXSSFWorkbook();

        //创建表
        Sheet sheet = workbook.createSheet();

        //写入数据
        for (int rowNumber = 0; rowNumber < 100000; rowNumber++) {
            Row row = sheet.createRow(rowNumber);
            for (int cellNumber = 0; cellNumber < 10; cellNumber++) {
                Cell cell = row.createCell(cellNumber);
                cell.setCellValue(cellNumber);
            }
        }
        System.out.println("over");

        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "用户信息表-SXSSF.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        long end = System.currentTimeMillis();
        System.out.println((double) (end - begin) / 1000);//6.39s
    }
}

1.3 导入excel

导入操作,即将 excel 中的数据采用java工具库将其解析出来,进而将 excel 数据写入数据库!

同样,在 poi 工具库中,导入 api 也分三种方式,与上面的导出一一对应!

1.3.1 HSSF方式导入

package cn.tedu.excel.test;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.joda.time.DateTime;

import java.io.FileInputStream;
import java.util.Date;

public class ExcelRead2003Test {
    public static String PATH = "/Users/lixin/Desktop/";

    public static void main(String[] args) throws Exception {
        //获取文件流
        FileInputStream inputStream = new FileInputStream(PATH + "用户信息表2003read.xls");

        //1.创建工作簿,使用excel能操作的这边都看看操作
        Workbook workbook = new HSSFWorkbook(inputStream);
        //2.得到表
        Sheet sheet = workbook.getSheetAt(0);
        //3.得到行
        Row row = sheet.getRow(0);
        //4.得到列
        Cell cell = row.getCell(0);
        getValue(cell);
        inputStream.close();
    }

    public static void getValue(Cell cell){
        //匹配类型数据
        if (cell != null) {
            CellType cellType = cell.getCellType();
            String cellValue = "";
            switch (cellType) {
                case STRING: //字符串
                    System.out.print("[String类型]");
                    cellValue = cell.getStringCellValue();
                    break;
                case BOOLEAN: //布尔类型
                    System.out.print("[boolean类型]");
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                case BLANK: //空
                    System.out.print("[BLANK类型]");
                    break;
                case NUMERIC: //数字(日期、普通数字)
                    System.out.print("[NUMERIC类型]");
                    if (HSSFDateUtil.isCellDateFormatted(cell)) { //日期
                        System.out.print("[日期]");
                        Date date = cell.getDateCellValue();
                        cellValue = new DateTime(date).toString("yyyy-MM-dd");
                    } else {
                        //不是日期格式,防止数字过长
                        System.out.print("[转换为字符串输出]");
                        cell.setCellType(CellType.STRING);
                        cellValue = cell.toString();
                    }
                    break;
                case ERROR:
                    System.out.print("[数据类型错误]");
                    break;
            }
            System.out.println(cellValue);
        }
    }
}

输出结果类似如图所示:
在这里插入图片描述

1.3.2 XSSF方式导入

package cn.tedu.excel.test;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;

import java.io.FileInputStream;
import java.util.Date;

public class ExcelRead2007Test {
    public static String PATH = "/Users/lixin/Desktop/";

    public static void main(String[] args) throws Exception {
        //获取文件流
        FileInputStream inputStream = new FileInputStream(PATH + "用户信息表2007read.xlsx");

        //1.创建工作簿,使用excel能操作的这边都看看操作
        Workbook workbook = new XSSFWorkbook(inputStream);
        //2.得到表
        Sheet sheet = workbook.getSheetAt(0);
        //3.得到行
        Row row = sheet.getRow(0);
        //4.得到列
        Cell cell = row.getCell(0);
        getValue(cell);
        inputStream.close();
    }
    public static void getValue(Cell cell){
        //匹配类型数据
        if (cell != null) {
            CellType cellType = cell.getCellType();
            String cellValue = "";
            switch (cellType) {
                case STRING: //字符串
                    System.out.print("[String类型]");
                    cellValue = cell.getStringCellValue();
                    break;
                case BOOLEAN: //布尔类型
                    System.out.print("[boolean类型]");
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                case BLANK: //空
                    System.out.print("[BLANK类型]");
                    break;
                case NUMERIC: //数字(日期、普通数字)
                    System.out.print("[NUMERIC类型]");
                    if (HSSFDateUtil.isCellDateFormatted(cell)) { //日期
                        System.out.print("[日期]");
                        Date date = cell.getDateCellValue();
                        cellValue = new DateTime(date).toString("yyyy-MM-dd");
                    } else {
                        //不是日期格式,防止数字过长
                        System.out.print("[转换为字符串输出]");
                        cell.setCellType(CellType.STRING);
                        cellValue = cell.toString();
                    }
                    break;
                case ERROR:
                    System.out.print("[数据类型错误]");
                    break;
            }
            System.out.println(cellValue);
        }
    }
}

1.3.3 SXSSF方式导入

package cn.tedu.excel.test;

import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class ExcelReadSXSSFTest {
    public static String PATH = "/Users/lixin/Desktop/";

    public static void main(String[] args) throws Exception {
        //获取文件流

        //1.创建工作簿,使用excel能操作的这边都看看操作
        OPCPackage opcPackage = OPCPackage.open(PATH + "用户信息表2007read.xlsx");
        XSSFReader xssfReader = new XSSFReader(opcPackage);
        StylesTable stylesTable = xssfReader.getStylesTable();
        ReadOnlySharedStringsTable sharedStringsTable = new ReadOnlySharedStringsTable(opcPackage);
        // 创建XMLReader,设置ContentHandler
        XMLReader xmlReader = SAXHelper.newXMLReader();
        xmlReader.setContentHandler(new XSSFSheetXMLHandler(stylesTable, sharedStringsTable, new SimpleSheetContentsHandler(), false));
        // 解析每个Sheet数据
        Iterator<InputStream> sheetsData = xssfReader.getSheetsData();
        while (sheetsData.hasNext()) {
            try (InputStream inputStream = sheetsData.next();) {
                xmlReader.parse(new InputSource(inputStream));
            }
        }
    }
    /**
     * 内容处理器
     */
    public static class SimpleSheetContentsHandler implements XSSFSheetXMLHandler.SheetContentsHandler {

        protected List<String> row;

        @Override
        public void startRow(int rowNum) {
            row = new ArrayList<>();
        }

        @Override
        public void endRow(int rowNum) {
            if (row.isEmpty()) {
                return;
            }
            // 处理数据
            System.out.println(row.stream().collect(Collectors.joining("   ")));
        }

        @Override
        public void cell(String cellReference, String formattedValue, XSSFComment comment) {
            row.add(formattedValue);
        }

        @Override
        public void headerFooter(String text, boolean isHeader, String tagName) {
        }
    }
}

在这里插入图片描述

二、Easypoi

以前的以前,有个大佬程序员,跳到一家公司之后就和业务人员聊上了,这些业务员对excel报表有着许许多多的要求,比如想要一个报表,他的表头是一个多行表头,过几天之后,他想要给这些表头添加样式,比如关键的数据标红,再过几天,他想要再末尾添加一条合计的数据,等等!

起初还好,都是copy、copy,之后发现系统中出现大量的重复代码,于是有一天真的忍受不了了,采用注解搞定来搞定这些定制化成程度高的逻辑,将公共化抽离出来,于是诞生了 easypoi!它的底层也是基于 apache poi 进行深度开发的,它主要的特点就是将更多重复的工作,全部简单化,避免编写重复的代码!

下面,我们就一起来了解一下这款高大上的开源工具:easypoi

2.1 添加依赖包

<dependencies>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-base</artifactId>
        <version>4.1.0</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-web</artifactId>
        <version>4.1.0</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-annotation</artifactId>
        <version>4.1.0</version>
    </dependency>
	<dependency>
	    <groupId>com.googlecode.json-simple</groupId>
	    <artifactId>json-simple</artifactId>
	    <version>1.1.1</version>
	</dependency>
</dependencies>

2.2 采用注解导出导入

easypoi 最大的亮点就是基于注解实体类来导出、导入excel,使用起来非常简单!

我们创建一个实体类UserEntity,其中@Excel注解表示导出文件的头部信息。

添加Lombok插件,替代set和get方法

2.2.1 导出操作

package cn.tedu.excel.easypoi;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserEntity {
    @Excel(name = "姓名")
    private String name;
    @Excel(name = "年龄")
    private int age;
    @Excel(name = "操作时间",format="yyyy-MM-dd HH:mm:ss", width = 20.0)
    private Date time;

    public static void main(String[] args) throws Exception {
        List<UserEntity> dataList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserEntity userEntity = new UserEntity();
            userEntity.setName("张三" + i);
            userEntity.setAge(20 + i);
            userEntity.setTime(new Date(System.currentTimeMillis() + i));
            dataList.add(userEntity);
        }
        //生成excel文档
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户","用户信息"),
                UserEntity.class, dataList);
        FileOutputStream fos = new FileOutputStream("/Users/lixin/Desktop/easypoi-user.xls");
        workbook.write(fos);
        fos.close();
    }
}

导出文件预览图如下:
在这里插入图片描述

2.2.2 导入操作

package cn.tedu.excel.easypoi;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.File;
import java.util.Date;
import java.util.List;
import org.json.simple.JSONArray;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentEntity {
    @Excel(name = "姓名")
    private String name;
    @Excel(name = "年龄")
    private int age;
    @Excel(name = "操作时间",format="yyyy-MM-dd HH:mm:ss", width = 20.0)
    private Date time;

    public static void main(String[] args) {
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        long start = new Date().getTime();
        List<StudentEntity> list = ExcelImportUtil.importExcel(new File("/Users/lixin/Desktop/easypoi-user1.xls"),
                UserEntity.class, params);
        System.out.println(new Date().getTime() - start);
        System.out.println(JSONArray.toJSONString(list));
    }
}

输出结果为:

[UserEntity(name=张三0, age=20, time=Mon Mar 29 11:29:52 CST 2021),UserEntity(name=李四, age=21, time=Mon Mar 29 11:29:52 CST 2021),UserEntity(name=王武, age=22, time=Mon Mar 29 11:29:52 CST 2021),UserEntity(name=赵六, age=23, time=Mon Mar 29 11:29:52 CST 2021),UserEntity(name=null, age=0, time=null),UserEntity(name=null, age=0, time=null),UserEntity(name=null, age=0, time=null),UserEntity(name=null, age=0, time=null),UserEntity(name=null, age=0, time=null),UserEntity(name=null, age=0, time=null)]

2.3 自定义数据结构导出导入

easypoi 同样也支持自定义数据结构导出导入excel。

自定义数据导出 excel

2.3.1 导出操作

public static void main(String[] args) throws Exception {
    //封装表头
    List<ExcelExportEntity> entityList = new ArrayList<ExcelExportEntity>();
    entityList.add(new ExcelExportEntity("姓名", "name"));
    entityList.add(new ExcelExportEntity("年龄", "age"));
    ExcelExportEntity entityTime = new ExcelExportEntity("操作时间", "time");
    entityTime.setFormat("yyyy-MM-dd HH:mm:ss");
    entityTime.setWidth(20.0);
    entityList.add(entityTime);
    //封装数据体
    List<Map<String, Object>> dataList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        Map<String, Object> userEntityMap = new HashMap<>();
        userEntityMap.put("name", "张三" + i);
        userEntityMap.put("age", 20 + i);
        userEntityMap.put("time", new Date(System.currentTimeMillis() + i));
        dataList.add(userEntityMap);
    }
    //生成excel文档
    Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("学生","用户信息"), entityList, dataList);
    FileOutputStream fos = new FileOutputStream("/Users/lixin/Desktop/easypoi-user2.xls");
    workbook.write(fos);
    fos.close();
}

2.3.2 导入操作

public static void main(String[] args) {
    ImportParams params = new ImportParams();
    params.setTitleRows(1);
    params.setHeadRows(1);
    long start = new Date().getTime();
    List<Map<String, Object>> list = ExcelImportUtil.importExcel(new File("/Users/lixin/Desktop/easypoi-user2.xls"),
            Map.class, params);
    System.out.println(new Date().getTime() - start);
    System.out.println(JSONArray.toJSONString(list));
}

更多的 api 操作可以访问 Easypoi - 接口文档

三、Easyexcel

easyexcel 是阿里巴巴开源的一款 excel 解析工具,底层逻辑也是基于 apache poi 进行二次开发的。不同的是,再读写数据的时候,采用 sax 模式一行一行解析,在并发量很大的情况下,依然能稳定运行!

下面,我们就一起来了解一下这款新起之秀!

3.1 添加依赖包

<!-- EasyExcel -->
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>easyexcel</artifactId>
     <version>2.2.6</version>
 </dependency>
 <!--常用工具库-->
 <dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava</artifactId>
     <version>29.0-jre</version>
 </dependency>

3.2 采用注解导出导入

easyexcel 同样也支持采用注解方式进行导出、导入!

首先,我们创建一个实体类UserEntity,其中@ExcelProperty注解表示导出文件的头部信息。

3.2.1 导出操作

package cn.tedu.excel.easyexcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserEntity {
    @ExcelProperty(value = "姓名")
    private String name;

    @ExcelProperty(value = "年龄")
    private int age;

    @DateTimeFormat(fallbackPatterns = "yyyy-MM-dd HH:mm:ss")
    @ExcelProperty(value = "操作时间")
    private Date time;

    public static void main(String[] args) {
        List<UserEntity> dataList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserEntity userEntity = new UserEntity();
            userEntity.setName("张三" + i);
            userEntity.setAge(20 + i);
            userEntity.setTime(new Date(System.currentTimeMillis() + i));
            dataList.add(userEntity);
        }
        EasyExcel.write("/Users/lixin/Desktop/easyexcel-user1.xls", UserEntity.class).sheet("用户信息").doWrite(dataList);
    }
}

导出预览图:
在这里插入图片描述

3.2.2 导入操作

package cn.tedu.excel.easyexcel;

import com.alibaba.excel.EasyExcel;
import org.json.simple.JSONArray;

import java.util.List;

public class DemoData {
    public static void main(String[] args) {
        String filePath = "/Users/lixin/Desktop/easyexcel-user1.xls";
        List<DemoData> list = EasyExcel.read(filePath).head(UserEntity.class).sheet().doReadSync();
        System.out.println(JSONArray.toJSONString(list));
    }
}

结果显示:

[UserEntity(name=张三0, age=20, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三1, age=21, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三2, age=22, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三3, age=23, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三4, age=24, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三5, age=25, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三6, age=26, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三7, age=27, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三8, age=28, time=Mon Mar 29 16:42:20 CST 2021),UserEntity(name=张三9, age=29, time=Mon Mar 29 16:42:20 CST 2021)]

3.3 自定义数据结构导出导入

easyexcel 同样也支持自定义数据结构导出导入excel。

3.3.1 导出操作

public static void main(String[] args) {
    //表头
    List<List<String>> headList = new ArrayList<>();
    headList.add(Lists.newArrayList("姓名"));
    headList.add(Lists.newArrayList("年龄"));
    headList.add(Lists.newArrayList("操作时间"));

    //数据体
    List<List<Object>> dataList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        List<Object> data = new ArrayList<>();
        data.add("张三" + i);
        data.add(20 + i);
        data.add(new Date(System.currentTimeMillis() + i));
        dataList.add(data);
    }
    EasyExcel.write("/Users/hello/Documents/easyexcel-user2.xls").head(headList).sheet("用户信息").doWrite(dataList);
}

3.3.2 导入操作

public static void main(String[] args) {
    String filePath = "/Users/panzhi/Documents/easyexcel-user2.xls";
    UserDataListener userDataListener = new UserDataListener();
    EasyExcel.read(filePath, userDataListener).sheet().doRead();
    System.out.println("表头:" + JSONArray.toJSONString(userDataListener.getHeadList()));
    System.out.println("数据体:" + JSONArray.toJSONString(userDataListener.getDataList()));
}

运行结果如图所示:

表头:[{0:"姓名",1:"年龄",2:"操作时间"}]
数据体:[{0:"张三0",1:"20",2:"2021-03-29 16:31:39"},{0:"张三1",1:"21",2:"2021-03-29 16:31:39"},{0:"张三2",1:"22",2:"2021-03-29 16:31:39"},{0:"张三3",1:"23",2:"2021-03-29 16:31:39"},{0:"张三4",1:"24",2:"2021-03-29 16:31:39"},{0:"张三5",1:"25",2:"2021-03-29 16:31:39"},{0:"张三6",1:"26",2:"2021-03-29 16:31:39"},{0:"张三7",1:"27",2:"2021-03-29 16:31:39"},{0:"张三8",1:"28",2:"2021-03-29 16:31:39"},{0:"张三9",1:"29",2:"2021-03-29 16:31:39"}]

更多的 api 操作可以访问 easyexcel - 接口文档!

四、总结

总体来说,EasypoiEasyexcel 都是基于Apache poi进行二次开发的。

不同点在于:

  1. Easypoi 在读写数据的时候,优先是先将数据写入内存,优点是读写性能非常高,但是当数据量很大的时候,会出现oom,当然它也提供了 sax 模式的读写方式,需要调用特定的方法实现。
  2. Easyexcel 基于sax模式进行读写数据,不会出现oom情况,程序有过高并发场景的验证,因此程序运行比较稳定,相对于 Easypoi 来说,读写性能稍慢!

EasypoiEasyexcel 还有一点区别在于,Easypoi 对定制化的导出支持非常的丰富,如果当前的项目需求,并发量不大、数据量也不大,但是需要导出 excel 的文件样式千差万别,那么我推荐你用 easypoi;反之,使用 easyexcel !

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Java操作excel的几种方法 的相关文章

  • Jackson JSON + Java 泛型

    我正在尝试将以下 JSON 反序列化 映射到List
  • 非易失性领域的出版与阅读

    public class Factory private Singleton instance public Singleton getInstance Singleton res instance if res null synchron
  • Kafka - 如何同时使用过滤器和过滤器?

    我有一个 Kafka 流 它从一个主题获取数据 并且需要将该信息过滤到两个不同的主题 KStream
  • 如何以编程方式使用包含多列的 where-in 子句执行 PostgreSQL 查询?

    我的查询是这样的 select from plat customs complex where code t code s in 01013090 10 01029010 90 它在 psql 控制台中运行良好 我的问题是如何在客户端代码中
  • Java 中的 <-- 是什么? [复制]

    这个问题在这里已经有答案了 我遇到了下面的片段 它输出到4 3 2 1 我从来没有遇到过 lt 在爪哇 Is lt 使 var1 的值变为 var2 的运算符 public class Test public static void mai
  • 使用 Exec Maven 插件分叉 Java,而不使用“exec”目标

    来自文档 https www mojohaus org exec maven plugin exec exec在单独的进程中执行程序和Java程序 exec java在同一虚拟机中执行 Java 程序 我想 fork 一个 java 程序
  • 我们可以有条件地声明 spring bean 吗?

    有没有一种方法可以有条件地声明 Spring bean 例如
  • Java中Gson、JsonElement、String比较

    好吧 我想知道这可能非常简单和愚蠢 但在与这种情况作斗争一段时间后 我不知道发生了什么 我正在使用 Gson 来处理一些 JSON 元素 在我的代码中的某个位置 我将 JsonObject 的 JsonElements 之一作为字符串获取
  • JOOQ 忽略具有默认值的数据库列

    看来JOOQ完全忽略了数据库列的默认值 既不会更新 ActiveRecord 对象 也不会在 INSERT 时跳过此列 相反 它尝试将其设置为 NULL 这在 NOT NULL 列上失败 Example CREATE TABLE bug f
  • 为什么 jar 执行的通配符在 docker CMD 中不起作用?

    我有一个Dockerfile与以下CMD启动我的 Spring Boot 应用程序 FROM java 8 jre CMD java jar app file jar 当我尝试从创建的图像启动容器时 我得到 Error Unable to
  • Java AES 256 加密

    我有下面的 java 代码来加密使用 64 个字符密钥的字符串 我的问题是这会是 AES 256 加密吗 String keyString C0BAE23DF8B51807B3E17D21925FADF273A70181E1D81B8EDE
  • JAXB - 忽略元素

    有什么方法可以忽略 Jaxb 解析中的元素吗 我有一个很大的 XML 文件 如果我可以忽略其中一个大而复杂的元素 那么它的解析速度可能会快很多 如果它根本无法验证元素内容并解析文档的其余部分 即使该元素不正确 那就更好了 例如 这应该只生成
  • Mockito 和 Hamcrest:如何验证 Collection 参数的调用?

    我遇到了 Mockito 和 Hamcrest 的泛型问题 请假设以下界面 public interface Service void perform Collection
  • 从三点求圆心的算法是什么?

    我在圆的圆周上有三个点 pt A A x A y pt B B x B y pt C C x C y 如何计算圆心 在Processing Java 中实现它 我找到了答案并实施了一个可行的解决方案 pt circleCenter pt A
  • 我所有的 java 应用程序现在都会抛出 java.awt.headlessException

    所以几天前我有几个工作Java应用程序使用Swing图书馆 JFrame尤其 他们都工作得很好 现在他们都抛出了这个异常 java awt headlessexception 我不知道是什么改变了也许我的Java版本不小心更新了 谢谢你尽你
  • Android ScrollView,检查当前是否滚动

    有没有办法检查标准 ScrollView 当前是否正在滚动 方向是向上还是向下并不重要 我只需要检查它当前是否正在滚动 ScrollView当前形式不提供用于检测滚动事件的回调 有两种解决方法可用 1 Use a ListView并实施On
  • 确定 JavaFX 中是否消耗了事件

    我正在尝试使用 JavaFX 中的事件处理来做一些非滑雪道的事情 我需要能够确定手动触发事件后是否已消耗该事件 在以下示例中 正确接收了合成鼠标事件 但调用 Consumer 不会更新该事件 我对此进行了调试 发现 JavaFX 实际上创建
  • Java 中清除嵌套 Map 的好方法

    public class MyCache AbstractMap
  • 什么是 Java2D 处理程序线程?

    我创建了一个使用 Hibernate 的示例 java 应用程序 当我进行线程转储时 我观察到一个名为 Java2D Disposer 的奇怪线程 有人能告诉我该线程的功能吗 AWT 系统中的某些实体需要最终确定以释放资源 最突出的例子是j
  • Java 的“&&”与“&”运算符

    我使用的示例来自 Java Herbert Schildt 的完整参考文献 第 12 版 Java 是 14 他给出了以下 2 个示例 如果阻止 第一个是好的 第二个是错误的 因此发表评论 public class PatternMatch

随机推荐

  • jenkins+ant&findbugs&fireline

    火线在jenkins上的安装 http magic 360 cn zh user html Jenkins jenkins插件离线下载的好地方 http updates jenkins ci org download plugins 在je
  • C语言运算符——自增与自减

    自增与自减 一个整数类型的变量自身加 1 可以这样写 a a 1 或者a 1 不过 C语言还支持另外一种更加简洁的写法 就是 a 或者 a 这种写法叫做自加或自增 意思很明确 就是每次自身加 1 相应的 也有a 和 a 它们叫做自减 表示自
  • 功能测试数据测试之数据测试关注点

    数据类型 常见数据类型 整型 浮点型 字符型 布尔型等 可用等价类方法对输入数据类型设计测试用例 数据长度 数据长度可能是固定长度或者是在某个范围内的长度 可用等价类和边界值方法对数据长度设计测试用例 数据一致性 组织数据测试该交易 在交易
  • Fatal Python error: init_sys_streams: can‘t initialize sys standard streamsPython runtime state: 问题

    哈喽 大家好 我是 奇点 江湖人称 singularity 刚工作几年 想和大家一同进步 一位上进心十足的 Java ToB端大厂领域博主 喜欢java和python 平时比较懒 能用程序解决的坚决不手动解决 如果有对 java 感兴趣的
  • canvas绘制火柴人

  • 每日面试题day02

    1 int 和 Integer 有什么区别 int 是基本数据类型 Integer 是其包装类 注意是一个类 在 java 中包装类 用途比较多的是用在于各种数据类型的转化中 2 重载和重写的区别 overload 重载 参数类型 个数 顺
  • vue3如何进行数据监听watch/watchEffect

    我们都知道监听器的作用是在每次响应式状态发生变化时触发 在组合式 API 中 我们可以使用 watch 函数和watchEffect 函数 当你更改了响应式状态 它可能会同时触发 Vue 组件更新和侦听器回调 默认情况下 用户创建的侦听器回
  • IntelliJ IDEA Plugins加载太慢_IntelliJ IDEA Plugins搜不出来【已解决】

    问题 IntelliJ IDEA Plugins加载太慢或者IntelliJ IDEA Plugins搜不出来 解决方案
  • html form 表单

    定义 form 表单在网页中主要负责数据采集功能 属于一个容器标记 表单组成 一个表单由 form元素 表单控件 和 表单按钮 组成 1 form元素 form元素用来创建表单 语法格式如下
  • SQL中根据经纬度计算两点之间的直线距离

    最近接到一个需求获取当前用户的经纬度 然后计算与目标地的的距离 我自己也是看别人的博客学习 自己也做个记录吧 直接放出计算的公式 不想浪费时间的 直接看公式套进去就成 依次是纬度 纬度 经度 round 6378 138 2 ASIN SQ
  • vue显示PDF文件

    小编最近接手的项目中 有个需求 前端显示后端返回的PDF格式的文件 经过小编两天的调研和试验 终于找到了一个比较好的插件方法 直接贴代码 1 安装 npm i vue pdf signature save dev 2 pdfShow vue
  • 一个测试的成长历程【功能测试篇】——web测试的总结

  • js自写发布订阅模块

    实现效果如下图所示 代码如下
  • 【论文阅读】文献阅读笔记-泊松重建

    先了解泊松分布 就二项分布而言 泊松分布可以是二项分布的推广 样本数趋向于无穷大 而事件发生的概率趋近于0时 此时期望满足np Lamda 常数 且此时事件发生的概率满足泊松分布 且概率的计算只与Lamda有关 但泊松方程和泊松分布没啥关系
  • 微信小程序实现扫二维码时仿微信扫码音效

    需求分析 使用wx scanCode时无交互感 对用户来说没有反馈 故增加扫码成功时震动及播放微信扫码音效 index html
  • 一些关于c语言if语句的练习

    练习题1 在终端输入一个整数 用来表示学生的成绩 输出学生成绩对应的等级 90 100 A 80 90 B 70 80 C 60 70 D 0 60 不及格 练习题2 在终端输入一个整数 用来表示年份 输出这一年是平年还是闰年 闰年 能被4
  • 联盟链FISCO BCOS网络端口讲解

    FISCO BCOS是完全开源的联盟区块链底层技术平台 由金融区块链合作联盟 深圳 简称金链盟 成立开源工作组通力打造 开源工作组成员包括博彦科技 华为 深证通 神州数码 四方精创 腾讯 微众银行 亦笔科技和越秀金科等金链盟成员机构 代码仓
  • IDEA 查看源码快捷键

    一 快捷键 快捷键 功能 Ctrl Shift i 出现类似于预览的小窗口 Ctrl Enter 接上步 完全打开源码 Ctrl 鼠标左键 一步到位打开源码 Ctrl Shift i gt Ctrl Enter IDEA 2018版 实用快
  • 使用Canal实现mysql binlog增量订阅数据

    前言 是由公司业务改造搜索功能 使用ES搜索引擎中间件 那么我们需要将mysql中的数据同步至ES服务中 最总选择使用alibaba的canal增量订阅和解析工具 简单原理 canal模拟mysql slave的交互协议 伪装自己为mysq
  • 使用Java操作excel的几种方法

    在平时的业务系统开发中 少不了需要用到导出 导入excel功能 今天我们就一起来总结一下 下面给大家介绍一下几种常用方法 apache poi easypoi easyexcel 文章目录 一 Apache poi 1 1 首先添加依赖 1