POI的基本使用& EasyPOI集成SpringMVC

这篇博客介绍了如何在SpringMVC项目中使用EasyPOI进行Excel的导出和导入操作。内容涵盖POI基础使用、EasyPOI的导入与删除原有POI包的注意事项、Excel数据的替换与日期处理、头像导出问题的解决,以及如何处理关联表。还详细讲解了如何实现导出功能,包括创建ExcelEmployee和POIDepartment对象,注解导出视图,以及导入功能的实现,包括数据验证和自定义验证处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POI的使用

先导包

    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.11</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.11</version>
    </dependency>

通过代码写一个九九乘法表在Excel里面

//    通过代码写一个九九乘法表
    @Test
    public void myTest() throws Exception{
//先创建一个Excel文件
        SXSSFWorkbook wb = new SXSSFWorkbook();
//        创建一张表
        Sheet sheet = wb.createSheet("九九乘法口诀");
//        创建相应的行
        for (int i=1;i<=9;i++){
            Row row = sheet.createRow(i-1);
//创建每行里面的格子
            for (int j=1;j<=i;j++){
                Cell cell = row.createCell(j);
//                在单元格里面填入数据
                cell.setCellValue(i+"*"+j+"="+(i*j));
            }
        }
        FileOutputStream out = new FileOutputStream("temp/99.xlsx");
        wb.write(out);//保存Excel文件
        out.close();//关闭文件流
    }

通过代码读取xlsx文件

//通过代码来读取外部Excel文件
    @Test
    public void testRead() throws Exception{
//      先将文件直接读取到内存中来
        Workbook wb = WorkbookFactory.create(new File("temp/emp.xlsx"));
//      根据文件拿到对应的表
        Sheet sheet = wb.getSheetAt(0);
//        拿到对应的行
//        先通过拿最后一行,得到总行数
        int lastRowNum = sheet.getLastRowNum();
//遍历行
        for (int i=2;i<=lastRowNum;i++){
//            拿到对应的行
            Row row = sheet.getRow(i);
//通过行,拿到每行对应的单元格
//          先通过获取最后一个单元格,来得到每行总的格数
            short lastCellNum = row.getLastCellNum();
//            遍历每一行的每一个单元格
            for (int j=0;j<lastCellNum;j++){
//                拿到该单元格的内容
                Cell cell = row.getCell(j);
                System.out.print(cell.getStringCellValue()+" ");
            }
            System.out.println();
        }

    }

学习怎样使用Easypoi

导入EasyPoi之前要将之前导入的POI包,删除。不然会有冲突

 <!-- 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>

在test里面准备一个domain POIEmployee
写一个EasyPOITest
在domain里面,如果那个字段要导出,就写上@Excel加一个name

//  添加上下面的注解,就代表哪个字段需要导出
    @Excel(name = "用戶名")
    private String name;
    @Excel(name = "邮箱",width =20)
    private String email;

替换功能:

将true改为男,false改为女

//想让导出的文件在性别显示的地方,显示男或者女,而不是显示true或者false
    @Excel(name = "性别",replace = {"男_true","女_false"})
    private Boolean sex=true;

解决日期问题

//导出时间,并设置导出的时间格式
    @Excel(name = "出生日期",format = "yyyy-MM-dd")
    private Date bornDate=new Date();

头像问题解决

//    导出图片
    @Excel(name = "用户头像",type = 2,height = 35,width = 50)
    private String headImage;

关联表

ExcelEmployee

@ExcelTarget("emp")
public class ExcelEmployee implements Serializable{
    private Long id;
//  添加上下面的注解,就代表哪个字段需要导出
    @Excel(name = "用戶名")
    private String name;
    @Excel(name = "邮箱",width =20)
    private String email;
//想让导出的文件在性别显示的地方,显示男或者女,而不是显示true或者false
    @Excel(name = "性别",replace = {"男_true","女_false"})
    private Boolean sex=true;

//导出时间,并设置导出的时间格式
    @Excel(name = "出生日期",format = "yyyy-MM-dd")
    private Date bornDate=new Date();

//    导出图片
    @Excel(name = "用户头像",type = 2,height = 35,width = 50)
    private String headImage;

//  关联部门
    @ExcelEntity
    private POIDepartment department;

POIDepartment

@ExcelTarget("dept")
public class POIDepartment {

