java实现excel的导出之使用easyExcel

这篇具有很好参考价值的文章主要介绍了java实现excel的导出之使用easyExcel。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在我们的项目需求中,经常会遇到导出的需求,其中excel的导出最为常见。生成Excel比较有名的框架有Apache poi,jxl等,但他们都存在一个严重的问题就是非常的耗内存,如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc.

一、EasyExcel特点

EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,
64M内存1分钟内读取75M(46W行25列)的Excel(当然还有急速模式能更快,但是内存占用会在100M多一点)。
EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

不支持的功能

1、单个文件的并发写入、
2、读取读取图片
3、宏
4、csv读取(这个后续可能会考虑)

三、常见问题

1、读取文件务必使用2.0.5+(现在项目中用的是2.2.10)
2、读写反射对象用到了Cglib动态代理,所以成员变量必须符合驼峰规范,而且使用@Data不能使用@Accessors(chain = true)。后续会考虑支持非驼峰。
3、出现 NoSuchMethodException, ClassNotFoundException, NoClassDefFoundError。极大概率是jar冲突,建议clean项目,或者统一poi 的版本,理论上来说easyexcel兼容poi的3.17,4.0.1,4.1.0所有较新版本
4、用String去接收数字,出现小数点等情况这个是BUG,但是很难修复,后续版本会修复这个问题。目前请使用@NumberFormat注解,里面的参数就是调用了java自带的NumberFormat.format方法,不知道怎么入参的可以自己网上查询。
easyExcel的官方文档地址:https://alibaba-easyexcel.github.io/index.html

四、常用注解

4-1、读

ExcelProperty 指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。

@Getter
@Setter
@EqualsAndHashCode 
public class IndexOrNameData{

//强制读取第三个这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去山配*
@ExcelProperty(index = 2)
private Double doubleData

/*用名字去匹配,这里需要注意,如果名字重复会导致只有一个字殷读取到数据@ExcelProperty ("字符串标题”) */
private Stringstring;

@ExcelProperty ("日期标题") 
private Date date;
}

ExcelIgnore 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

//强制读取第三个这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去山配*
@ExcelIgnore
private Double doubleData

DateTimeFormat 日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat。

@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
private String date;

NumberFormat 数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat。

@NumberFormat("#.##%") 
private String doubleData; //接收百比的数字

4-2、写

ExcelProperty index 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头
ExcelIgnore 默认所有字段都会写入excel,这个注解会忽略这个字段
DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat
NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat
ExcelIgnoreUnannotated 默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

五、EasyExcel的使用

1、依赖

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

2、读excel

java easyexcel,java,excel,开发语言

2.1最简单的

对象

@Data
public class DemoData {    
private String string;    
private Date date;    
private Double doubleData;
}

controller类

@PostMapping("/outstoragcExce1")
@Apioperation("读取出库excel表")
public DeviceResponse storageservice(@RequestBody MultipartFile file) {
	try{
		storageservice.storageservice(file);
		} catch (Exception e){
	return new DeviceResponse(Constant.FAIL CODE,"出库导失败");
	}
	return new DeviceResponse(Constant.SUCCESS CODE,"出库导入成功");
}

service实现类

@Autowired
private StorageService storageServicel
@override
publil void slorageservice(MulliparlFile file) {
  Tnnutstream is = null:
  try{
     is=file.getInputstream();
  } catch (IDException e){
     e.printstackTrace();
  }
  //1.进行读取数数据,slorageReLrieval是我的puju类,
  //2.new Soragelistenpr(storagpServire)这个是监听器,主要用来i取数据的,别急后面会讲
  //3.特别注意的是storageservice这个service,我上面有注入进去 @Autowired,切记不要new会报错
  EasyExcel.read(is,StorageRetrieval.class, new Soragelisterer(storageService))sheet().doRead();
}

SorageListener监听器

@Component
public class SorageListener extends AnalysisEventListener<pojo类> {

    private static final Logger LOGGER = LoggerFactory.getLogger(SorageListener.class);
    //读取数据初始化值
    private static final int BATCH_COUNT = 50;
    List<pojo类> list = new ArrayList<pojo类>();

    private StorageService storageService;

    public SorageListener() {
        storageService=new StorageServiceImpl();
    }
 
    public SorageListener(StorageService storageService) {
        this.storageService = storageService;
    }

    /**
     * 这个每一条数据解析都会来调用,数据是一条一条进行解析的
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(StorageRetrieval data, AnalysisContext context) {
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }
/**
     * 所有excel表中数据解析完成了 都会来调用这个
     * 解释为什么要保存数据?
     *初始化读取数量为50,表中信息已经加载完毕,,假设excel表中最后只剩下30行遗留数据,所以为了防止存在遗留数据 尽量判断下集合是否为空,不为空在进行存储(这是我的逻辑需要判断,如果不需要也可进行不判断)
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
      if(list.size()==0){
         return;
      }
        saveData();
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    public void saveData() {
        storageService.save(list); //代码实现类层保存数据
        LOGGER.info("存储数据库成功!");
    }
}
2.2、指定列的下标或者列名
@Data
public class IndexOrNameData {
    /**
     * 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
     */
    @ExcelProperty(index = 2)
    private Double doubleData;
    /**
     * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
     */
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
}
/**
 * 指定列的下标或者列名
 *
 * <p>1. 创建excel对应的实体对象,并使用{@link ExcelProperty}注解. 参照{@link IndexOrNameData}
 * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link IndexOrNameDataListener}
 * <p>3. 直接读即可
 */
