EasyPOI使用详解

EasyPOI

简介

easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法
文档:http://easypoi.mydoc.io/#category_50222

环境搭建

# 1.引入相关依赖
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>      

相关注解

# 1.注解说明
- easypoi起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model--row,filed--col 这样利用注解我们可以和容易做到excel到导入导出经过一段时间发展,现在注解有5个类分别是
  • @Excel 作用到filed上面,是对Excel一列的一个描述
  • @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
  • @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
  • @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导出
  • @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
@ExcelTarget
# 1.说明
- 用在实体类上标识是一个可以通过EasyPOI导入导出的实体类
- 相关属性:
value: [String][定义id唯一标识,不能重复] `常用`
height: [Double][定义单元格高度]
fontSize: [short ][定义单元格字体大小]
# 2.使用
@ExcelTarget("users")
public class User implements Serializable {
//..... 省略属性 相关GET,SET方法
}
@Excel
# 1.说明
- 用在filed(属性)上面,是对Excel一列的一个描述
- 常用属性:
name : [String][生成Excel表格中列名]
needMerge: [boolean][是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)]
orderNum : [String][指定生成Excel中列的顺序,按照数字自然顺序排序]
savePath : [String][指定导入Excel中图片的保存路径]
type : [String][导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本]
width : [Double][指定导出Excel时列的宽度]
isImportField: [boolean][是否是导入字段,如果没有说明是错误的Excel]
exportFormat: [String][导出Excel的时间格式]
importFormat: [String][导入Excel的时间格式]
format : [String][相当于同时设置了exportFormat和importFormat]
imageType: [int ][导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的]
suffix : [String][文字后缀,如% ,90 变成90%]
replace:[String[]][替换,用法:{"a_1","b_2"},a指的是要替换的内容,1指的被替换的数据(把数据库为1的替换为a,把2替换为b)]
public class User implements Serializable {
@Excel(name="编号",orderNum="1",replace = {"第一份_1","第二份_2"})
private String id;
@Excel(name="姓名",orderNum="2")
private String name;
@Excel(name="年龄",orderNum="4",suffix = " $")
private Integer age;
@Excel(name="生日",orderNum = "3",width = 20.0,exportFormat = "yyyy年MM月dd日")
private Date bir;
//...省略GET、SET方法
}
@ExcelTarget("emp")
@Data
public class Emp implements Serializable {
    // name要和excel的标题一致
    @Excel(name="编号")
    private Integer id;
    @Excel(name="姓名")
    private String name;
    @Excel(name="年龄" )
    private Integer age;
    @Excel(name = "生日",format = "yyyy-MM-dd")
    private Date birthday;
    @Excel(name = "状态",replace = {"可用_0","不可用_1"})//replace:替换
    private String status;
    //图片  type:标识导入导出类型为图片,savePath:图片保存的位置
    @Excel(name = "头像",type = 2,savePath = "C:/Users/1/IdeaProjects/easypoi/src/main/resources/static")
    private String image;
}
@ExcelEntity
# 1.说明
- 标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透
- 常用属性:
name: [String][定义唯一标识]
@ExcelTarget("users")
public class User implements Serializable {
    //... 省略GET SET和其他属性
    @ExcelEntity(name="身份信息")
    private Card card;
}
@ExcelTarget("card")
public class Card implements Serializable {
    @Excel(name="身份证号",orderNum = "6")
    private String id;
    @Excel(name="家庭住址",orderNum = "7")
    private String address;
}
@ExcelCollection
# 1.说明
- 一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
- 常用属性:
name : [String][定义集合列名]
orderNum: [int][用来指定导出excel集合内列的顺序]
type : [Class\<?>][用来指定导出是创建对象类型]
@ExcelTarget("users")
public class User implements Serializable {
    //....省略GET SET其他属性
    @ExcelCollection(name="订单",orderNum = "5")
    private List<Order> orders;
}
@ExcelTarget("orders")
public class Order implements Serializable {
    //....省略GET SET方法
    @Excel(name = "订单编号")
    private String id;
    @Excel(name = "订单名称")
    private String name;
}
@ExcelIgnore
# 1.说明
- 用在属性上,导出Excel时忽略这个属性

