1、POI概述

在企业级应用开发中,Excel报表是一种最常见的报表需求。Excel报表开发一般分为两种形式:

  • 基于Excel报表批量上传数据
  • 通过Java代码生成Excel报表

Java中常见的用来操作Excel的方式一般有2种:JXL和POI

  • JXL只能对Excel进行操作,属于比较老的框架,它只支持到Excel 95-2000的版本。现在已经停止更新和维护。
  • POI是Apache的项目,可对微软的Word、Excel、PPT进行操作:包括office2003和2007,Excl2003和2007。POI现在一直有更新。

Apache POI是Apache软件基金会的开源项目,由Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java语言操作Microsoft Office的功能。使用场景:

  • 数据报表生成
  • 数据备份
  • 数据批量上传

2、准备工作

2.1、创建项目导入依赖

<dependencies><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.0.1</version></dependency>
</dependencies>

2.2、POI常用API介绍

2.3、自定义工具类

自定义生成Excel报表文件有很多不尽如意的地方,特别是针对复杂报表头,单元格样式,字体等操作。手写这些代码不仅费时费力,有时候效果还不太理想。怎么样才能更方便的对报表样式,报表头进行处理呢?答:使用已经准备好的Excel模板,只需要关注模板中的数据即可。

2.3.1、准备模板文件,比如:

2.3.2、自定义注解

// 用来修饰实体类的字段:指定属性用来封装excel表的哪一列数据
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAttribute {/** 对应的列名称 */String name() default "";/** 列序号 */int sort();/** 字段类型对应的格式 */String format() default "";
}

2.3.3、创建实体类

// 用来封装数据库的每条记录:对应excel的一条记录
public class Employee {// 编号@ExcelAttribute(sort = 0)private String id;// 姓名@ExcelAttribute(sort = 1)private String username;// 手机@ExcelAttribute(sort = 2)private String mobile;// 最高学历@ExcelAttribute(sort = 3)private String edu;// 籍贯@ExcelAttribute(sort = 4)private String province;// 生日@ExcelAttribute(sort = 5)private String birthday;// 入职时间@ExcelAttribute(sort = 6)private Date joinDate;// 省略setters & getters
}

2.3.4、导出工具类

// 基本模板的Excel导出工具类
public class ExcelExportUtil<T> {// 写入数据的起始行private int rowIndex;// 需要提取样式所在的行号private int styleIndex;// 对象的字节码private Class clazz;// 对象中的所有属性private  Field fields[];// 构造方法public ExcelExportUtil(Class clazz,int rowIndex,int styleIndex) {this.clazz = clazz;this.rowIndex = rowIndex;this.styleIndex = styleIndex;fields = clazz.getDeclaredFields();}/*** 基于注解导出* response:响应对象,用于往浏览器导出数据(文件下载)* is:模板文件对应的输入流* objs:要导出的数据,即从数据库中查询的对象数据集合* fileName:导出的文件名(文件下载名)*/public void export(HttpServletResponse response,InputStream is, List<T> objs,String fileName) throws Exception {// 根据模板创建工作簿XSSFWorkbook workbook = new XSSFWorkbook(is);// 获得工作表Sheet sheet = workbook.getSheetAt(0);// 获取公共样式CellStyle[] styles = getTemplateStyles(sheet.getRow(styleIndex));AtomicInteger datasAi = new AtomicInteger(rowIndex);// 遍历集合for (T t : objs) {// 创建每一行对象Row row = sheet.createRow(datasAi.getAndIncrement());for(int i=0;i <styles.length; i++) {// 创建一个单元格对象(每一列)Cell cell = row.createCell(i);// 设置列的样式cell.setCellStyle(styles[i]);// 遍历成员变量对象for (Field field : fields) {// 判断成员变量上是否使用了ExcelAttribute注解if(field.isAnnotationPresent(ExcelAttribute.class)){// 暴露反射field.setAccessible(true);// 获得注解对象ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);if(i == ea.sort()) {// 设置单元格内容cell.setCellValue(field.get(t).toString());}}}}}// 将excel文件导出到浏览器fileName = URLEncoder.encode(fileName, "UTF-8");response.setContentType("application/octet-stream");response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("ISO8859-1")));response.setHeader("filename", fileName);workbook.write(response.getOutputStream());}/*** 获得指定行的单元格样式*/public CellStyle[] getTemplateStyles(Row row) {CellStyle [] styles = new CellStyle[row.getLastCellNum()];for(int i=0;i<row.getLastCellNum();i++) {styles[i] = row.getCell(i).getCellStyle();}return styles;}// 省略 setters & getters ..................
}

