EasyExcel导入、导出数据

EasyExcel

官方解析

Java解析、生成Excel比较有名的框架有Apache poijxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。
easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便

网站

  • 官方网站:https://easyexcel.opensource.alibaba.com/
  • github地址:https://github.com/alibaba/easyexcel
  • gitee地址:https://gitee.com/easyexcel/easyexcel

写Excel

最简单写

示例

模板对象

@Data
@EqualsAndHashCode
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private String dateTime;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

插入值

private List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

开始写

/**
     * 最简单的写
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 直接写即可
     */
    @Test
    public void simpleWrite() {
        // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入
        // 写法1 JDK8+
        // since: 3.0.0-beta1
        String path = "D:\\excel\\";
        String fileName = path + "simpleWrite.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
        System.out.println("excel导出成功");
    }

根据参数只导出指定列

示例:排除导出日期时间列

模板对象和插入值和以上一致

开始写

@Test
    public void excludeOrIncludeWrite() {
        String path = "D:\\excel\\";
        String fileName = path + "excludeOrIncludeWrite" + ".xlsx";
        // 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,
        // 而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。
        // 根据用户传入字段 假设我们要忽略 date
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        //将不想导出的列放到一个集合中
        excludeColumnFiledNames.add("dateTime");
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFiledNames).sheet("模板")
                .doWrite(data());
        System.out.println("excel导出成功");
    }

指定写入的列

①、使用index格式

示例:使用index会出现空列情况

模板对象

//index,不会忽略空列,在第几列就是第几列。
@Data
@EqualsAndHashCode
public class IndexData {
    @ExcelProperty(value = "字符串标题", index = 0)
    private String string;
    @ExcelProperty(value = "日期标题", index = 1)
    private String dateTime;
    /**
     * 这里设置3 会导致第二列空的
     */
    @ExcelProperty(value = "数字标题", index = 3)
    private Double doubleData;
}

插入值