导出Excel

1.导出基本数据
注意:导出Excel的对象必须实现对象序列化接口
# 1.定义对象
@ExcelTarget("users")
public class User implements Serializable {
    @Excel(name="编号",orderNum="1",replace = {"xxx_1","nnn_2"})
    private String id;
    @Excel(name="姓名",orderNum="2")
    private String name;
    @Excel(name="年龄",orderNum="4",suffix = " $")
    private Integer age;
    @Excel(name="生日",orderNum = "3",width = 20.0,exportFormat = "yyyy年MM月dd日")
    private Date bir;
    //省略GET、SET方法。。。
}
# 2.定义测试数据
//测试数据
public static List<User> getUsers(){
    List<User> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(String.valueOf(i));
        user.setName("小陈");
        user.setAge(20+i);
        user.setBir(new Date());
        users.add(user);
    }
    return users;
}
# 3.导出Excel
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表","测试"),User.class,getUsers());
FileOutputStream outputStream = new FileOutputStream("/Users/chenyannan/Desktop/aa.xls");
workbook.write(outputStream);
outputStream.close();
workbook.close();
# 4.查看Excel

2.导出指定字段
//@Excel(name="年龄",orderNum="4",suffix = " $")
@ExcelIgnore
private Integer age;
3.导出list集合
# 1.说明
- 往往有时候导出的对象中含有数组或者集合,需要导出这样的数据可以直接使用@Excel进行导出
@ExcelTarget("users")
public class User implements Serializable {
    @Excel(name="爱好",orderNum = "5",width = 20.0)
    private List<String> habbys;
    //....
}
# 2.说明
- 从上面运行结果可以看出,导出的格式默认是上述图片中格式,如果需要自定义导出格式怎么办?
- 自定义导出格式可以在对应的set方法中进行处理即可
@ExcelTarget("users")
public class User implements Serializable {
    @ExcelIgnore //忽略原始list集合
    private List<String> habbys;
    @Excel(name="爱好",orderNum = "5",width = 20.0)
    private String habbysstr; //定义一个list集合字符串,用来存储集合数据
    public String getHabbysstr(){ //修改get方法
        StringBuilder sb = new StringBuilder();
        this.habbys.forEach(s->sb.append(s).append("、"));
        return sb.toString();
    }
}
# 3.导出查看结果

3.导出对象中含有对象
# 1.说明
- 导出对象中含有对象的Excel
@ExcelTarget("users")
public class User implements Serializable {
    @ExcelEntity(name="card") //定义对象
    private Card card;
    //.....
}
@ExcelTarget("card")
public class Card implements Serializable {
    @Excel(name="身份证号",orderNum = "6")
    private String id;
    @Excel(name="家庭住址",orderNum = "7")
    private String address;
}
# 2.为导出对象赋值
//测试数据
public static List<User> getUsers(){
    List<User> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(String.valueOf(i));
        user.setName("小陈");
        user.setAge(20+i);
        user.setBir(new Date());
        user.setHabbys(Arrays.asList("看书","听歌","打篮球"));
        user.setCard(new Card("11000103422323212342","北京市朝阳区"));
        users.add(user);
    }
        return users;
}
# 3.导出Excel
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表","测试"),User.class,getUsers());
FileOutputStream outputStream = new FileOutputStream("/Users/chenyannan/Desktop/aa.xls");
workbook.write(outputStream);
outputStream.close();
workbook.close();

