java导入导出excel文件

前言:该文章使用java集成poi来操作excel文件,此处只对poi相关api进行代码编写,对于poi的理论性知识,可在学习完这篇文章后,自行百度学习。建议大家跟着文章敲一遍代码。

  1. 创建一个maven项目,并在pom文件中导入poi相关依赖。
		<!--xls(03版本)需要的依赖-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.9</version>
        </dependency>
        <!--xlsx(07版本)需要的依赖-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.9</version>
        </dependency>
        <!--日期格式化工具-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.4</version>
        </dependency>
  1. 在Java中一切皆对象,xlsx各组成部分对于java来说也是对象。对于一个excel文件来说,要先有工作簿,然后有工作表,接着有行,最后有单元格;因此对于java而言,要使用poi先创建工作簿对象,然后创建工作表对象,接着创建行对象,最后创建单元格对象。(注意:这点很重要,因为这关系到后面的代码编写)
    在这里插入图片描述
  2. 接下来使用代码生成xls和xlsx文件。poi提供HSSFWorkbook对象来操作xls,提供XSSFWorkbook来操作xlsx。注意看注释部分的代码描述。
/**
 * java生成excel文件
 */
public class ExcelWriteTest {

    //生成xls文件,注意使用HSSFWorkbook对象
    @Test
    public void testWrite03() throws IOException {
        //1、创建一个工作簿;注意此处使用HSSFWorkbook对象
        Workbook workbook = new HSSFWorkbook();
        //2、通过工作簿来创建工作表,可自定义表名
        Sheet sheet = workbook.createSheet("测试表");
        //3、通过工作表来创建行;注意:第一行的下标是0
        Row row1 = sheet.createRow(0);
        //4、通过行来创建单元格,即(1,1)单元格;注意:单元格的下标也是从0开始
        Cell cell_1_1 = row1.createCell(0);
        //5、给单元格赋值
        cell_1_1.setCellValue("第1行第1列单元格");
        //创建(1,2)单元格
        Cell cell_1_2 = row1.createCell(1);
        cell_1_2.setCellValue("第1行第2列单元格");

        //创建第二行
        Row row2 = sheet.createRow(1);
        //创建(2,1)和(2,2)单元格,并写入数据
        Cell cell_2_1 = row2.createCell(0);
        cell_2_1.setCellValue("第2行第1列单元格");
        Cell cell_2_2 = row2.createCell(1);
        cell_2_2.setCellValue("第2行第2列单元格");

        //创建输出流对象,指定要生成的文件路径,注意格式一定是xls类型的
        FileOutputStream outputStream = new FileOutputStream("C:\\Users\\admin\\Desktop\\测试.xls");
        //将workbook对象(工作簿对象)写入流中
        workbook.write(outputStream);
        outputStream.close();
        System.out.println("xls文件生成完毕");
    }

    //生成xlsx文件,注意使用XSSFWorkbook对象
    //此处代码和上面testWrite03()方法除了XSSFWorkbook和xlsx类型不同,其他部分都相同
    @Test
    public void testWrite07() throws IOException {
        //创建一个工作簿;注意此处使用XSSFWorkbook对象
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("测试表");
        Row row1 = sheet.createRow(0);
        Cell cell_1_1 = row1.createCell(0);
        cell_1_1.setCellValue("第1行第1列单元格");
        Cell cell_1_2 = row1.createCell(1);
        cell_1_2.setCellValue("第1行第2列单元格");

        Row row2 = sheet.createRow(1);
        Cell cell_2_1 = row2.createCell(0);
        cell_2_1.setCellValue("第2行第1列单元格");
        Cell cell_2_2 = row2.createCell(1);
        cell_2_2.setCellValue("第2行第2列单元格");

        //注意格式一定是xlsx类型的
        FileOutputStream outputStream = new FileOutputStream("C:\\Users\\admin\\Desktop\\测试2.xlsx");
        workbook.write(outputStream);
        outputStream.close();
        System.out.println("xlsx文件生成完毕");
    }

}

到目前为止,已经可以生成简单的excel文件了,接下来介绍下HSSFWorkbook和XSSFWorkbook的区别,以及在面前大数据量情况下生成excel的解决方案。

  1. 以下是HSSF和XSSF各自的优缺点,另外再介绍一下生成xlsx文件更高效的SXSSF