private List<IndexData> data() {
        List<IndexData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            IndexData data = new IndexData();
            data.setString("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

开始写

/**
     * 指定写入的列
     * <p>1. 创建excel对应的实体对象 参照{@link IndexData}
     * <p>2.
     * <p>3. 直接写即可
     */
    @Test
    public void indexWrite() {
        String path = "D:\\excel\\";
        String fileName = path + "indexWrite" + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());
    }

②、使用order格式

示例:使用order格式不会出现空列情况

模板对象

//order,不会出现空列情况
@Data
@EqualsAndHashCode
public class OrderData {
    @ExcelProperty(value = "字符串标题", order = 0)
    private String string;
    @ExcelProperty(value = "日期标题", order = 1)
    private String dateTime;
    /**
     * 这里设置3 不会出现空列情况
     */
    @ExcelProperty(value = "数字标题", order = 3)
    private Double doubleData;
}

插入值

private List<OrderData> data() {
        List<OrderData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            OrderData data = new OrderData();
            data.setString("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

开始写

/**
     * 指定写入的列
     * <p>1. 创建excel对应的实体对象 参照{@link OrderData}
     * <p>2.
     * <p>3. 直接写即可
     */
    @Test
    public void OrderWrite() {
        String path = "D:\\excel\\";
        String fileName = path + "OrderWrite" + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, OrderData.class).sheet("模板").doWrite(data());
    }

复杂头写入

类似类似插入单元格

示例

模板对象

@Getter
@Setter
@EqualsAndHashCode
public class ComplexHeadData {
    @ExcelProperty({"主标题", "字符串标题"})
    private String string;
    @ExcelProperty({"主标题", "日期标题"})
    private Date date;
    @ExcelProperty({"主标题", "数字标题"})
    private Double doubleData;
}

插入值

private List<ComplexHeadData> data() {
        List<ComplexHeadData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            ComplexHeadData data = new ComplexHeadData();
            data.setString("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

开始写

/**
     * 复杂头写入
     * <p>1. 创建excel对应的实体对象 参照{@link ComplexHeadData}
     * <p>2.
     * <p>3. 直接写即可
     */
    @Test
    public void complexHeadWrite() {
        String path = "D:\\excel\\";
        String fileName = path + "complexHeadWrite" + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());
    }

重复多次写入(写到单个或者多个Sheet)

①、写到同一个sheet

示例:同一个数据重复写了五次

模板对象

@Data
@EqualsAndHashCode
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private String dateTime;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

插入值

private List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

写到同一个sheet

/**
     * 重复多次写入
     * <p>
     * 1. 创建excel对应的实体对象
     * 3. 直接调用二次写入即可
     */
    @Test
    public void repeatedWrite() {
        // 方法1: 如果写到同一个sheet
        String path = "D:\\excel\\";
        String fileName = path + "repeatedWrite" + ".xlsx";
        // 这里 需要指定写用哪个class去写
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
            // 这里注意 如果同一个sheet只要创建一次
            WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
            // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
            for (int i = 0; i < 5; i++) {
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                List<DemoData> data = data();
                excelWriter.write(data, writeSheet);
            }
        }
    }

②、写到不同的sheet 同一个对象

示例

开始写入

// 方法2: 如果写到不同的sheet 同一个对象
        // 这里 指定文件
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
            // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
            for (int i = 0; i < 5; i++) {
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                List<DemoData> data = data();
                excelWriter.write(data, writeSheet);
            }
        }

③、写到不同的sheet 不同的对象

示例

开始写入

// 方法3 如果写到不同的sheet 不同的对象
        // 这里 指定文件
        try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {
            // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
            for (int i = 0; i < 5; i++) {
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class
                // 实际上可以一直变
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                List<DemoData> data = data();
                excelWriter.write(data, writeSheet);
            }
        }

日期、数字或者自定义格式转换

示例

模板对象

@Data
@EqualsAndHashCode
@Component
public class DemoData{
    @ExcelProperty(value = "字符串标题",index = 0)
    private String title;
    
    @ExcelProperty(value = "日期标题",index = 1)
    private String dateTime;

    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题",index = 2)
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

插入值

private List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setTitle("字符串" + i);
            data.setDateTime(new DateTime().toString("yyyy年MM月dd日HH时mm分ss秒"));
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

开始导入

/**
     * 日期、数字或者自定义格式转换
     * <p>3. 直接写即可
     */
    @Test
    public void converterWrite() {
        String path = "D:\\excel\\";
        String fileName = path + "converterWrite" + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    }

web中的写(实战篇)

实现用户数据导出

前端代码

<el-col :span="1.5">
        <el-button v-if="canAdd" type="primary" size="small" @click="handleExportExcel">导出<i class="el-icon-upload2"></i>
        </el-button>
      </el-col> 

methods:{
	handleExportExcel(){
      window.open("http://localhost:8800/shiyi/system/user/export")
    }
}

后端代码

导出模板数据

@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class UserDto implements Serializable {
    @ApiModelProperty(value = "用户账号")
    @ExcelProperty(value = {"用户信息数据","用户账号"},order = 0)
    private String username;

    @ApiModelProperty(value = "登录密码")
    @ExcelProperty(value = {"用户信息数据","登录密码"},order = 1)
    private String password;

    @ApiModelProperty(value = "状态")
    @ExcelProperty(value = {"用户信息数据","状态"},order = 2)
    private Integer status;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @ExcelProperty(value = {"用户信息数据","创建时间"},order = 3)
    private String createTime;

    @ApiModelProperty(value = "最后更新时间")
    @ExcelProperty(value = {"用户信息数据","最后更新时间"},order = 4)
    @TableField(fill = FieldFill.UPDATE)
    private String updateTime;

    @ApiModelProperty(value = "最后登录时间")
    @ExcelProperty(value = {"用户信息数据","最后登录时间"},order = 5)
    @TableField(fill = FieldFill.UPDATE)
    private String lastLoginTime;

    @ApiModelProperty(value = "IP地址")
    @ExcelProperty(value = {"用户信息数据","IP地址"},order = 6)
    private String ipAddress;

    @ApiModelProperty(value = "IP来源")
    @ExcelProperty(value = {"用户信息数据","IP来源"},order = 7)
    private String ipSource;

    @ApiModelProperty(value = "登录系统")
    @ExcelProperty(value = {"用户信息数据","登录系统"},order = 8)
    private String os;

    @ApiModelProperty(value = "浏览器")
    @ExcelProperty(value = {"用户信息数据","浏览器"},order = 9)
    private String browser;
}

数据的值从数据库中查询得到

开始导出

public void export(HttpServletResponse response) throws IOException {
        //文件需要设置成StandardCharsets.ISO_8859_1编码,否则导出的excel文件名乱码
        String excelName = new String("用户信息数据.xlsx".getBytes(), StandardCharsets.ISO_8859_1);
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-disposition", "attachment;filename=" + excelName );
    	//从数据库查询所有用户数据
        List<User> userList = baseMapper.selectList(null);

        List<UserDto> userDtoList = new ArrayList<>();
        //数据格式化
        userList.stream().forEach(user -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date cTime = user.getCreateTime();
            Date uTime = user.getUpdateTime();
            Date lTime = user.getLastLoginTime();
            //日期格式化
            String createTime = simpleDateFormat.format(cTime);
            String updateTime = simpleDateFormat.format(uTime);
            String lastLoginTime = simpleDateFormat.format(lTime);

            UserDto userDto = new UserDto();
            userDto.setBrowser(user.getBrowser());
            userDto.setUsername(user.getUsername());
            userDto.setPassword(user.getPassword());
            userDto.setIpAddress(user.getIpAddress());
            userDto.setIpSource(user.getIpSource());
            userDto.setOs(user.getOs());
            userDto.setStatus(user.getStatus());
            userDto.setCreateTime(createTime);
            userDto.setUpdateTime(updateTime);
            userDto.setLastLoginTime(lastLoginTime);
            userDtoList.add(userDto);
        });
        ServletOutputStream outputStream = response.getOutputStream();
        EasyExcel.write(outputStream, UserDto.class)
                .sheet("user")
                .doWrite(userDtoList);
    	
    }

controller层

@GetMapping("/export")
@ApiOperation(value = "导出用户数据", httpMethod = "GET", response = ResponseResult.class, notes = "导出用户数据")
    public void excel(HttpServletResponse response) throws IOException {
        userService.export(response);
    }

浏览器直接访问:http://localhost:端口号/export

读Excel

实现用户数据导入

web中的读(实战篇)

模板对象

@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class UserDto implements Serializable {
    @ApiModelProperty(value = "用户账号")
    @ExcelProperty(value = {"用户信息数据","用户账号"},order = 0)
    private String username;

    @ApiModelProperty(value = "登录密码")
    @ExcelProperty(value = {"用户信息数据","登录密码"},order = 1)
    private String password;

    @ApiModelProperty(value = "状态")
    @ExcelProperty(value = {"用户信息数据","状态"},order = 2)
    private Integer status;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    @ExcelProperty(value = {"用户信息数据","创建时间"},order = 3)
    private String createTime;

    @ApiModelProperty(value = "最后更新时间")
    @ExcelProperty(value = {"用户信息数据","最后更新时间"},order = 4)
    @TableField(fill = FieldFill.UPDATE)
    private String updateTime;

    @ApiModelProperty(value = "最后登录时间")
    @ExcelProperty(value = {"用户信息数据","最后登录时间"},order = 5)
    @TableField(fill = FieldFill.UPDATE)
    private String lastLoginTime;

    @ApiModelProperty(value = "IP地址")
    @ExcelProperty(value = {"用户信息数据","IP地址"},order = 6)
    private String ipAddress;

    @ApiModelProperty(value = "IP来源")
    @ExcelProperty(value = {"用户信息数据","IP来源"},order = 7)
    private String ipSource;

    @ApiModelProperty(value = "登录系统")
    @ExcelProperty(value = {"用户信息数据","登录系统"},order = 8)
    private String os;

    @ApiModelProperty(value = "浏览器")
    @ExcelProperty(value = {"用户信息数据","浏览器"},order = 9)
    private String browser;
}

开始导入

//用户数据导入
    @Override
    public void excelImport(MultipartFile file) throws IOException {
        List<UserDto> list = new ArrayList<>();
        EasyExcel.read(file.getInputStream(), UserDto.class, new PageReadListener<UserDto>(dataList -> {
            for (UserDto demoData : dataList) {
                //将JSON对象转换成实体类
                UserDto entity = JSONObject.parseObject(JSONObject.toJSONString(demoData), UserDto.class);
                list.add(entity);
            }
        })).sheet().doRead();
        //将导入的用户数据保存到数据库中
        list.stream().forEach(userDto ->{
            //设置值
            UserInfo userInfo = new UserInfo();
            userInfo.setAvatar("http://img.shiyit.com/66bb121d47e94b89945d29bb6e3e6cab.jpg");
            userInfo.setIntro("游客");
            String nickname = "游客" + RandomUtils.generationCapital(4) + RandomUtils.generationNumber(6);
            userInfo.setNickname(nickname);
            //用户信息绑定
            userInfoMapper.insert(userInfo);

            //查询获取userInfoId
            LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserInfo::getNickname,nickname);
            UserInfo selectOne = userInfoMapper.selectOne(wrapper);
            Integer userInfoId = selectOne.getId();

            User user = new User();
            user.setUsername(userDto.getUsername());
            //密码加密
            user.setPassword(AesEncryptUtils.aesEncrypt(userDto.getPassword()));
            user.setStatus(userDto.getStatus());
            user.setRoleId(2);
            user.setLoginType(1);
            user.setUserInfoId(userInfoId);
            user.setOs(userDto.getOs());
            user.setIpAddress(userDto.getIpAddress());
            user.setIpSource(userDto.getIpSource());
            user.setBrowser(userDto.getBrowser());
            userService.save(user);
        });
    }