4.导出一对多关系
# 1.说明
- 往往在业务比较复杂时,我们需要导出一对多关联关系处理,如 导出学生课程信息,导出用户的所有订单信息等等....
- 在Easypoi中如何处理一对多关系呢?
@ExcelTarget("users")
public class User implements Serializable {
    //......
    @ExcelCollection(name="订单信息",orderNum="8")
    private List<Order> orders; //定义集合
}
@ExcelTarget("orders")
public class Order implements Serializable {
    @Excel(name = "订单编号")
    private String id;
    @Excel(name = "订单名称")
    private String name;
}
# 2.测试数据
//测试数据
public static List<User> getUsers(){
    List<User> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(String.valueOf(i));
        user.setName("小陈");
        user.setAge(20+i);
        user.setBir(new Date());
        user.setHabbys(Arrays.asList("看书","听歌","打篮球"));
        user.setCard(new Card("11000103422323212342","北京市朝阳区"));
        user.setOrders(Arrays.asList(new Order("1","超短裙"), new Order("2","iphone X")));
        users.add(user);
    }
    return users;
}
# 3.导出Excel
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表","测试"),User.class,getUsers());
FileOutputStream outputStream = new FileOutputStream("/Users/chenyannan/Desktop/aa.xls");
workbook.write(outputStream);
outputStream.close();
workbook.close();

5.导出图片
# 1.说明
- 往往随着业务不断变化,可能需要在导出excel时将图片信息也一并导出,如商品图标,用户头像信息等数据,这个时候easypoi该如何处理呢?
@ExcelTarget("users")
public class User implements Serializable {
    //.....
    @Excel(name="头像信息",type = 2,orderNum = "0",width = 12,height = 12)//type的值一定要指定为2
    private String photo;//定义头像 直接写指定图片路径
}
# 2.准备图片放入指定路径中,并在测试数据中进行赋值
//测试数据
public static List<User> getUsers(){
    List<User> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(String.valueOf(i));
        user.setName("小陈");
        user.setAge(20+i);
        user.setBir(new Date());
        user.setHabbys(Arrays.asList("看书","听歌","打篮球")); //设置爱好
        user.setCard(new Card("11000103422323212342","北京市朝阳区"));//设置对象
        user.setOrders(Arrays.asList(new Order("1","超短裙"), new Order("2","iphone X")));//设置集合
        user.setPhoto("/Users/chenyannan/Desktop/1.jpeg");//设置头像
        users.add(user);
    }
    return users;
}
# 3.导出Excel查看结果

6.大数据量导出
# 1.说明
- 大数据导出是当我们的导出数量在几万,到上百万的数据时,一次从数据库查询这么多数据加载到内存然后写入会对我们的内存和CPU都产生压力,这个时候需要我们像分页一样处理导出分段写入Excel缓解Excel的压力
Workbook workbook1 = ExcelExportUtil.exportBigExcel(new ExportParams("用户列表", "测试"), User.class, getUsers());
workbook1.write(outputStream);
ExcelExportUtil.closeExportBigExcel();
注意:最好大量数据进行分页处理,每次导出数据最好不要超过1W条记录

导入Excel

1.导入基本数据
# 0.准备导入的目标Excel
# 1.定义导出数据基本对象
- 为了节省篇幅,一下代码统一忽略getter,setter
public class Student implements Serializable {
    @Excel(name="编号")
    private String id;
    @Excel(name="姓名")
    private String name;
    @Excel(name="年龄")
    private Integer age;
    @Excel(name="生日",format = "yyyy年MM月dd日")
    private Date bir;
}
# 2.导入excel中数据
@Test
public void test(){
    //定义导入参数
    ImportParams importParams = new ImportParams();
    importParams.setTitleRows(1);
    importParams.setHeadRows(1);
    //导出数据 餐数1:当如excel文件 参数2:导入对象的类型 参数3:导入参数配置
    List<Student> students = ExcelImportUtil.importExcel(new File("/Users/chenyannan/Desktop/student.xls"),              Student.class,importParams);
    students.forEach(s-> System.out.println(s));
}
# 3.查看导入结果

