其他分享
首页 > 其他分享> > 一文教你轻松掌握Apache POI的基本使用

一文教你轻松掌握Apache POI的基本使用

作者:互联网

文章目录

一、Apache POI介绍

开发中经常会设计到excel的处理,如导出Excel,导入Excel到数据库中,几年前操作Excel常用的有两个框架,一个是apache 的poi, 另一个是 Java Excel,不过现在又出现了EasyPoi和阿里开源的EasyExcel,这两个后面再进行整理

二:Apache POI常用的类

常用的类和方法

HSSFWorkbook :工作簿,代表一个excel的整个文档

HSSFSheet:工作表

HSSFRow :行

HSSFCell:单元格

HSSFFont:字体,

HSSFName:名称

Excel中的工作簿、工作表、行、单元格中的关系:

一个Excel文件对应于一个workbook(HSSFWorkbook),
一个workbook可以有多个sheet(HSSFSheet)组成, 一个sheet是由多个row(HSSFRow)组成,
一个row是由多个cell(HSSFCell)组成

三、实例演示

1.创建一个普通的maven项目
2.引入Apache 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>

示例一:在桌面生成一个Excel文件【03版本】

@Test
    public void createExcel() throws IOException{
        // 获取桌面路径
        FileSystemView fsv = FileSystemView.getFileSystemView();
        String desktop = fsv.getHomeDirectory().getPath();
        System.out.println("桌面路径:"+desktop);
        String filePath = desktop + "/test.xls";

        File file = new File(filePath);
        OutputStream outputStream = new FileOutputStream(file);
        //1.创建一个工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        //2.创建一个名叫test1的工作表
        HSSFSheet sheet = workbook.createSheet("test1");
        //3.创建第一行并设置值
        HSSFRow row = sheet.createRow(0);
        row.createCell(0).setCellValue("id");
        row.createCell(1).setCellValue("订单号");
        row.createCell(2).setCellValue("下单时间");
        row.createCell(3).setCellValue("个数");
        row.createCell(4).setCellValue("单价");
        row.createCell(5).setCellValue("订单金额");
        row.setHeightInPoints(30); // 设置行的高度
        //4.创建第二行并设置值
        HSSFRow row1 = sheet.createRow(1);
        row1.createCell(0).setCellValue("1");
        row1.createCell(1).setCellValue("NO00001");

        //4.1设置第三列值,并做日期格式化
        HSSFCellStyle cellStyle2 = workbook.createCellStyle();
        HSSFCreationHelper creationHelper = workbook.getCreationHelper();
        cellStyle2.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
        sheet.setColumnWidth(2, 20 * 256); // 设置列的宽度

        HSSFCell cell2 = row1.createCell(2);
        cell2.setCellStyle(cellStyle2);
        cell2.setCellValue(new Date());
        //4.2设置第四列值
        row1.createCell(3).setCellValue(2);


        //4.3设置第五列值 保留两位小数
        HSSFCellStyle cellStyle3 = workbook.createCellStyle();
        cellStyle3.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
        HSSFCell cell4 = row1.createCell(4);
        cell4.setCellStyle(cellStyle3);
        cell4.setCellValue(29.5);


        //4.3设置第六列值 货币格式化
        HSSFCellStyle cellStyle4 = workbook.createCellStyle();
        HSSFFont font = workbook.createFont();
        font.setFontName("华文行楷");
        font.setFontHeightInPoints((short)15);
        font.setColor(HSSFColor.RED.index);
        cellStyle4.setFont(font);

        HSSFCell cell5 = row1.createCell(5);
        cell5.setCellFormula("D2*E2");  // 设置计算公式

        //4.3.1获取计算公式的值
        HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(workbook);
        cell5 = e.evaluateInCell(cell5);
        System.out.println("计算得到的值为:"+cell5.getNumericCellValue());

        //设置默认选中第一张工作表
        workbook.setActiveSheet(0);
        //将数据写入文件
        workbook.write(outputStream);
        //关闭流
        outputStream.close();
    }

运行结果:
在这里插入图片描述
桌面生成的文件为:
在这里插入图片描述

注意:07版本和03版本的区别是:

读写操作基本一样,不同的就是对象和后缀名不一样而已

示例二:03版本大量数据写入【HSSF】