//PageReadListener此监听器可以自己实现,这里用的是官方封装好的。

Controller层

@PostMapping("/import")
@ApiOperation(value = "导入用户数据", httpMethod = "GET", response = ResponseResult.class, notes = "导入用户数据")
    public ResponseResult excelImport(MultipartFile file) throws IOException {
        userService.excelImport(file);
        return ResponseResult.success();
    }
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于EasyExcel库,我们可以使用它来实现数据导入导出。下面是一个示例代码,演示了如何使用EasyExcel进行数据导入导出: ```java import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; import com.alibaba.excel.support.ExcelTypeEnum; import java.util.ArrayList; import java.util.List; public class EasyExcelDemo { public static void main(String[] args) { // 导出数据 exportData(); // 导入数据 importData(); } private static void exportData() { // 准备数据 List<User> userList = new ArrayList<>(); userList.add(new User("张三", 20)); userList.add(new User("李四", 25)); // 导出文件路径 String exportFilePath = "D:/users.xlsx"; // 设置表头 Table table = new Table(0); table.setHead(User.getHead()); // 写入数据Excel文件 ExcelWriter excelWriter = EasyExcel.write(exportFilePath, User.class).excelType(ExcelTypeEnum.XLSX).build(); Sheet sheet = new Sheet(1, 0, User.class); sheet.setSheetName("用户信息"); excelWriter.write(userList, sheet, table); excelWriter.finish(); } private static void importData() { // 导入文件路径 String importFilePath = "D:/users.xlsx"; // 读取Excel文件并转换为对象列表 List<User> userList = EasyExcel.read(importFilePath).head(User.class).sheet().doReadSync(); // 输出导入数据 for (User user : userList) { System.out.println(user); } } static class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public static List<String> getHead() { List<String> head = new ArrayList<>(); head.add("姓名"); head.add("年龄"); return head; } // 省略 getter 和 setter 方法 @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } } ``` 上述示例代码中,我们先定义了一个 `User` 类作为数据的实体类,然后使用EasyExcel库进行数据导出导入。在导出数据的部分,我们首先准备了一个用户列表 `userList`,然后指定导出的文件路径 `exportFilePath`,接着设置表头信息,最后使用 `ExcelWriter` 将数据写入到Excel文件中。在导入数据的部分,我们指定导入的文件路径 `importFilePath`,然后使用 `EasyExcel.read()` 方法读取Excel文件,并使用 `doReadSync()` 方法将Excel数据转换为对象列表。 请注意,上述示例代码中使用的是EasyExcel的最新版本,你需要在你的项目中添加相应的依赖。你可以通过访问EasyExcel的官方网站来获取更多关于EasyExcel库的信息和文档:[https://www.yuque.com/easyexcel/doc/easyexcel](https://www.yuque.com/easyexcel/doc/easyexcel)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

six-key

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值