2.3.5、导入工具类

// 基于注解实现Excel报表数据导入
public class ExcelImportUtil<T> {// 对象的字节码private Class clazz;// 对象的所有属性private  Field fields[];public ExcelImportUtil(Class clazz) {this.clazz = clazz;fields = clazz.getDeclaredFields();}/*** 基于注解读取excel文档数据*   is:上传文件的字节输入流*  rowIndex:读取数据的起始行*  cellIndex:读取数据的起始单元格索引*/public List<T> readExcel(InputStream is, int rowIndex,int cellIndex) {// 创建集合:用来每一行记录(对象)List<T> list = new ArrayList<T>();// 实体对象T entity = null;try {// 根据字节输入流创建工作簿XSSFWorkbook workbook = new XSSFWorkbook(is);//获得工作表Sheet sheet = workbook.getSheetAt(0);// 获得总行数int rowLength = sheet.getLastRowNum();// 遍历每行数据for (int rowNum = rowIndex; rowNum <= sheet.getLastRowNum(); rowNum++) {// 获得每一行的行对象Row row = sheet.getRow(rowNum);// 通过反射创建实体对象:一行对应一个实体对象entity = (T) clazz.newInstance();// 遍历每一列for (int j = cellIndex; j < row.getLastCellNum(); j++) {// 获得单元格对象Cell cell = row.getCell(j);// 遍历成员变量对象for (Field field : fields) {// 判断成员变量上是否使用了注解:ExcelAttributeif(field.isAnnotationPresent(ExcelAttribute.class)){// 暴露反射field.setAccessible(true);// 获得ExcelAttribute注解对象ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);if(j == ea.sort()) {// 给对象的成员变量赋值field.set(entity, covertAttrType(field, cell));break;}}}}// 将对象添加到集合中list.add(entity);}} catch (Exception e) {e.printStackTrace();}// 返回集合return list;}/*** 类型转换 将cell 单元格格式转为 字段类型*/private Object covertAttrType(Field field, Cell cell) throws Exception {String fieldType = field.getType().getSimpleName();if ("String".equals(fieldType)) {return getValue(cell);}else if ("Date".equals(fieldType)) {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(getValue(cell)) ;}else if ("int".equals(fieldType) || "Integer".equals(fieldType)) {return Integer.parseInt(getValue(cell));}else if ("double".equals(fieldType) || "Double".equals(fieldType)) {return Double.parseDouble(getValue(cell));}else {return null;}}/*** 格式转为String* @param cell* @return*/public String getValue(Cell cell) {if (cell == null) {return "";}switch (cell.getCellType()) {case STRING:return cell.getRichStringCellValue().getString().trim();case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {Date dt = DateUtil.getJavaDate(cell.getNumericCellValue());return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(dt);} else {// 防止数值变成科学计数法String strCell = "";Double num = cell.getNumericCellValue();BigDecimal bd = new BigDecimal(num.toString());if (bd != null) {strCell = bd.toPlainString();}// 去除 浮点型 自动加的 .0if (strCell.endsWith(".0")) {strCell = strCell.substring(0, strCell.indexOf("."));}return strCell;}case BOOLEAN:return String.valueOf(cell.getBooleanCellValue());default:return "";}}// 省略 setters & getters ..................
}

3、报表导入和导出测试

 /*** 导出Excel,导出员工*/