java.lang.IllegalArgumentException:Invalid row number (65536) outside allowable range (0.. 65535)
@Test
    public void testwrite03BigData() throws IOException {
        //时间
        long begin = System.currentTimeMillis();
        //创建一个薄
        Workbook workbook = new HSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 65536; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        FileOutputStream fos = new FileOutputStream(PATH + "03版本Excel大量数据测试.xls");
        workbook.write(fos);
        fos.close();
        System.out.println("over");
        long end = System.currentTimeMillis();
        System.out.println((double) (end - begin) / 1000);
    }

运行结果:
在这里插入图片描述

示例三:07版本大量数据写入【XSSF】

 @Test
    public void testwrite07BigData() throws IOException {
        //时间
        long begin = System.currentTimeMillis();
        //创建一个薄
        Workbook workbook = new XSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 65536; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        FileOutputStream fos = new FileOutputStream(PATH + "07版本Excel大量数据测试.xlsx");
        workbook.write(fos);
        fos.close();
        System.out.println("over");
        long end = System.currentTimeMillis();
        System.out.println((double) (end - begin) / 1000);
    }

运行结果:
在这里插入图片描述
可以发现07版本写入数据时非常慢,很耗内存,耗时比03版本还要长,接下来介绍另一种方式进行大数据写入,那就是SXSSF

示例四:大量数据写入【SXSSF】

优点:可以写非常大量的数据库,如100万条甚至更多条,写数据速度快,占用更少的内存
注意:

 @Test
    public void testwrite07_S_BigData() throws IOException {
        //时间
        long begin = System.currentTimeMillis();
        //创建一个薄
        Workbook workbook = new SXSSFWorkbook(100);
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 65536; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        FileOutputStream fos = new FileOutputStream(PATH + "07_S_版本Excel大量数据测试.xlsx");
        workbook.write(fos);
        fos.close();
        //清除临时缓存
        ((SXSSFWorkbook)workbook).dispose();
        System.out.println("over");
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+(double) (end - begin) / 1000+"秒");
    }

运行结果:速度大大提升了
在这里插入图片描述
SXSSWorkbook 来自官方解释:实现:BigGridDemo策略的流式XSSFWorkbook版本。这允许写入非常大的文件而不会耗尽内存,因为任何时候只有可配置的行部分被保存在内存中。

示例五:读取Excel,解析数据 [ 多数据类型校验 ]

表数据如下所示:
在这里插入图片描述

表的特点是:里面的数据有字符串,数值,日期,布尔值,空值,所以读取的时候需要对表中的字段值进行类型判断,然后再进行解析,否则会报错:
在这里插入图片描述

 @Test
    public void testCellType() throws Exception {

        //获取文件流
        FileInputStream fis = new FileInputStream(PATH +"多类型测试表.xlsx");

        //创建一个工作簿。使用 excel能操作的这边他都可以操作
        Workbook workbook = new XSSFWorkbook(fis);
        Sheet sheet = workbook.getSheetAt(0);

        //获取标题内容
        Row rowTitle = sheet.getRow(0);
        if (rowTitle != null) {
            //得到一行有多少列有数据
            int cellCount = rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                Cell cell = rowTitle.getCell(cellNum);
                if (cell != null) {
                    int cellType = cell.getCellType();
                    String cellValue = cell.getStringCellValue();
                    System.out.print(cellValue + "|");
                }
            }
            System.out.println();
        }

        //获取表中的内容
        //获取表中有多少行有数据
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 1; rowNum < rowCount; rowNum++) {
            Row rowData = sheet.getRow(rowNum);
            if (rowData != null) {
                //读取列
                int cellCount = rowTitle.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                    System.out.println("[" + (rowNum + 1) + "-" + (cellNum + 1) + "]");

                    Cell cell = rowData.getCell(cellNum);
                    //匹配列的数据类型
                    if (cell != null) {
                        int cellType = cell.getCellType();
                        String cellValue = "";

                        switch (cellType) {
                            case HSSFCell.CELL_TYPE_STRING://字符
                                System.out.print("【 String】");
                                cellValue = cell.getStringCellValue();
                                break;
                            case HSSFCell.CELL_TYPE_BOOLEAN://布尔
                                System.out.print("【 BOOLEAN】");
                                cellValue = String.valueOf(cell.getBooleanCellValue());
                                break;
                            case HSSFCell.CELL_TYPE_BLANK://空
                                System.out.print("【 BLANK】");
                                break;
                            case HSSFCell.CELL_TYPE_NUMERIC://数字(日期、普通数字)
                                System.out.print("【 NUMERIC】");
                                if (HSSFDateUtil.isCellDateFormatted(cell)) {// 日期
                                    System.out.print("--【日期】");
                                    Date date = cell.getDateCellValue();
                                    cellValue = new DateTime(date).toString("yyyy-MM-dd HH:mm:ss");
                                } else {
                                    //不是日期格式,防止数字过长!
                                    System.out.print("--【转换为字符串输出】");
                                    cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                    cellValue = cell.toString();
                                }
                                break;
                            case HSSFCell.CELL_TYPE_ERROR://错误
                                System.out.print("【 数据类型错误】");
                                break;
                        }
                        System.out.println(cellValue);
                    }
                }
            }
        }
        //关闭流
        fis.close();
    }

