POI操作Excel

POI

1. 快速入门

HSSF是2003版的Excel,后缀为xls
XSSF是2007版的Excel,后缀为xlsx
XSSF和HSSF操作基本一致,只需要把H换成X就行

  • 依赖
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.14</version>
    </dependency>
    <!--消耗小,不支持图片,表格-->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.14</version>
    </dependency>

1.1. 从Excel表格读取数据

在使用POI操作Excel表格时,Excel表格必须是关闭状态

  • 创建excel表格,填写内容
  • 获取工作簿
  • 获取工作表
  • 获取行
  • 获取单元格(列)
  • 获取单元格的值
    /**
     * 从excel表格中获取数据
     * @author yxk
     * Date 2021/4/9 11:13
     */
    @Test
    public void test01() throws IOException {
        //1.创建工作簿
        XSSFWorkbook workbook = new XSSFWorkbook("D:\\Java\\2.xlsx");
        //2.获取工作表--根据名称或索引
        XSSFSheet sheet = workbook.getSheetAt(0);
        //3.获取行--遍历获取所有行
        for (Row row : sheet) {
            //4.获取单元格--遍历行获取所有单元格
            for (Cell cell : row) {
                //5.获取单元格的值
                String stringValue = cell.getStringCellValue();
                System.out.print(stringValue+" ");
            }
            System.out.println();
        }
        //关流
        workbook.close();

    }

    /**
     * 从excel表格中获取数据
     * @author yxk
     * Date 2021/4/9 11:13
     */
    @Test
    public void test02() throws IOException {
        //1.创建工作簿
        XSSFWorkbook workbook = new XSSFWorkbook("D:\\Java\\2.xlsx");
        //2.获取工作表--根据名称或索引
        XSSFSheet sheet = workbook.getSheetAt(0);
        //3.获取行-使用索引遍历
        int lastRowNum = sheet.getLastRowNum();
        for (int i = 0; i < lastRowNum; i++) {
            XSSFRow row = sheet.getRow(i);
            if (row != null) {
                int lastCellNum = row.getLastCellNum();
                for (int j = 0; j < lastCellNum; j++) {
                    XSSFCell cell = row.getCell(j);
                    if (cell != null) {
                        String value = cell.getStringCellValue();
                        System.out.print(value+" ");
                    }
                }
                System.out.println();
            }

        }
        //关流
        workbook.close();
    }

1.2. 往Excel表格写入数据

  • 创建工作簿
  • 创建工作表
  • 创建行
  • 创建单元格并赋值
  • 通过IO流把数据写到磁盘文件
    /**
     * 往excel表格中写入数据
     * @author yxk
     * Date 2021/4/9 11:41
     */
    @Test
    public void test03() throws IOException {
        //1.创建工作簿
        XSSFWorkbook workbook = new XSSFWorkbook();
        //2.创建工作表
        XSSFSheet sheet = workbook.createSheet();

       
        for (int i = 0 ; i < 10;i++) {
            //3.创建行 - 0代表第一行
            XSSFRow row = sheet.createRow(i);
            //4.创建单元格 - 0代表第一列
            XSSFCell cell = row.createCell(0);
            //赋值
            cell.setCellValue("Java"+"-"+i);
        }
        //5.通过IO流把数据写到磁盘文件
        FileOutputStream stream = new FileOutputStream("D:\\Java\\2.xlsx");
        workbook.write(stream);
        //刷新
        stream.flush();
       //关流
        stream.close();
        workbook.close();
    }

结果:
往第一列第i行写入数据
在这里插入图片描述

遇到的问题
当把XSSFRow row = sheet.createRow(i);的i改成0,XSSFCell cell = row.createCell(0);的0改成i
按理说第一行的第一列到第十列都应该有数据的,但是实际上只有第十列有数据
在这里插入图片描述

2. 结合Web端实现Excel文件数据导入与导出

2.1 准备

  • 创建Excel表格
    在这里插入图片描述
  • 创建数据库表
    在这里插入图片描述
  • 创建实体类User
    在这里插入图片描述
  • 在ssm环境下进行的,请自行搭建