    private Long id;
//  给两个表配置@ExcelTarget,然后在下面配置@Excel的name,表示当导出部门表的时候
//    显示名称,导出员工数据的时候显示部门名称
    @Excel(name = "部门名称_emp,名称_dept")
    private String name;

    @Excel(name = "部门地址_emp,名称_dept")
    private String address="簇锦街道";


导入

//  导入我们之前导出的数据
    @Test
    public void testRead() throws Exception{
//        设置的导入参数
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        List<ExcelEmployee> list = ExcelImportUtil.importExcel(new File("temp/employee.xls"),
                ExcelEmployee.class,params
                );
        list.forEach(excelEmployee -> System.out.println(excelEmployee));
    }

和项目相结合,实现导出功能。

第一步,先加注解
名字,邮箱,年龄,头像,部门,给部门添加的注解用@EntityExcel,在部门domain里面对name添加@Excel
第二步:添加一个按钮

<a href="/employee/export" data-method="search" class="easyui-linkbutton" iconCls="icon-search">导出</a>

在EmployeeController里面添加一个路径方法
@RequestMapping(“/export”)
public String export(ModelMap map){
//怎么从数据库中拿到数据,并变成Excel中的数据,并且要导出到前台
查看EasyPOI教程,注解导出view的用法
}

然后在注解目录扫描的时候加上cn.afterturn.easypoi.view

扫描Excel的View包,在applicationContext-mvc

<!--扫描Excel的view包-->
    <context:component-scan base-package="cn.afterturn.easypoi.view"/>
    <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"
    p:order="0"/>

使用了p:order=”0”的时候,会添加一个假的头。

       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"

实现员工头像的导出

//      以图片的样式来导出员工的图片路径
//        先拿到图片的真实路径
        String realPath = request.getServletContext().getRealPath("");
    
        list.forEach(e->{
            e.setHeadImage(e.getHeadImage());
            
        });

如果只想导出单个部门的所有数据

给查询部件的form添加一个method=“post”
和action=”/employee/export”
并将导出变成按钮格式

 <button class=”easyui-linkbutton” iconCls=”icon-search”>导出</button>
 

前台传入相应的查询数据

 <form id="searchForm" method="post" action="/employee/download">
    用户名: <input name="username" class="easyui-textbox" style="width:80px">
    邮件: <input name="email" class="easyui-textbox" style="width:80px">
    部门:
    <input name="departmentId"  class="easyui-combobox"
           data-options="panelHeight:'auto',valueField:'id',textField:'name',url:'/util/deptlist'" />
    <a href="javascript:;" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询</a>
    <!-- button不写type,它就是提交 -->
    <button class="easyui-linkbutton" iconCls="icon-redo">导出</button>
</form>

写一个导入管理的页面,ImportController

package cn.cxm.aisell.web.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.cxm.aisell.common.EmployeeExcelVerifyHandler;
import cn.cxm.aisell.domain.Department;
import cn.cxm.aisell.domain.Employee;
import cn.cxm.aisell.service.IDepartmentService;
import cn.cxm.aisell.service.IEmployeeService;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.OutputStream;
import java.util.List;

@Controller
@RequestMapping("/import")
public class ImportController {
    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private IDepartmentService departmentService;

    @Autowired
    private EmployeeExcelVerifyHandler employeeExcelVerifyHandler;
    //    上传页面
    @RequestMapping("/index")
    public String index() {

        return "import";
    }