HSSF:先写入缓存,不操作磁盘,最后一次性写入,效率高;但是最多只能处理65536行数据,否则就会报错,因为xls格式的文件最多存放65536行数据。
XSSF:可以写入比较大的数据量,如20万行,甚至更多;但是写数据的速度慢,非常耗内存,也有可能发生内存溢出的情况,如写入100万行数据时。因此在生成xlsx文件时,更推荐使用SXSSF对象,因为效率更高,下面用代码来展示SXSSF对象使用过程。

    //使用SXSSF生成大数据量xlsx文件,10万行
    @Test
    public void testWriteSXSSF() throws IOException {
        //开始时间
        long begin = System.currentTimeMillis();
        //创建顺序:工作簿-->工作表-->行-->单元格
        Workbook workbook = new SXSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        //生成10万行
        for (int rowNum = 0; rowNum < 100000; rowNum++) {
            Row row = sheet.createRow(rowNum);
            //每行生成10个单元格
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        FileOutputStream outputStream = new FileOutputStream("C:\\Users\\admin\\Desktop\\测试3.xlsx");
        workbook.write(outputStream);
        outputStream.close();
        //生成sxls会产生临时文件,所以需要清除临时文件
        ((SXSSFWorkbook) workbook).dispose();
        //结束时间
        long end = System.currentTimeMillis();
        System.out.println("耗时(秒):" + (double) (end - begin) / 1000);
    }
  1. 以上的内容介绍了使用poi生成excel文件,接下来介绍使用excel读取excel文件,其使用方式与导出类似,使用HSSF对象读取xls文件,使用XSSF读取xlsx文件,下面代码来演示用法:
    /**
     * 使用HSSF读取xls文件
     */
    @Test
    public void readXls() throws IOException {
        //创建输入流对象,读取指定文件的内容
        FileInputStream inputStream = new FileInputStream("C:\\Users\\admin\\Desktop\\测试.xls");
        //使用流来构造工作簿对象,注意:这里读取xls文件,要构造HSSFWorkbook对象
        Workbook workbook = new HSSFWorkbook(inputStream);
        //通过sheet名称或者下标获取要读取的sheet页
        Sheet sheet = workbook.getSheetAt(0);
        //根据下标得到第1行
        Row row = sheet.getRow(0);
        //根据下标得到(1,1)单元格
        Cell cell = row.getCell(0);
        //获取单元格的值
        String value = cell.getStringCellValue();
        System.out.println(value);
    }

    /**
     * 使用XSSF读取xlsx文件
     */
    @Test
    public void readXlsx() throws IOException {
        //创建输入流对象,读取指定文件的内容
        FileInputStream inputStream = new FileInputStream("C:\\Users\\admin\\Desktop\\测试2.xlsx");
        //使用流来构造工作簿对象,注意:这里读取xlsx文件,要构造XSSFWorkbook对象
        Workbook workbook = new XSSFWorkbook(inputStream);
        //通过sheet名称或者下标获取要读取的sheet页
        Sheet sheet = workbook.getSheetAt(0);
        //根据下标得到第1行
        Row row = sheet.getRow(0);
        //根据下标得到(1,1)单元格
        Cell cell = row.getCell(0);
        //获取单元格的值
        String value = cell.getStringCellValue();
        System.out.println(value);
    }
  1. 上面的代码,介绍了HSSF读取xls文件和XSSF读取xlsx文件的简单用法,但是在实际工作中读取的excel远比demo中的复杂,届时就需要各位大牛们使用代码逻辑来读取相关数据。另外,在excel中单元格的数据可能是字符串、数字、日期、布尔值等格式,下面介绍面对不同格式的数据时的读取方式:
    /**
     * 读取不同数据类型的单元格
     */
    @Test
    public void readDifferentType() throws IOException {
        FileInputStream inputStream = new FileInputStream("C:\\Users\\admin\\Desktop\\测试.xls");
        //因为读取xls,因此此处创建HSSF对象
        Workbook workbook = new HSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);
        //通过sheet获取总行数
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 0; rowNum < rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row != null) {
                //通过row获取总列数(即每行的单元格)
                int cellCount = row.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                    Cell cell = row.getCell(cellNum);
                    if (cell != null) {
                        //获取单元格的数据类型
                        int cellType = cell.getCellType();
                        String cellValue = "";
                        switch (cellType) {
                            //字符串类型
                            case HSSFCell.CELL_TYPE_STRING:
                                cellValue = cell.getStringCellValue();
                                break;
                            //布尔类型
                            case HSSFCell.CELL_TYPE_BOOLEAN:
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            //空
                            case HSSFCell.CELL_TYPE_BLANK:
                                break;
                            //数字(日期、普通数字)
                            case HSSFCell.CELL_TYPE_NUMERIC:
                                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                    //日期格式
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-dd");
                                } else {
                                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                    cellValue = cell.getStringCellValue();
                                }
                                break;
                            //错误
                            case HSSFCell.CELL_TYPE_ERROR:
                                break;
                        }
                        //输出结果。但在工作中,大多是将读取的数据组成对象,存入数据库
                        System.out.println(cellValue);
                    }
                }
            }
        }
        inputStream.close();
    }
  1. 以上介绍了在读取不同数据类型数据时的处理方式,除此之外还有一种情况,如果单元格的数据是通过公式计算生成的,如下图所示,那这种情况该如何处理呢?(了解即可)

