当前位置: 首页 > 工具软件 > easyexcel > 使用案例 >

easyExcel

宋畅
2023-12-01

什么是easyExcel

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
EasyExcel官方文档地址

下载模板

需要导入数据时,我们一定需要先制定模板,通过模板导入数据。接下来描述的是springBoot读取resource下的文件并下载。templatePath应该是从resource下开始,需要文件名需要加后缀。如"导入律师库模板.xlsx"

//读取文件
        try (InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templatePath)) {
//            //fast-fail原则
            HttpServletResponse response = context.getHttpServletResponse();
            assert resourceAsStream != null;
            try (BufferedInputStream fis = new BufferedInputStream(resourceAsStream); OutputStream toClient = new BufferedOutputStream(response.getOutputStream())) {
                //获取文件名
                String name = FileUtil.getName(templatePath);
                int available = fis.available();
                byte[] buffer = new byte[4096];
                int r;
                while (-1 != (r = fis.read(buffer))) {
                    toClient.write(buffer, 0, r);
                }
                // 清空response
                //response.reset();
                // 设置response的Header
                response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(name, "utf-8"));
                response.addHeader("Content-Length", "" + available);
                //response.setContentType("application/octet-stream");
                toClient.flush();
            }
        }

下载的模板可能会出现乱码,因为编译时也编译了模板文件,需要在pom.xml文件中配置不编译模板文件类型的文件。

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <configuration>
            <encoding>UTF-8</encoding>
            <nonFilteredFileExtensions>
                <nonFilteredFileExtension>xls</nonFilteredFileExtension>
                <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
            </nonFilteredFileExtensions>
        </configuration>
    </plugin>
</plugins>

读取文件

  • read()
    从读取流读取的是一个一个字节,.返回的是字节的(0-255)内的字节值,读一个下次就自动到下一个,如果返回值是-1说明读完了。
  • read(byte[] bytes)
    从读取流读取一定数量的字节,如果比如文件总共是102个字节,我们定义的数组长度是10,那么默认前面10次都是读取10个长度。最后一次不够十个,那么读取的是2个,这十一次,每次都是放入10个长度的数组。
  • read(byte[] bytes,int off ,int len)
    从读取流读取一定数量的字节,如果比如文件总共是102个字节,read(bytes,0,9)那么每次往里面添加的(将只会是9个长度),就要读12次,最后一次放入3个。0指的的是每次都从读到的第0个开始放到buffer中,放九个长度.

导入

  1. 首先需要依赖EasyExcel
 <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>3.0.5</version>
</dependency>
  1. 读导入的excel中的数据
//参数依次是文件流、接收参数的class类【类中通过@ExcelProperty(value = "案件名称")将excel列表头与类对应。】、指定监听器,读取的sheet页,从execl第几行开始读取。
EasyExcel.readread(InputStream inputStream, Class head, ReadListener readListener).sheet().headRowNumber(headRowNumber).doRead();
  1. 读到excel中的数据时会触发指定的监听器,在监听器中做具体的操作就可以了。
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

导出

  1. 导出到excel

一定要在获取response后立即写,不同格式的文件浏览器需要使用不同的解析
EasyExcel会自动关闭输出流

try {
                HttpServletResponse response = getHttpServletResponse(context, excelName);
                EasyExcel.write(response.getOutputStream(), ExportTraderBaseInfoVo.class).includeColumnFiledNames(includeColumnFiledNames).sheet("交易商基础信息表").doWrite(vos);
            } catch (Exception e) {
                e.printStackTrace();
            }
private HttpServletResponse getHttpServletResponse(ServiceHandlerContext context, String excelName) throws UnsupportedEncodingException {
    HttpServletResponse response = context.getHttpServletResponse();
    // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman测试
    //浏览器解析页面的方式,"application/octet-stream"支持所有格式的文件
    response.setContentType("application/octet-stream");
    告知客户端响应正文类型
    response.setHeader("content-type", "application/octet-stream");
    response.setCharacterEncoding("utf-8");
    // 这里URLEncoder.encode可以防止中文乱码
    String fileName = URLEncoder.encode(excelName, "UTF-8").replaceAll("\\+", "%20")+".xlsx";
    //attachment表示以附件方式下载,如果在页面中打开,应该修改为Inline
    response.setHeader("Content-disposition", "attachment;filename=" + fileName);
    return response;
}
  1. 导出的excel打开后可能出现乱码、文件损坏不能打开,不同文件类型浏览器应该用不同的方式解析。
文件类型解析方式
pdfapplication/pdf
jpeimage/jpeg
jpegimage/jpeg
jpgimage/jpeg
htmtext/html
*application/octet-stream
xlsapplication/vnd.ms-excel
 类似资料:

相关阅读

相关文章

相关问答