    //    上传Excel的功能实现
    @RequestMapping("/employeeXlsx")
    public String employeeXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception{
//设置导入参数
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
//      为true表示这里需要验证
        params.setNeedVerfiy(true);
//      加入自定义验证
        params.setVerifyHandler(employeeExcelVerifyHandler);
        ExcelImportResult<Employee> result=ExcelImportUtil.importExcelMore(
                empFile.getInputStream(), Employee.class, params);
//        拿到数据将其保存到数据库里面
        List<Employee> list = result.getList();
        list.forEach(e -> {
//            从数据库中查询到部门的名字
            String deptName = e.getDepartment().getName();
//            通过部门的名字来查找部门的其他信息
            Department byName = departmentService.findByName(deptName);
            e.setDepartment(byName);
//            这里我们给他设置一个初始密码
            e.setPassword("123");
            employeeService.save(e);

        });
//        利用之前学过的下载功能将文件写出
        Workbook failWorkbook = result.getFailWorkbook();
        //大佬说下面设置好直接使用即可导出
        //设置响应的文件类型 mime类型
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //attachment:表示不要用浏览器打开
        response.setHeader("Content-disposition", "attachment;filename=empFail.xlsx");
        response.setHeader("Pragma", "No-cache");//设置不要缓存
        OutputStream ouputStream = response.getOutputStream();
        failWorkbook.write(ouputStream);
        ouputStream.flush();
        ouputStream.close();
        return "import";
    }

}

导入的时候应该做一下验证

导入验证包

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>5.2.4.Final</version>
</dependency>

自定义验证用户是否存在

这个类型是需要Spring扫描

/*把普通javaBean实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
* */
@Component
public class EmployeeExcelVerifyHandler implements IExcelVerifyHandler<Employee> {

    @Autowired
    private IEmployeeService employeeService;

    @Override
    public ExcelVerifyHandlerResult verifyHandler(Employee employee) {
//        自定义验证,验证新导入的用户名是否重复
        boolean checkName = employeeService.checkName(employee.getUsername());
        if (checkName){
//            如果核对后显示为true,就代表该用户名可用
            return new ExcelVerifyHandlerResult(true);
        }
        return new ExcelVerifyHandlerResult(false,"该用户名已被使用");
    }
}

导入功能修改

要验证,必需设置 params.setNeedVerfiy(true);
自定义验证:params.setVerifyHandler(employeeExcelVerifyHandler);
result.getList(); 拿到所有通过验证的数据 result.getFailList():拿到所有错误的数据 result.getFailWorkbook();拿到错误的文本

@Autowired
private EmployeeExcelVerifyHandler employeeExcelVerifyHandler;
...
@RequestMapping("/empXlsx")
public String empXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception{
    //准备一些导入的参数
    ImportParams params = new ImportParams();
    params.setTitleRows(1);
    params.setHeadRows(1);
    params.setNeedVerfiy(true); //需要做验证
    //设置验证处理器
    params.setVerifyHandler(employeeExcelVerifyHandler);

    //把上传的excel文件中的数据变成Employee
    ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore(
            empFile.getInputStream(),
            Employee.class, params);

    //拿到相应的值
    List<Employee> list = result.getList();
    //把员工进行保存
    list.forEach(e -> {
        //设置一个默认密码
        e.setPassword("123456");
        //根据名称到数据库中拿到部门
        Department department = e.getDepartment();
        if(department!=null){
            Department dbDept =  departmentService.findByName(department.getName());
            e.setDepartment(dbDept);
        }
        employeeService.save(e);
    });

    //拿到错误的值
//        List<Employee> errList = result.getFailList();
//        errList.forEach(e -> System.out.println("错误的:"+e));
    //有错误的情况进行导出
    if(result.isVerfiyFail()){
        //拿到错误的文件
        Workbook failWorkbook = result.getFailWorkbook();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //mime类型
        response.setHeader("Content-disposition", "attachment;filename=error.xlsx");
        response.setHeader("Pragma", "No-cache");//设置不要缓存
        OutputStream ouputStream = response.getOutputStream();
        failWorkbook.write(ouputStream);
        ouputStream.flush();
        ouputStream.close();
    }
    return "import";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值