zoukankan      html  css  js  c++  java
  • java的(SXSSF)EasyExcel阿里开源excel导出和XSSF导出简单示例

    一、EasyExcel阿里开源excel导出(SXSSF)

    参考链接:EasyExcel阿里开源excel导出

     1、建立映射到excel文件的映射类,然后get和set

    import com.alibaba.excel.annotation.ExcelProperty;
    
    public class DownloadAjgl {
        @ExcelProperty(value = "账套编码", index = 0)//可以只写列名,不写index会默认按照这个类的属性顺序来写到excel
        private String ztCode;
        @ExcelProperty(value = "账套名称", index = 1)
        private String ztName;
        @ExcelProperty("年份")
        private int year;
        @ExcelProperty("部门编码")
        private String bmCode;
        @ExcelProperty("部门名称")
        private String bmName;
    
        public String getZtCode() {
            return ztCode;
        }
    
        public void setZtCode(String ztCode) {
            this.ztCode = ztCode;
        }
    
        public String getZtName() {
            return ztName;
        }
    
        public void setZtName(String ztName) {
            this.ztName = ztName;
        }
    
        public int getYear() {
            return year;
        }
    
        public void setYear(int year) {
            this.year = year;
        }
    
        public String getBmCode() {
            return bmCode;
        }
    
        public void setBmCode(String bmCode) {
            this.bmCode = bmCode;
        }
    
        public String getBmName() {
            return bmName;
        }
    
        public void setBmName(String bmName) {
            this.bmName = bmName;
        }
    
       
    
    }

    2、controller里面

    @GetMapping("/exportExcel")
        public void exportExcel(@RequestParam(value = "ztId") int ztId, HttpServletResponse response) throws IOException {
    
            List<Ajgl> ajglList =ajglRepository.findAllByZtId(ztId);
           
            if (ajglList.size() > 0) {
                response.setHeader("Content-Disposition", "attachment; filename=Ajgl.xlsx");
                // 响应类型,编码
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    
     EasyExcel.write(response.getOutputStream(), DownloadAjgl.class).sheet("案卷导出模板").doWrite(data(ajglList));//data是把数据封装成映射类的自定义方法
                
    
            }
        }

    3、前端跟下面  “二、XSSF导出。”一样

    4、这点比较重要,如果不做的话会报错
    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.excel.exception.ExcelGenerateException: Can not close IO.] with root
    cause
    java.net.SocketTimeoutException: null

    (我公司用window10的子系统ubuntu编译运行的)

    需要在ubuntu运行几个命令

    $ sudo apt-get update
    $ sudo apt-get upgrade
    $ sudo apt-get install build-essential git unzip zip curl wget vim fontconfig ttf-dejavu fonts-dejavu

    主要是第三个命令,只要第三个命令运行成功之后就不会报错了。

    二、XSSF导出。

    java代码

    @GetMapping("/exportExcel")
        public void exportExcel(@RequestParam(value = "ztId") int ztId,
                                HttpServletResponse response) throws IOException {
       
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
        XSSFSheet sheet = xssfWorkbook.createSheet("测试");
        XSSFRow row0 = sheet.createRow(0);
        row0.createCell(0).setCellValue("编码");
        row0.createCell(1).setCellValue("名称");
        List<Ce> ces = ceRepository.findAllByZtId(ztId);
        int num=0;
        for(var it : ces){
          num++;
          XSSFRow row = sheet.createRow(num);
          row.createCell(0).setCellValue(it.getCode());
          row.createCell(1).setCellValue(it.getName());
        }
       response.setHeader("Content-Disposition", "attachment; filename=Cs.xlsx");
         // 响应类型,编码
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 将指定的字节写入此输出流
        xssfWorkbook.write(response.getOutputStream());
        response.flushBuffer();
        xssfWorkbook.close();
    }

    在自定义的request.js中导出download

    export const download = (path, name) => {
      const data = options('GET');
      fetch(backend(path), data)
        .then(response => response.blob())
        .then(blob => {
          var url = window.URL.createObjectURL(blob);
          var a = document.createElement('a');
          a.href = url;
          a.download = name;
          document.body.appendChild(a); // for firefox
          a.click();
          a.remove();
        });
    };

    前端代码:

    <el-button type="warning" size="small" @click="exportExcel">导出</el-button>
    
    .........
    
    <script>
    import {
      download as httpDownload,//下载必须的
      upload as uploadHeaders,
      get as httpGet,
      delete_ as httpDelete,
      PAGE_SIZE
    } from "@/request";
    .............
    
      methods: {
        exportExcel() {
           httpDownload(`/exportExcel/?ztId=${this.ztId}`, "Ajgl.xlsx");
        }
    }
    .....

     三、HSSFworkbook、XSSFworkbook、SXSSFworkbook区别总结

    参考连接:HSSFworkbook,XSSFworkbook,SXSSFworkbook区别总结

    1、HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;

    poi导出excel最常用的方式;但是此种方式的局限就是导出的行数至多为65535行,超出65536条后系统就会报错。此方式因为行数不足七万行所以一般不会发生内存不足的情况(OOM:OutOfMemoryError)。

    2、XSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;

    这种形式的出现是为了突破HSSFWorkbook的65535行局限。其对应的是excel2007(1048576行,16384列)扩展名为“.xlsx”,最多可以导出104万行,不过这样就伴随着一个问题---OOM内存溢出,原因是你所创建的book sheet row cell等此时是存在内存的并没有持久化。

    3、SXSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;

    从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的SXSSF方式。对于大型excel文件的创建,一个关键问题就是,要确保不会内存溢出。其实,就算生成很小的excel(比如几Mb),它用掉的内存是远大于excel文件实际的size的。如果单元格还有各种格式(比如,加粗,背景标红之类的),那它占用的内存就更多了。对于大型excel的创建且不会内存溢出的,就只有SXSSFWorkbook了。它的原理很简单,用硬盘空间换内存(就像hash map用空间换时间一样)。

    SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excel rows在内存里供查看,在此之前的excel rows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。

    SXSSF与XSSF的对比:

    a. 在一个时间点上,只可以访问一定数量的数据

    b. 不再支持Sheet.clone()

    c. 不再支持公式的求值

    d. 在使用Excel模板下载数据时将不能动态改变表头,因为这种方式已经提前把excel写到硬盘的了就不能再改了

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    (无关)(额外)请求导出示例:

    import {
      get as getToken
    } from './token';
    
    export const PAGE_SIZE = 20;
    
    export const backend = (u) => `${process.env.VUE_APP_BASE_API}${u}`;
    
    export const upload = () => {
      return {
        'Authorization': `Bearer ${getToken()}`
      }
    }
    
    export const options = (method) => {
      return {
        credentials: 'include',
        headers: {
          'Authorization': `Bearer ${getToken()}`,
          'Content-Type': 'application/json; charset=utf-8'
        },
        method
      };
    };
    
    export const get = (path) => fetch(backend(path), options('GET')).then((res) => res.status === 200 ?
      res.json() :
      res.json().then(err => {
        throw err;
      }));
    
    export const delete_ = (path) => fetch(backend(path), options('DELETE')).then((res) => res.status === 200 ?
      res.json() :
      res.json().then(err => {
        throw err;
      }));
    
    // https://github.github.io/fetch/#options
    export const post = (path, body) => {
      const data = options('POST');
      data.body = JSON.stringify(body);
      return fetch(backend(path), data).then((res) => res.status === 200 ?
        res.json() :
        res.json().then(err => {
          throw err;
        }));
    };
    
    export const patch = (path, body) => {
      const data = options('PATCH');
      data.body = JSON.stringify(body);
      return fetch(backend(path), data).then((res) => res.status === 200 ?
        res.json() :
        res.json().then(err => {
          throw err;
        }));
    };
    
    export const put = (path, body) => {
      const data = options('PUT');
      data.body = JSON.stringify(body);
      return fetch(backend(path), data).then((res) => res.status === 200 ?
        res.json() :
        res.json().then(err => {
          throw err;
        }));
    };
    
    
    export const download = (path, name) => {
      const data = options('GET');
      fetch(backend(path), data)
        .then(response => response.blob())
        .then(blob => {
          var url = window.URL.createObjectURL(blob);
          var a = document.createElement('a');
          a.href = url;
          a.download = name;
          document.body.appendChild(a); // for firefox
          a.click();
          a.remove();
        });
    };

    使用例子:

    .........
    <script>
    import {
      download as httpDownload,
      upload as uploadHeaders,
      get as httpGet,
      delete_ as httpDelete,
      PAGE_SIZE
    } from "@/request";
    ...................
  • 相关阅读:
    [No0000CA]什么是“普瑞马法则”?以及 如何利用“普瑞马法则”,三步克服惰性
    [No0000B9]C# 类型基础 值类型和引用类型 及其 对象复制 浅度复制vs深度复制 深入研究2
    [No0000B8]WPF或Winform调用系统Console控制台显示信息
    [No0000B7]If else 与 三元表达式? : 效率对比
    [No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1
    [No0000B4].Net中String是引用类型还是值类型,答string是特殊的引用类型
    [No0000B6]C#中 ==与equals的区别
    [No0000B3].NET C# 单体模式(Singleton)
    [No0000AF]去除wpf窗口标题栏ICON
    [No000090]C#捕获控制台(console)关闭事件及响应cmd快捷键
  • 原文地址:https://www.cnblogs.com/pzw23/p/12786744.html
Copyright © 2011-2022 走看看