2.2. 导入

把Excel表格的数据导入到数据库表中

  • import.jsp

获取Excel表格并提交到后台

<body>
<hi>导入Excel表格文件,本质就是文件上传</hi><br>
<form action="${pageContext.request.contextPath}/import/excel.do" method="post" enctype="multipart/form-data">
    <input type="file" name="excelFile" value="导入excel表格">
    <input type="submit" value="提交">
</form>
<br>
<p>${msg}</p>
</body>
  • showUsers.jsp

Excel表格的内容存储到数据库之后,在页面展示

<body>
<table border="1px" width="500px" align="center">
    <tr>
        <th>用户id</th>
        <th>用户名称</th>
        <th>用户密码</th>
        <th>用户地址</th>
        <th>用户年龄</th>
    </tr>
    <c:forEach items="${users}" var="user" varStatus="status">
    <tr>
        <td>${user.userId}</td>
        <td>${user.username}</td>
        <td>${user.password}</td>
        <td>${user.userAddress}</td>
        <td>${user.userAge}</td>
    </tr>
    </c:forEach>
</table>

<a href="${pageContext.request.contextPath}/export/excel.do">导出所有用户信息</a>
</body>
  • ExcelUtil.java

本来想写工具类的,但是没有成功,所以ExcelUtil.java只适合这里