运行结果:
在这里插入图片描述

四:Java Web 中导出和导入Excel

1、导出示例

我需要将下方列表的信息导出为Excel
在这里插入图片描述
controller层:

@RequestMapping(value = "/exportSearchEcomizeActivityList", method = RequestMethod.GET)
    private void exportSearchEcomizeActivityList(HttpServletResponse response){
        adminService.exportSearchEcomizeActivityList(response);
    }

实现类:

@Override
	public void exportSearchEcomizeActivityList(HttpServletResponse response) {
		ServletOutputStream outputStream = null;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		try{
			// 处理日期 2019-12-03 00:00:00 ~ 2019-12-11 00:00:00
			String startDate ="";
			String endDate="";
			String selectDate = request.getParameter("selectDate");
			String activityName = request.getParameter("activityName");

			if(selectDate != null && !"".equals(selectDate) && selectDate.indexOf("~") !=-1){
				String[] splitDate = selectDate.split("~");
				startDate = splitDate[0].trim();
				endDate = splitDate[1].trim();
			}
			
            //获取活动信息
            List<EcomizeDateInfoPojo>  activityList = ecomizeActivityMapper.findEcomizeActivityByListForExport(activityName);

            if(CollectionUtils.isNotEmpty(activityList)){
                for (EcomizeDateInfoPojo activity : activityList) {
                    // 分类名称
                    List<EcomizeActivityTypeModel> typeList = ecomizeActivityMapper.findActivityTypeByActivity(activity.getId());

                    if(CollectionUtils.isNotEmpty(typeList) && typeList != null){
                        String typeName = "";
                        for (EcomizeActivityTypeModel type : typeList) {
                            if(type.getName() != null){
                                typeName += type.getName() +"/";
                            }
                        }
                        activity.setType_name(typeName.substring(0,typeName.length() - 1));
                    }

                    // 参与人数
                    int takeNumber = ecomizeActivityMapper.findEcomizeActivityTakeNumber(activity.getId(),startDate,endDate);
                    activity.setTakeNumber(takeNumber);
                    //  提交订单人数
                    int putNumber = ecomizeActivityMapper.findEcomizeActivityPutNumber(activity.getId(),startDate,endDate);
                    activity.setPutNumber(putNumber);
                    //   拉新人数
                    int helpNumber = ecomizeActivityMapper.findEcomizeActivityHelpNumber(activity.getId(),startDate,endDate);
                    activity.setHelpNumber(helpNumber);
                    //   助力人次
                    int newNumber = ecomizeActivityMapper.findEcomizeActivityNewNumber(activity.getId(),startDate,endDate);
                    activity.setNewNumber(newNumber);
                }
            }

			//创建poi导出数据对象
			SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();

			//创建sheet页
			SXSSFSheet sheet = (SXSSFSheet) sxssfWorkbook.createSheet("导出测试");

			//创建表头
			SXSSFRow headRow = (SXSSFRow) sheet.createRow(0);
			//设置表头信息
			headRow.createCell(0).setCellValue("活动id");
			headRow.createCell(1).setCellValue("活动名称");
			headRow.createCell(2).setCellValue("活动分类");
			headRow.createCell(3).setCellValue("新增活动时间");
			headRow.createCell(4).setCellValue("参与人数");
			headRow.createCell(5).setCellValue("提交订单人数");
			headRow.createCell(6).setCellValue("拉新人数");
			headRow.createCell(7).setCellValue("助力人次");

            activityList.forEach(obj -> {

				//填充数据
				SXSSFRow dataRow = (SXSSFRow) sheet.createRow(sheet.getLastRowNum() + 1);

				//活动id
				if (obj.getId() != null) {
					dataRow.createCell(0).setCellValue(obj.getId().toString());
				} else {
					dataRow.createCell(0).setCellValue("");
				}
				//活动名称 nickname
				if (obj.getName() != null) {
					dataRow.createCell(1).setCellValue(obj.getName());
				} else {
					dataRow.createCell(1).setCellValue("");
				}
				// 活动分类
				if (obj.getType_name() != null) { 
					dataRow.createCell(2).setCellValue(obj.getType_name());
				} else {
					dataRow.createCell(2).setCellValue("");
				}
				// 新增活动时间
				if (obj.getCreate_time() != null) {
					dataRow.createCell(3).setCellValue(simpleDateFormat.format(obj.getCreate_time()));
				} else {
					dataRow.createCell(3).setCellValue("");
				}
				// 参与人数
				if (obj.getTakeNumber() != null) {
					dataRow.createCell(4).setCellValue(obj.getTakeNumber().toString());
				} else {
					dataRow.createCell(4).setCellValue("");
				}
				// 提交订单人数
				if (obj.getPutNumber() != null) {
					dataRow.createCell(5).setCellValue(obj.getPutNumber().toString());
				} else {
					dataRow.createCell(5).setCellValue("");
				}
				// 拉新人数
				if (obj.getNewNumber() != null) {
					dataRow.createCell(6).setCellValue(obj.getNewNumber().toString());
				} else {
					dataRow.createCell(6).setCellValue("");
				}
				// 助力人次
				if (obj.getHelpNumber() != null) {
					dataRow.createCell(7).setCellValue(obj.getHelpNumber().toString());
				} else {
					dataRow.createCell(7).setCellValue("");
				}
			});
			//下载导出
			String fileName = "导出测试";

			// 设置头信息
			this.request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/vnd.ms-excel");

			//一定要设置成xlsx格式
			response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName
					.getBytes("gb2312"), "ISO-8859-1") + ".xlsx");

			//创建一个输出流
			outputStream = response.getOutputStream();

			//写入数据
			sxssfWorkbook.write(outputStream);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (outputStream != null) {
					outputStream.flush();
					outputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

前端:

1.绑定Onclick事件:
在这里插入图片描述
2.监听搜索
在这里插入图片描述
3.searchDownload()方法
在这里插入图片描述
导出测试:
在这里插入图片描述

2、导入案例

其实导入就是导出的反向,导入的基本操作就是根据导入的文件,读取并解析里面的数据[上面有案例怎么解析Excel数据],然后拿到解析的数据后根据自己的业务需求对解析到的数据进行处理,这里不做详细展示

3、下载Excel模板

本质还是导出,基本操作和导出一样,只不过下载模板只有表头没有其他数据而已

controller层:

	@GetMapping("/downloadBonusExcel")
    public void downloadBonusExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        managerService.downloadBonusExcel(request,response);
    }

实现类:

@Override
    public void downloadBonusExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 文件名
        String fileName = "下载模板测试";
        ServletOutputStream outputStream = null;
        try {
            //创建poi导出数据对象
            SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
            //创建sheet页
            SXSSFSheet sheet =sxssfWorkbook.createSheet();
            //创建表头
            SXSSFRow headRow =sheet.createRow(0);
            //设置表头信息
            headRow.createCell(0).setCellValue("奖金数额");
            headRow.createCell(1).setCellValue("手机号");
            headRow.createCell(2).setCellValue("备注");

            // 设置头信息
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            //一定要设置成xlsx格式
            response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO-8859-1") + ".xlsx");
            //创建一个输出流
            outputStream = response.getOutputStream();

            //写入数据
            sxssfWorkbook.write(outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            outputStream.close();
        }
    }

说明:

File file = new File(filePath);
//这样也能获取到outputStream 
OutputStream outputStream = new FileOutputStream(file);

这里列举一下其他常用的文件设置格式:

标签:sheet,int,Excel,System,文教,createCell,POI,Apache,setCellValue
来源: https://blog.csdn.net/qq_44799924/article/details/116533104