@RequestMapping(value = "/emp/export", method = RequestMethod.GET)
public void export() throws Exception {// 1.构造数据List<Employee> list = null; // 查询数据库获得数据// 2.加载模板数据Resource resource = new ClassPathResource("excel.xlsx");FileInputStream fis = new FileInputStream(resource.getFile());// 3. 导出数据new ExcelExportUtil(Employee.class,2,2).export(response,fis,list,"员工报表.xlsx");
}/*** 导入Excel,添加员工*/
@RequestMapping(value="/emp/import",method = RequestMethod.POST)
public Result importUser(@RequestParam(name="file") MultipartFile file) throws Exception {// 1.解析ExcelList<Employee> list = new ExcelImportUtil(Employee.class).readExcel(file.getInputStream(),1,1)// 2.批量保存员工employeeService.saveAll(lis);return new Result(ResultCode.SUCCESS);
}

Apache POI 实现报表导入和导出相关推荐

  1. sql2java-excel(二):基于apache poi实现数据库表的导出的spring web支持

    sql2java是我几年年开始写的一个sql2java是一个轻量级数据库(SQL)访问代码(java)生成器.这几年一直在根据工作需要维护升级,最近的项目中需要对数据库的记录提供导出excel的功能. ...

  2. sql2java-excel(一):基于apache poi实现数据库表的导出及支持spring web

    sql2java是我几年年开始写的一个sql2java是一个轻量级数据库(SQL)访问代码(java)生成器.这几年一直在根据工作需要维护升级,最近的项目中需要对数据库的记录提供导出excel的功能. ...

  3. POI实现Excel导入和导出(源码测试)

    简介: Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 注意: 1.HSSFworkbook对象导 ...

  4. 使用POI导入和导出 Excel文件

    来源:http://www.blogjava.net/caihualin/archive/2008/05/12/164724.html 1.ExcelWriter.java package com.e ...

  5. Phoenix 数据导入与导出

    Phoenix 官方提供了相应的导入和导出的方案,分别位于: 导入:https://phoenix.apache.org/bulk_dataload.html 导入.导出:https://phoeni ...

  6. 玩转POI、EasyExcel报表导入导出!

    POI.EasyExcel报表导出 前言 一.POI操作Excel 1.1 导入依赖包 1.2 编写测试代码: 1.3 03和07版本的区别 二.大文件写入 2.1 大文件写HSSF 2.2 大文件写 ...

  7. SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」(亲测)

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 来源:Springboot使用POI实现导出Excel文件示例的搜索结果-阿里云开 ...

  8. SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  9. Springboot使用Apache POI实现导入导出和解析Excel

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站 点击跳转浏览. 1准备pom文件 <?xml version="1.0" e ...

最新文章

  1. php 获取下拉框选中的文本,jQuery实现select下拉框获取当前选中的文本
  2. file:///f:winwwwxml2.php,php simplexml_load_file 中文乱码的解决方法
  3. iOS知识小集·NSNumber to NSString出错啦
  4. 前端进阶-Event
  5. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) Stone Games
  6. WEB/H5性能优化总结
  7. k8s 基础概念和术语
  8. 前端开发课件 202002
  9. ortp编程示例代码
  10. 一周年工作总结--wfdb库使用
  11. 足以封神的文献下载网站,知道一个你就赚了!
  12. SUN SPARC T4-4电源故障引起的宕机
  13. 完全教程 Aircrack-ng破解WEP、WPA-PSK加密利器[zz]
  14. matlab输入二项分布函数,MATLAB如何使用binopdf函数计算二项分布的概率
  15. 关于用Unity实现校区AR导航毕业设计的建议
  16. win10可以上网但显示无法连接到Internet
  17. 蓝牙mesh- Features和设备类型
  18. Scrum大白话总结
  19. 关于java行业的一些见闻与感悟
  20. 基于Echarts实现可视化数据大屏大数据平台车辆监控系统HTML模板

热门文章

  1. 基于SSM的手表商城系统设计与实现
  2. js设置canvas的宽高(动态设置canvas的宽高)
  3. IDM(Internet Download Manager)最新一款 功能最全/电脑必备的下载器激活序列号版
  4. 【计算机毕业设计】心理健康教育系统
  5. 创造性平面设计思维是如何养成的
  6. java跟微服务什么关系_分布式和微服务是什么关系?
  7. 修改word文件属性
  8. ISFP型人格的优势和劣势分析(mbti性格测试)
  9. android:登录界面记住密码
  10. win 10查看wifi密码