/**
     * 校验excelFile文件
     * @author yxk
     * @param excelFile
     * @return java.lang.String
     * Date 2021/4/9 19:18
     */
    public static StringBuffer checkExcel(MultipartFile excelFile) {

        StringBuffer msg = null;

        //1是否为null
        if (excelFile == null) {
            msg = new StringBuffer("文件不存在");
        }else {
            //2格式是否正确
            String filename = excelFile.getOriginalFilename();
            String xls = "xls";
            String xlsx = "xlsx";
            assert filename != null;
            if (!filename.endsWith(xls) && !filename.endsWith(xlsx)) {
               msg = new StringBuffer("文件不是Excel文件");
            }
        }
        return msg;
    }

    /**
     * 通过工具类ExcelUtil得到行对象集合,通过增强for循环得到每一行,然后获得每一行单元格的值封装到实体类里
     * 在这个方法里只是一个示例,一位List的泛型,和for循环里面的内容都是写死的
     * 在实际应用中可以把该方法移除工具类.然后具体情况具体分析
     * @author yxk
     * @param excelFile
     * @return java.util.List<com.zy.pojo.User>
     * Date 2021/4/9 19:54
     */
    public static List<User> readXssf02(MultipartFile excelFile) {
        List<User> users = new ArrayList<>();
        List<XSSFRow> xssfRows = ExcelUtil.readXssf01(excelFile);
        for (XSSFRow row : xssfRows) {
            int userId = (int)row.getCell(0).getNumericCellValue();
            String username = row.getCell(1).getStringCellValue();
            String password = row.getCell(2).getStringCellValue();
            String userAddress = row.getCell(3).getStringCellValue();
            int userAge = (int)row.getCell(4).getNumericCellValue();
            users.add(new User(userId,username,password,userAddress,userAge));
        }
        return users;
    }

    /**
     * Excel表格导入 --后缀为xlsx
     * @author yxk
     * @param excelFile
     * @return java.util.List<com.zy.pojo.User>
     * Date 2021/4/9 19:19
     */
    public static List<XSSFRow> readXssf01(MultipartFile excelFile) {
        List<XSSFRow> list = null;
        try {
            //从文件excelFile获取字节输入流
            InputStream inputStream = excelFile.getInputStream();
            //构建工作簿
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            //获取工作表
            XSSFSheet sheet = workbook.getSheetAt(0);
            //获取第一行索引和最后一行索引
            int firstRowNum = sheet.getFirstRowNum();
            int lastRowNum = sheet.getLastRowNum();
            //声明一个容器
            list = new ArrayList<>();
            //遍历工作表的到行
            for (int i = firstRowNum+1; i <= lastRowNum; i++) {
                //获取工作表中的一个个行对象
                XSSFRow row = sheet.getRow(i);
                //如果行为空,跳过
                if (row == null) {
                    continue;
                }
                list.add(row);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
  • UserController.java
/**
 * @author yxk
 * @version 1.0
 * Date 2021/4/9 15:37
 */
@Controller
@RequestMapping("/import")
public class ExcelUploadController {

    @Resource
    private UserService userService;

    /**
     * Excel文件导入----文件上传
     * @author yxk
     * @param excelFile
     * @param model
     * @return java.lang.String
     * Date 2021/4/9 15:40
     */
    @RequestMapping("/excel.do")
    public String excelUpload(@RequestParam("excelFile") MultipartFile excelFile, Model model) {

        //1.校验excelFile文件
        String filename = excelFile.getOriginalFilename();
        String xlsx = "xlsx";
        //1.1判断是否为null和格式是否正确
        StringBuffer msg = ExcelUtil.checkExcel(excelFile);
        if (msg != null) {
            model.addAttribute("msg",msg);
            return "/import";
        }
        //1.2不同格式使用不同的对象
        assert filename != null;
        if (filename.endsWith(xlsx)) {
            //使用XSSFWorkbook
            List<User> users = ExcelUtil.readXssf02(excelFile);
            userService.addUser(users);
            model.addAttribute("users",users);
            return "/showUsers";
        }else {
            //假设Excel是xls的后缀在这里写逻辑代码,基本和xlsx后缀的一样
            //使用HSSFWorkbook获取工作簿
        }
        return null;
    }

}

UserServiceImpl.java

    @Resource
    private UserMapper userMapper;


    @Override
    public void addUser(List<User> users) {
        for (User user : users) {
            userMapper.addUser(user);
        }
    }

UserMapper.xml

    <!--Excel文件导入 文件上传-->
    <insert id="addUser" parameterType="user">
        insert into user values(#{userId},#{username},#{password},#{userAddress},#{userAge})
    </insert>

2.3 导出

把数据库的表中数据下载到Excel表格里

  • Controller.java
/**
 * @author yxk
 * @version 1.0
 * Date 2021/4/9 16:38
 */
@Controller
@RequestMapping("/export")
public class ExcelExportController {

    @Resource
    private UserService userService;
    @RequestMapping("/excel.do")
    public void downLoadExcel(HttpServletResponse response) {
        List<User> users = userService.queryAllUsers() ;

        //创建工作簿
        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建工作表
        XSSFSheet sheet = workbook.createSheet("用户详情表");
        //创建行
        XSSFRow xssfRow = sheet.createRow(0);
        //创建单元格
        xssfRow.createCell(0).setCellValue("用户ID");
        xssfRow.createCell(1).setCellValue("用户姓名");
        xssfRow.createCell(2).setCellValue("用户密码");
        xssfRow.createCell(3).setCellValue("用户地址");
        xssfRow.createCell(4).setCellValue("用户年龄");

        //往表格里插入数据
        for (int i = 1; i < users.size() ; i++) {
            //创建行
            XSSFRow row = sheet.createRow(i+1);
            row.createCell(0).setCellValue(users.get(i).getUserId());
            row.createCell(1).setCellValue(users.get(i).getUsername());
            row.createCell(2).setCellValue(users.get(i).getPassword());
            row.createCell(3).setCellValue(users.get(i).getUserAddress());
            row.createCell(4).setCellValue(users.get(i).getUserAge());
        }

        try {
            //获取输出流
            ServletOutputStream outputStream = response.getOutputStream();
            //设置响应头
            response.setHeader("Content-Disposition","attachment;filename=user.xlsx");
            //设置内容类型
            response.setContentType("application/msexcel");
            //写入工作簿
            workbook.write(outputStream);
            //刷新
            outputStream.flush();
            //关流
            outputStream.close();
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

service层和mapper层基本和导入一致,省略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值