本文最后更新于 2023-08-16,文章内容可能已经过时,请注意内容的辨别。

poi与easyexcel

poi

介绍

Aache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。

关键包

包名称 说明
HSSF 提供读写Microsoft Excel XLS格式档案的功能。03版本的
XSSF 提供读写Microsoft Excel OOXML XLSX格式档案的功能。07版本的
HWPF 提供读写Microsoft Word DOC格式档案的功能。
HSLF 提供读写Microsoft PowerPoint格式档案的功能。
HDGF 提供读Microsoft Visio格式档案的功能。
HPBF 提供读Microsoft Publisher格式档案的功能。
HSMF 提供读Microsoft Outlook格式档案的功能。

poi写excel

就是将事物抽象成对象去做

maven quickestart

导包

 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <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.8</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
      <scope>test</scope>
    </dependency>

相关对象

new HSSFWorkbook()  03
new xSSFWorkbook()  07

Workbook=====就是你创建的那个excel的表
Sheet=====就是你创建的那个excel的表里面的sheet
Row=====就是你创建的那个excel的表一行
Cell=====就是你创建的那个excel的表一行的第几个,从0开始
package kj08;

import static org.junit.Assert.assertTrue;

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.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

/**
 * Unit test for simple App.
 */
public class AppTest 
{
    /**
     * Rigorous Test :-)
     */
    @Test
    public void shouldAnswerWithTrue() throws Exception {
        String path = "D:\\";
        // 创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        // 创建一个工作表
        Sheet sheet = workbook.createSheet("工作表1");
        // 创建一行
        Row row1 = sheet.createRow(0);
        // 创建一个单元格
        Cell cell11 = row1.createCell(0);
        // 设置单元格内容
        cell11.setCellValue("用户ID");
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue("用户名");
        // 创建第二行
        Row row2 = sheet.createRow(1);
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue(1);
        Cell cell22 = row2.createCell(1);
        cell22.setCellValue("codewei");
        File file = new File(path + "poitest.xls");
        System.out.println(path);
        file.createNewFile();

        // 生成一张表(IO流)
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        workbook.write(fileOutputStream);
        // 关闭流
        fileOutputStream.close();
        System.out.println("文件生成完毕");
    }
}

poi读excel

    @Test
    public void testRead03() throws Exception{
        String path = "f://test03.xls";
        // 获取文件流
        FileInputStream in = new FileInputStream(path);
        // 读取到工作簿
        Workbook workbook = new HSSFWorkbook(in);
        // 根据索引得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 获取行
        Row row = sheet.getRow(0);
        // 获取单元格
        Cell cell = row.getCell(0);
        // 获取单元格的值
        // getStringCellValue:获取字符串
        // getNumericCellValue:获取数值
        // 读取值的时候一定要注意类型
        String str = cell.getStringCellValue();
        System.out.println(str);
        in.close();
    }

EasyExcel

EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

你只要知道poi容易内存溢出,excel操作简单且不会内存溢出。

EasyExcel写excel

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId> 
<version>2.2.6</version>
</dependency>

实体类

package kj08.pojo;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor

public class Student {
@ExcelProperty("学生姓名")
    private String name;
@ExcelProperty("学生年龄")
    private String age;
@ExcelProperty("学生年性别")
    private String sex;
@ExcelIgnore
private String pwd;

}


监听

package kj08.listen;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import kj08.pojo.Student;

public class StudentListen  extends AnalysisEventListener<Student> {
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
    System.out.println(student);
}

@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    System.out.println("读完了");
}
}

读写

@Test
public void dosth(){
    String fileName = "d://EasyExcelTest.xlsx";
    // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    // 如果这里想使用03 则 传入excelType参数即可
    ArrayList arrayList = new ArrayList<Student>();
    Student student = new Student();
    student.setName("a");
    student.setAge("s");
    student.setPwd("ss");
    student.setSex("ss");
    arrayList.add(student);
    arrayList.add(student);
    arrayList.add(student);
    arrayList.add(student);
    arrayList.add(student);
    arrayList.add(student);
    EasyExcel.write(fileName, Student.class).sheet("模板").doWrite(arrayList);

}

@Test
public void dosthy(){
    String fileName = "d://EasyExcelTest.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    EasyExcel.read(fileName, Student.class, new StudentListen()).sheet().doRead();

}

要做的事都是在监听里面去做的

实例

<form id="fm" action="stu/saveStudentList" method="post" enctype="multipart/form-data" autocomplete="off">
    <input type="file" name="file" id="">
    <input type="submit">
</form>
  @RequestMapping("saveStudentList")
    public String saveStudentList(MultipartFile file) throws IOException {
      InputStream inputStream = file.getInputStream();
      EasyExcelFactory.read(inputStream, Student.class,new StudentListener(studentService)).sheet().doRead();
      inputStream.close();
      return "redirect:queryAll";

  }
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

@ExcelProperty("编号")
  private long id;
@ExcelProperty("姓名")
  private String name;
@ExcelProperty("年龄")
  private long age;
@ExcelProperty("性别")
  private String sex;
@ExcelProperty("密码")
  private String pwd;
@ExcelProperty("老师编号")
  private long tid;
@ExcelProperty("版本")
  private long version;

}
package s309.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import s309.mapper.StudentMapper;
import s309.pojo.Student;
import s309.service.IStudentService;
import s309.service.impl.StudentService;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class StudentListener extends AnalysisEventListener<Student> {

private static final int BATCH_COUNT = 5;
List<Student> list = new ArrayList<Student>();


private IStudentService studentService;

public StudentListener() {
}

public StudentListener(IStudentService studentService) {
    this.studentService = studentService;
}

/**
 * 读取数据会执行invoke方法
 * DemoData 类型
 * AnalysisContext 分析上下文
 * @param data
 * @param context
 */
@Override
public void invoke(Student data, AnalysisContext context) {
    System.out.println(JSON.toJSONString(data));
    list.add(data);
    /*// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
    if (list.size() >= BATCH_COUNT) {
        saveData();
        // 存储完成清理 list
        list.clear();
    }*/
}
/**
 * 所有数据解析完成了 都会来调用
 *
 * @param context
 */
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
    // 这里也要保存数据,确保最后遗留的数据也存储到数据库
    saveData();
  /*  log.info("所有数据解析完成!");*/
}
/**
 * 加上存储数据库
 */
private void saveData() {
   /* log.info("{}条数据,开始存储数据库!", list.size());*/
    System.out.println(list.size());
    studentService.saveAll(list);
   /* log.info("存储数据库成功!");*/
}

}