在这里插入图片描述
针对这种情况,poi专门提供了公式对象来解决,请观察以下代码:

    /**
     * 计算公式
     */
    @SuppressWarnings("all")
    @Test
    public void readFormula() throws IOException {
        FileInputStream inputStream = new FileInputStream("C:\\Users\\admin\\Desktop\\公式测试.xls");
        Workbook workbook = new HSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);
        //(5,1)单元格所在的行是由公式生成
        Row row = sheet.getRow(4);
        Cell cell = row.getCell(0);
        //获取计算公式
        HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
        //获取单元格数据类型
        int cellType = cell.getCellType();
        switch (cellType) {
            case HSSFCell.CELL_TYPE_FORMULA:
                //获取公式字符串,即-->SUM(A2:A4)
                String cellFormula = cell.getCellFormula();
                System.out.println(cellFormula);
                CellValue evaluate = formulaEvaluator.evaluate(cell);
                String cellValue = evaluate.formatAsString();
                System.out.println(cellValue);
                break;
        }
        inputStream.close();
    }
  1. 截止到这里,想必大家已经了掌握poi操作excel的基本用法,但在实际工作中,仅靠这些是远远不够的,当出现一些比较复杂的情况时,如在导出excel时需要合并单元格、改变样式,又该如何处理呢?大家先看下导出excel的效果图。
    在这里插入图片描述
    从上图中可以发现,有部分单元格是被合并的,接下来通过代码来演示如何合并单元格:
    /**
     * 导出excel文件
     */
    public void export(HttpServletResponse response) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        //设置字体大小
        Font font = workbook.createFont();
        font.setFontHeightInPoints((short) 18);
        //定义样式
        HSSFCellStyle style = workbook.createCellStyle();
        style.setFont(font);
        //注意:这里有坑,在不同版本的poi中,设置居中方式不同。
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中
        style.setWrapText(true);//自动换行
        //合并单元格的集合
        List<CellRangeAddress> addressList = new ArrayList<>();
        //创建sheet
        HSSFSheet sheet = workbook.createSheet("月报表");
        //设置第1列的宽度
        sheet.setColumnWidth(0, 35 * 256);
        //第一行标题
        Row row_0 = sheet.createRow(0);
        //设置行高
        row_0.setHeight((short) 1500);
        Cell cell_0_0 = row_0.createCell(0);
        //设置样式
        cell_0_0.setCellStyle(style);
        //注意:这里的值写死了,实际工作中要从数据库读取的
        cell_0_0.setCellValue("司法鉴定行业党建工作情况月报表\n(2020年7月)");
        /*
         *使用CellRangeAddress对象合并单元格
         * CellRangeAddress参数解读:
         * 第一个参数:合并单元格的起始行下标
         * 第二个参数:合并单元格的结束行下标
         * 第三个参数:合并单元格的起始列下标
         * 第四个参数:合并单元格结束列下标
         * 最终意思:把从第1行到第1行,从第1列到第37列,合并为一个单元格
         * 注:参考上面的图片理解这句话的意思
         */
        addressList.add(new CellRangeAddress(0, 0, 0, 36));
        //第二行
        Row row_1 = sheet.createRow(1);
        row_1.setHeight((short) 1000);
        Cell cell_1_0 = row_1.createCell(0);
        cell_1_0.setCellStyle(style);
        cell_1_0.setCellValue("山东省(市、区)");
        addressList.add(new CellRangeAddress(1, 1, 0, 5));
        /*
         *因为第二行的第一个单元格合并了从第2行到第2行,从第1列到第6列的所有单元格(注意下标是0开始)
         *所有第二个单元格从第7列开始
         */
        Cell cell_1_6 = row_1.createCell(6);
        cell_1_6.setCellStyle(style);
        cell_1_6.setCellValue("统计期间:截至2021年03月18日");
        //合并从第2行到第2行,从第7列到第37列的所有单元格
        addressList.add(new CellRangeAddress(1, 1, 6, 36));

        //其他单元格代码省略......

        //合并单元格
        for (CellRangeAddress address : addressList) {
            //CellRangeAddress描述单元格的合并信息,使用sheet的addMergedRegion方法执行合并操作
            sheet.addMergedRegion(address);
        }

        //通过response下载excel到客户端
        OutputStream outputStream = response.getOutputStream();
        response.reset();
        response.setHeader("Content-disposition",
                "attachment;filename=" + new String("月报表".getBytes("gbk"), "iso8859-1") + ".xls");
        response.setContentType("application/msexcel");
        response.setCharacterEncoding("utf-8");
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

以上便是使用poi导入导出excel文件的全部内容,满意的小伙伴记得点个赞哦!!>.<

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小Y先生。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值