@Test
public void indexOrNameRead() {
    String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
    // 这里默认读取第一个sheet
    EasyExcel.read(fileName, IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead();
}

3、写excel

3.1最简单的

java easyexcel,java,excel,开发语言
实体对象

@Data
@piModel(value = "年龄统计实体类”
public class FToWAgeStatisticalVo implements Serializable {
private static final long serialVersionUID = -7891558029837989473L;
@ApiModelProperty("区间")
@ExcelProperty(value = "区间")
private String ageGap;

@ApiModeLProperty("病例数”)
@ExcelProperty(value ="病例数)
private Integer casesNumber ;

@ApiModeProperty("密接数”)
@ExceProperty(value = "密接数”)
private Integer closeNumber ;
}

service实现

@Override
public void avestatisticalExcel(Httpservlethesponse resonse,FlowReionStatisticalParam flowReionStatisticalParam) throws Exception{
  //这里文件名如果涉及中文一定要使用URL编码,否则会乱码
  String fileName = URLEncoder.encode( s: "floWAgeStatistical.xlsx" StandardCharsets.UTF_8.toString());
  List<FloWAgeStatisticalVo> data = ageStatistical(flowRegionStatisticalParam);
  response.setContentType("application/force-download");
  response.setcharacterEncoding("utf-8");
  response.setHeader( s: "Content-Disposition", s1: "attachment;filename=" + fileName);
  EasyExcel.write(response.getoutputstream()FLoWAgeStatisticalVo.class)
    .autoclosestream(true)
    .exceType(ExcelTypeEnum.XLSX)
    .sheet( sheetName: "年龄统计表")
    .doWrite(data) ;
}
3.2、列宽、行高
@Data
@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
public class WidthAndHeightData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 宽度为50
     */
    @ColumnWidth(50)
    @ExcelProperty("数字标题")
    private Double doubleData;
}
3.3、合并单元格
@Getter
@Setter
@EqualsAndHashCode
// 将第6-7行的2-3列合并成一个单元格
// @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
public class DemoMergeData {
    // 这一列 每隔2行 合并单元格
    @ContentLoopMerge(eachRow = 2)
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
}
/**
  * 合并单元格
  * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
  * <p>2. 创建一个merge策略 并注册
  * <p>3. 直接写即可
  */
 @Test
 public void mergeWrite() {
     String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
     // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
     LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
     // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
     EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板")
         .doWrite(data());
 }
3.4、复杂头写入

java easyexcel,java,excel,开发语言

@Data
@ApiModel("学校学生缺勤信息")
public class SchoolAnalyseVo {

    @ApiModelProperty("学校Id")
    @ExcelIgnore()
    private Long schoolId;

    @ExcelProperty("学校")
    private String schoolName;

    @ExcelProperty("学校类型")
    private String schoolType;
     ..........

    @ExcelProperty({"症状", "发热"})
    private String fever;

    @ExcelProperty({"症状", "咳嗽"})
    private String cough;

    @ExcelProperty({"症状", "头痛"})
    private String headache;
    .........

    @ExcelProperty({"疾病","普通感冒", "人数"})
    private String commonColdNumber ;

    @ExcelProperty({"疾病","普通感冒", "因病缺勤率"})
    private String commonColdRate ;

    @ExcelProperty({"疾病","流感", "人数"})
    private String influenzaNumber;
    .........
}
3.5、日期、数字或者自定义格式转换

java easyexcel,java,excel,开发语言

@Data
public class ConverterData {
    /**
     * 我想所有的 字符串起前面加上"自定义:"三个字
     */
    @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)
    private String string;
    /**
     * 我想写到excel 用年月日的格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 我想写到excel 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题")
    private Double doubleData;
}

自定义转换器

public class CustomStringStringConverter implements Converter<String> {
    @Override
    public Class supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 这里读的时候会调用
     *
     * @param cellData
     * @param contentProperty
     * @param globalConfiguration
     * @return
     */
    @Override
    public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        return "自定义:" + cellData.getStringValue();
    }

    /**
     * 这里是写的时候会调用 不用管
     *
     * @param value
     * @param contentProperty
     * @param globalConfiguration
     * @return
     */
    @Override
    public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        return new CellData(value);
    }
}
3.6、指定写入列

java easyexcel,java,excel,开发语言

@Getter
@Setter
@EqualsAndHashCode
public class IndexData {
    @ExcelProperty(value = "字符串标题", index = 0)
    private String string;
    @ExcelProperty(value = "日期标题", index = 1)
    private Date date;
    /**
     * 这里设置3 会导致第二列空的
     */
    @ExcelProperty(value = "数字标题", index = 3)
    private Double doubleData;
}
3.7、其他读操作

https://www.yuque.com/easyexcel/doc/write

4、填充excel

4.1 最简单的填充

java easyexcel,java,excel,开发语言
对象

@Getter
@Setter
@EqualsAndHashCode
public class FillData{
private string name;
private double number;
private Date date;
}

代码

/*最简单的填充
* @since 2.1.1
*/
@Test
public void simpleFill() [
    // 模板注 用]来表示你要用的变量 如果本来就有””,”]”特殊字符 用””]"代替
    String templateFileName =TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx";
    // 方案1 根据对象填充
    String fileName = TestFileUtil,getPath() + "simpleFill" + System,currentTimeMillis() + ".xlsx",
    // 这里 会填充到第一个sheet, 然后文件流会自动关闭
    FillData fillData = new FillData();
    fillData.setName("张一");
    fillData.setNumber(5.2);
    EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
    // 方案2 根据Map填充
    fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"
    // 这里 会填充到第一个sheet, 然后文件流会自动关闭
    Map<string, Object> map = new HashMap<string, Object>();
    map.put("name”,"张二");
    map .put("number", 5.2) :
    EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
}
4.2、其他填充

填充列表、复杂的填充、数据量大的复杂填充、横向的填充、多列表组合填充填充
https://www.yuque.com/easyexcel/doc/fill文章来源地址https://www.toymoban.com/news/detail-618338.html

到了这里,关于java实现excel的导出之使用easyExcel的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用EasyExcel实现excel导出,支持百万大数据量导出-----超简单

    通过设置sheet数量,完成分批导出,每个sheet存100万数据,每次查询插入20万数据,避免超时,内存溢出等问题,可以根据服务器配置调整参数设置。 1.引入依赖 2.创建对应的实体类 @ExcelProperty设置的就是导出的列名,还可以设置排序等等 3.核心导出代码 4.配置类 至此就完成导

    2024年02月11日
    浏览(62)
  • 使用POI和EasyExcel来实现excel文件的导入导出

    废话不多说咱们直接上干货!!!! 一.读取Excel表格 【1】使用POI读取excel表格中的数据 POI还可以操作我们这个word文档等等,他不仅仅只能弄Excel,而JXI只能操作excel 1.POI的结构,我们可以更具文件的类去选择 相关的对象我当前是使用的XLSX来操作的 HSSF - 提供读写Microsoft

    2024年02月05日
    浏览(59)
  • Java 导出Excel表格生成下拉框-EasyExcel

     

    2024年02月11日
    浏览(51)
  • 【JAVA】easyexcel 导出excel文件带多个图片

    最终效果  pom版本 实现代码  

    2024年02月16日
    浏览(36)
  • 【Java结合EasyExcel,模板文件填充并导出Excel】

    需求描述: 客户网页上填一个Excel表格,数据存到数据库,这个导出接口要做的就是从数据库中的获取数据并填充到模板文件,最后通过response返给前端一个下载链接,用户即可获取填充好的Excel文件。 方案一: 一开始使用的是easypoi,发现当填充一行数据时是OK的,但是如果

    2024年02月09日
    浏览(58)
  • EasyExcel实现Excel文件导入导出功能

    Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。 EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。

    2024年02月02日
    浏览(68)
  • Java 使用 EasyExcel 实现导入导出(新手篇教程)

    官网镇楼↓,觉得我写的不好的同学可以去官网看哦 EasyExcel 示例: 如上一个简易 Excel 表格,表头占了两行,且第三列开始才为有效数据,那么我们应该如何导入? 建造实体类 首先无论是导入还是导出,都需要先建对应的实体类  如图所示,因为我的示例 Excel 一共需要读

    2024年04月17日
    浏览(41)
  • 使用easyexcel填充模板数据,并导出excel

    导出excel功能非常场景,本片文章记录如何使用模板填充数据后再导出。因直接导出excel数据样式不符合要求,所以做了模板填充然后再导出excel。 效果如下: 注意:列表数据变量名前面要写点{.id},如果单条数据可以不写。 使用表单提交: 实体代码: controller代码: 只对je

    2024年03月11日
    浏览(53)
  • SpringBoot 集成 EasyExcel 3.x 实现 Excel 导出

    目录   EasyExcel官方文档 EasyExcel是什么? EasyExcel注解  springboot集成EasyExcel 简单入门导出 : 实体类  自定义转换类 测试一下 复杂表头一对多导出 :   自定义注解 定义实体类 自定义单元格合并策略  测试一下     EasyExcel官方文档 EasyExcel官方文档 - 基于Java的Excel处理工具

    2024年02月13日
    浏览(56)
  • Java根据excel模版导出Excel(easyexcel、poi)——含项目测试例子拿来即用

    一般列表导出以及个性化样式设置请看下面的文章: JAVA导出Excel通用工具类——第一篇:详细介绍POI 导出excel的多种复杂情况,包括动态设置筛选、动态合并横向(纵向)单元格等多种复杂情况. JAVA导出Excel通用工具——第二篇:使用EasyExcel导出excel的多种情况的例子介绍.

    2024年04月29日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包