2.导入小技巧
# 1.技巧说明
- 读取指定的sheet
比如要读取上传得第二个sheet 那么需要把startSheetIndex = 1 就可以了
- 读取几个sheet
比如读取前2个sheet,那么 sheetNum=2 就可以了
- 读取第二个到第五个sheet
设置 startSheetIndex = 1 然后sheetNum = 4
- 读取全部的sheet
sheetNum 设置大点就可以了
- 判断一个Excel是不是合法的Excel
importFields 设置下值,就是表示表头必须至少包含的字段,如果缺一个就是不合法的excel,不导入
3.带图片导入
# 0.准备数据
# 1.说明
- 有图片的导出就有图片的导入,导入的配置和导出是一样的,但是需要设置保存路径
public class Student implements Serializable {
    @Excel(name="编号")
    private String id;
    @Excel(name="姓名")
    private String name;
    @Excel(name="年龄")
    private Integer age;
    @Excel(name="生日",format = "yyyy年MM月dd日")
    private Date bir;
    @Excel(name="头像信息",type = 2,savePath = "/Users/chenyannan/IdeaProjects/180codes/baizhimail/src/main/webapp")
    private String photo;
}
# 2.导入Excel
@Test
public void test(){
    //定义导入参数
    ImportParams importParams = new ImportParams();
    importParams.setTitleRows(1);
    importParams.setHeadRows(1);
    importParams.setImportFields(new String[]{"生日"});
    importParams.setNeedSave(false);//是否保存上传的excel
    importParams.setSaveUrl("/Users/chenyannan/IdeaProjects/180codes/baizhimail/src/main/webapp");
    //导出数据 餐数1:当如excel文件 参数2:导入对象的类型 参数3:导入参数配置
    List<Student> students = ExcelImportUtil.importExcel(new File("/Users/chenyannan/Desktop/students.xls"),           Student.class,importParams);
    students.forEach(s-> System.out.println(s));
}
# 3.测试导入结果

集成web实现导入导出

1.搭建springboot+mybatis项目环境
# 1.创建springboot项目
# 2.引入相关依赖
- mybatis
- mysql
- druid
- easypoi
- 引入thymelaf
<!--引入mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--引入mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--引入druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<!--引入thymelaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--引入easypoi-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
# 3.编写配置文件
server.port=8989
spring.application.name=easypoi
spring.thymeleaf.cache=false
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/easypoi?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
mybatis.mapper-locations=classpath:com/baizhi/mapper/*.xml
mybatis.type-aliases-package=com.baizhi.entity
# 4.创建包结构
# 5.启动项目检测环境搭建是否成功

2.开发测试页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>导入excel的主页面</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
                <h1>选择Excel文件导入到数据中</h1>
                <form action="" method="post" class="form-inline">
                    <div class="form-group">
                        <input class="form-control" type="file" name="excelFile">
                        <input type="submit" class="btn btn-danger" value="导入数据">
                    </div>
                </form>
            </div>
            <div class="col-md-12">
                <h1>显示导入数据列表</h1>
                <table class="table table-bordered" >
                    <tr>
                        <th>编号</th>
                        <th>头像</th>
                        <th>姓名</th>
                        <th>年龄</th>
                        <th>生日</th>
                    </tr>
                    <tr>
                        <td>1</td>
                        <td><img src="" alt=""></td>
                        <td>小陈</td>
                        <td>23</td>
                        <td>2012-12-12</td>
                    </tr>
                    <tr>
                        <td>1</td>
                        <td><img src="" alt=""></td>
                        <td>小陈</td>
                        <td>23</td>
                        <td>2012-12-12</td>
                    </tr>
                </table>
                <hr>
                <input type="button" class="btn btn-info" value="导出excel">
            </div>
        </div>
    </div>
</body>
</html>

3.查询所有
# 0.准备数据Excel
# 1.根据Excel抽取库表结构
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`bir` timestamp NULL DEFAULT NULL,
`photo` varchar(150) DEFAULT NULL,
`habbys` varchar(100) DEFAULT NULL,
`cardno` varchar(18) DEFAULT NULL,
`address` varchar(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
# 2.创建实体类
@Data
@ExcelTarget("users")
public class User implements Serializable {
    @Excel(name="编号")
    private String id;
    @Excel(name="姓名")
    private String name;
    @Excel(name="生日",format = "yyyy年MM月dd日")
    private Date bir;
    @Excel(name="头像信息",type = 2,savePath =                "/Users/chenyannan/IdeaProjects/180codes/easypoi/src/main/resources/static/imgs")
    private String photo;
    @Excel(name="爱好",width = 12.0)
    private String habbys;
    @Excel(name="身份证号",width = 15.0)
    private String cardno;
    @Excel(name="家庭住址",width = 15.0)
    private String address;
}
# 3.创建DAO接口
@Mapper
public interface UserDAO {
    //查询所有
    List<User> findAll();
}
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDAO">
    <!--查询所有-->
    <select id="findAll" resultType="User">
        select id,name,bir,photo,habbys,cardno,address from t_user
    </select>
</mapper>
# 4.创建Service接口&实现
public interface UserService {
    List<User> findAll();
}
@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;
    @Override
    public List<User> findAll() {
        return userDAO.findAll();
    }
}
# 5.创建Controller完成查询所有
@Controller
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;
    //查询所有
    @RequestMapping("/findAll")
    public String findAll(HttpServletRequest request){
        List<User> users = userService.findAll();
        request.setAttribute("users",users);
        return "index";
    }
}
# 6.修改index.html展示所有数据
引入thymeleaf语法解析:<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>导入excel的主页面</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">
                <h1>选择Excel文件导入到数据中</h1>
                <form th:action="@{/user/import}" method="post" enctype="multipart/form-data" class="form-inline">
                    <div class="form-group">
                        <input class="form-control" type="file" name="excelFile">
                        <input type="submit" class="btn btn-danger" value="导入数据">
                    </div>
                </form>
            </div>
            <div class="col-md-12">
                <h1>显示导入数据列表</h1>
                <table class="table table-bordered" >
                    <tr>
                        <th>编号</th>
                        <th>头像</th>
                        <th>姓名</th>
                        <th>生日</th>
                        <th>爱好</th>
                        <th>身份证号</th>
                        <th>家庭住址</th>
                    </tr>
                    <tr th:each="user : ${users}">
                        <td th:text="${user.id}"></td>
                        <td><img th:src="${'/imgs/'+ user.photo}" height="60px" alt=""></td>
                        <td th:text="${user.name}"></td>
                        <td th:text="${#dates.format(user.bir,'yyyy-MM-dd')}"></td>
                        <td th:text="${user.habbys}"></td>
                        <td th:text="${user.cardno}"></td>
                        <td th:text="${user.address}"></td>
                    </tr>
                </table>
                <hr>
                <a th:href="@{/user/export}" class="btn btn-info">导出excel</a>
            </div>
        </div>
    </div>
</body>
</html>
# 7.启动项目进行访问

4.导入数据
# 1.开发DAO&Mapper
@Mapper
public interface UserDAO {
    //查询所有
    List<User> findAll();
    //插入记录
    void save(User user);
}
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDAO">
    <!--查询所有-->
    <select id="findAll" resultType="User">
        select id,name,bir,photo,habbys,cardno,address from t_user
    </select>
    <!--插入记录-->
    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values (#{id},#{name},#{bir},#{photo},#{habbys},#{cardno},#{address})
    </insert>
</mapper>
# 2.开发Service接口和实现类
public interface UserService {
    //查询所有
    List<User> findAll();
    //批量保存
    void saveAll(List<User> users);
}
@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;
    @Override
    public List<User> findAll() {
        return userDAO.findAll();
    }
    @Override
    public void saveAll(List<User> users) {
        users.forEach(user -> {
        user.setId(null);
        user.setPhoto(user.getPhoto().substring(user.getPhoto().lastIndexOf("/")+1));
        userDAO.save(user);
        });
    }
}
# 3.开发controller
//导入excel
@RequestMapping("/import")
public String importExcel(MultipartFile excelFile) throws Exception {
    log.info("文件名称: [{}]",excelFile.getOriginalFilename());
    ImportParams params = new ImportParams();
    params.setTitleRows(1);//设置一级标题行为1行
    params.setHeadRows(1);//设置header标题为1行
    List<User> users = ExcelImportUtil.importExcel(excelFile.getInputStream(), User.class, params);
    log.info("导入总数为: [{}]", users.size());
    userService.saveAll(users);
    return "redirect:/user/findAll";
}
# 4.编辑页面index.html
- 表单提交方式必须是post
- 表单的enctype必须为multipart/form-data
<form th:action="@{/user/import}" method="post" enctype="multipart/form-data" class="form-inline">
    <div class="form-group">
        <input class="form-control" type="file" name="excelFile">
        <input type="submit" class="btn btn-danger" value="导入数据">
    </div>
</form>
# 5.启动项目导入Excel数据

5.导出数据
# 1.开发Controller
//导出excel
@RequestMapping("/export")
public void exportExcel(HttpServletResponse response,HttpServletRequest request) throws IOException {
    List<User> users = userService.findAll();
    users.forEach(user -> {
        try {
            Excel excelAnn = user.getClass().getDeclaredField("photo").getAnnotation(Excel.class);
            user.setPhoto(excelAnn.savePath()+'/'+user.getPhoto());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    });
    Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表", "用户信息"), User.class, users);
    response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode("用户列表.xls","UTF-8"));
    ServletOutputStream os = response.getOutputStream();
    workbook.write(os);
    os.close();
    workbook.close();
}
# 2.编辑index.html页面
# 3.启动项目测试excel导出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/7898.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA设计模式之【建造者模式】

1 定义 建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 2 类图 产品类&#xff08;Product&#xff09;&#xff1a;表示被创建的复杂…

智能化健身房管理:Spring Boot与Vue的创新解决方案

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

如何修改WordPress经典编辑器的默认高度?

boke112百科有一个使用WordPress搭建的小网站&#xff0c;文章内容就是几个字不到一行&#xff0c;但是每次使用经典编辑器编辑文章时&#xff0c;都觉得编辑器默认高度太高了&#xff0c;影响了我添加文章摘要和其他属性&#xff0c;有没有办法修改WordPress经典编辑器的默认高…

C#属性 Property

属性Property不是变量。 它们是由名为访问器方法来实现的一种方法。 实例属性表示的是实例的某个数据&#xff0c;通过这个数据反映实例当前的状态 静态属性表示的是类型的某个数据&#xff0c;通过这个数据反映类型当前的状态 意义&#xff1a; 防止恶意赋值(通过属性间接访问…

【力扣热题100】[Java版] 刷题笔记-121. 买卖股票的最佳时机

题目&#xff1a;121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。…

Wi-Fi7 puncturing技术增强与应用

原文关注公众号 - 无线技术栈,及时查看网络/Wi-Fi更多知识 “本文图片没有一一列出,感兴趣可以关注公众号 - 无线技术栈” “本文图片没有一一列出,感兴趣可以关注公众号 - 无线技术栈” Puncturing是一种有效的编码技术,广泛应用于无线通信中,用于在保持信号的可靠性的同…

C语言内存函数介绍和模拟实现:(memcpy,memmove,memcmp,memset)

memcpy介绍及模拟实现&#xff1a; memcpy介绍&#xff1a; void* 是指可以接受任何类型的指针。 memcpy是把从 source 指针开始之后的 num 个字节的内存拷贝到 destination 指针之后的空间。 遇到‘\0’不会停止&#xff0c;而且memcpy不可以拷贝重叠空间&#xff0c;就是说…

浏览器指纹修改指南2024 - 修改Geolocation API指纹(十一)

引言 在前几篇文章中&#xff0c;我们已经详细探讨了Geolocation API的定义、作用及其在浏览器指纹中的重要性&#xff0c;并深入分析了Chromium源码中Geolocation API的实现位置和修改方法。通过这些分析&#xff0c;我们为后续的修改工作奠定了坚实的基础。 在本篇文章中&a…

【微信小程序】基本语法

一、导入小程序 选择代码目录 项目配置文件 appid 当前小程序的 AppIDprojectname 当前小程序的项目名称 变更AppID&#xff08;视情况而定&#xff0c;如果没有开发权限时需要变更成个人的 AppID&#xff09; 二、模板语法 在页面中渲染数据时所用到的一系列语法叫做模板…

数据结构:顺序表

顺序表 顺序表的概念与结构静态顺序表动态顺序表 动态顺序表的实现SeqList.h的创建初始化动态顺序表&#xff08;LS_Init&#xff09;动态顺序表的销毁&#xff08;LS_Destry&#xff09;检查动态内存空间是否已满&#xff08;SL_CheckCapacity&#xff09;动态顺序表打印有效数…

MySQL_数据类型建表

复习&#xff1a; 我们昨天学习的知识都忘了嘛&#xff1f;如果忘了也不要担心&#xff0c;我来带大家来复习一遍吧&#xff01;&#xff01;&#xff01; 1.查看所有数据库 show databases;2.创建属于自己的数据库 create database 数据库名; 检查自己创建的数据库是…

PHP不良事件上报系统源码,医院安全不良事件管理系统,基于 vue2+element+ laravel框架开发

不良事件上报系统通过 “事前的人员知识培训管理和制度落地促进”、“事中的事件上报和跟进处理”、 以及 “事后的原因分析和工作持续优化”&#xff0c;结合预存上百套已正在使用的模板&#xff0c;帮助医院从对护理事件、药品事件、医疗器械事件、医院感染事件、输血事件、意…

在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序

如果您有 Android 设备&#xff0c;您可能会将个人和专业的重要文件保存在设备的 SD 卡上。这些文件包括照片、视频、文档和各种其他类型的文件。您绝对不想丢失这些文件&#xff0c;但当您的 SD 卡损坏时&#xff0c;数据丢失是不可避免的。 幸运的是&#xff0c;您不需要这样…

实战:看懂并分析执行计划——Nested Loops (Inner Join)

这是执行计划中 Nested Loops 的详情信息,下面将逐行解释每个字段的含义,并提供优化思路。 Nested Loops 分析 Physical Operation: Nested Loops (Inner Join) 物理操作,表示这是一个嵌套循环连接(Nested Loops),用于执行 INNER JOIN。嵌套循环通常用于小数据集的连接…

Meta Llama3用于药物发现的微调、RAG 和提示工程-LLM保姆级资料

Meta Llama3用于药物发现的微调、RAG 和提示工程的使用指南&#xff1a;LLM微调的基本概念&#xff0c;每种微调方式的深入解读&#xff0c;2种生物医药领域的Llama3的微调应用。 LLM 如何微调LLMs&#xff1f;3种微调方式&#xff0c;什么时候&#xff1f;什么情况下该使用何…

如何通过 PXE 使用 UEFI 启动 Tiny Core Linux

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

根据关键字搜索商品API返回值解析:深入解析与代码实践

在电子商务和数据集成领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;扮演着至关重要的角色。通过API&#xff0c;开发者可以访问和利用平台的数据资源&#xff0c;实现自动化和智能化的数据交互。本文将探讨如何根据关键字搜索商品API的返回值进行解析&#xff…

Python http打印(http打印body)flask demo(http调试demo、http demo、http printer)

文章目录 代码解释 代码 # flask_http_printer.pyfrom flask import Flask, request, jsonify import jsonapp Flask(__name__)app.route(/printinfo, methods[POST]) def print_info():# 分隔符separator "-" * 60# 获取请求头headers request.headers# 获取 JS…

「C/C++」C/C++ STL 之 迭代器

✨博客主页何曾参静谧的博客📌文章专栏「C/C++」C/C++程序设计📚全部专栏「VS」Visual Studio「C/C++」C/C++程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid函数说明「…

大模型微调,使用QLoRA和自定义数据集微调大模型(下)

4.8 数据预处理 在微调模型之前&#xff0c;我们不能直接使用原始数据集&#xff0c;需要将数据集中的提示转换成模型能够理解的格式。 为了使数据集适配微调流程&#xff0c;这里编写辅助函数来格式化输入数据集。具体来说&#xff0c;就是将对话摘要&#xff08;即提示-响应…