Apache POI实现Excel文件导出
2017-10-25 19:17
337 查看
最近开发excel导入导出功能,使用的是Apache的POI技术
POI提供了很多对Microsoft Office的功能,本文仅仅讲解POI的Excel导出功能
版本如下:
几个关键对象:
HSSFWorkbook类就是一个excel文件
一个excel文件有很多页,HSSFSheet就是一个页
一页有很多行,HSSFRow代表一行
一行有很多格,HSSFCell代表一个单元格
前辈大牛充分发挥了Java的抽象,封装,继承,多态,写出了如此优雅的代码….尔等渣渣只能膜拜
我的想法是利用反射获取JavaBean的字段和值,写一个通用的Excel工具类,并可以在客户端选择保存路径,代码分为几个部分讲解:
第一部分:
因为传入的数据集合肯定是相同对象,所以获取第一个对象的类对象,并创建好excel文件,与第一页,页的名字就用表名来命名,并指定单元格居中显示
第二部分:
因为一个JavaBean有很多的属性,大部分情况下不会对全部的字段都需要导出,如何只导出指定对象的字段与值呢?作者在这里采用了注解来标识,利用Java反射获取对象的全部字段,但是却只对标识了注解的字段进行excel导出,还可以自己确定列名
注解代码:
注解使用代码:
获取了需要的字段名,并用数组存储好,就需要创建好第一行用来显示字段名,循环数组长度,确定有多少列,指定好列名(就是字段名),宽度与样式等,这里有个小问题,如果指定了列名的宽度就不要宽度自适应,两者只会产生一个效果
第三部分:
然后就需要循环数据集合开始导出数据了,这里有个需要注意的地方就是第一行已经被列名占用了,所以创建行肯定是从第二行开始,同样需要判断字段有没有注解,然后反射获取值。因为单元格设置值的方法不能是Object,很蛋疼,所以需要判断类型,然后转换再赋值,如果有更好的办法,欢迎指点作者与广大读者。
还有一个坑的地方就是循环字段时,会发生某个字段不需要导出,然后顺序就会发生断层,创建单元格的时候肯定就不能用这个循环变量来创建,需要另外的循环变量,代码中已指出,如果有更简单,更效率的办法,我是很欢迎大家来指点的啦
第四部分:
最后用response对象设置Http协议并指定编码,用uuid指定文件名,防止重复,用输出流输出到客户端。这里有个不懂的地方就是大部分浏览器都会弹出下载框,而chrome浏览器则会直接下载到桌面,如果有知道的,请指教。。。
一个基本的excel导出通用工具类就完成了….
还是那句话,这只是作者自己写的一个不入流的工具类,肯定还会有更优秀的代码,欢迎大家指点,方便作者与读者学习交流
POI提供了很多对Microsoft Office的功能,本文仅仅讲解POI的Excel导出功能
版本如下:
<!-- poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency>
几个关键对象:
HSSFWorkbook类就是一个excel文件
一个excel文件有很多页,HSSFSheet就是一个页
一页有很多行,HSSFRow代表一行
一行有很多格,HSSFCell代表一个单元格
前辈大牛充分发挥了Java的抽象,封装,继承,多态,写出了如此优雅的代码….尔等渣渣只能膜拜
我的想法是利用反射获取JavaBean的字段和值,写一个通用的Excel工具类,并可以在客户端选择保存路径,代码分为几个部分讲解:
第一部分:
//反射,获取类对象 Object obj = list.get(0); Class clazz = obj.getClass(); //创建excel工作簿 HSSFWorkbook wb = new HSSFWorkbook(); //创建页 ,指定页的名字就是表名,excel有很多页 HSSFSheet sheet = wb.createSheet(clazz.getSimpleName()); //设置单元格样式,居中显示 HSSFCellStyle style = wb.createCellStyle(); style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
因为传入的数据集合肯定是相同对象,所以获取第一个对象的类对象,并创建好excel文件,与第一页,页的名字就用表名来命名,并指定单元格居中显示
第二部分:
//获取字段对象 Field[] fields = clazz.getDeclaredFields(); //字段名数组,只需要标识了注解的字段 List<String> names = new ArrayList<String>(); for(int i=0,len=fields.length;i<len;i++){ //获取字段是否有导出标识注解 ExcelField field = fields[i].getAnnotation(ExcelField.class); if(field!=null) { //如果指定了列名,就使用列名,不然使用字段名 if(field.title()!=null){ names.add(field.title()); }else{ names.add(fields[i].getName()); } } } //创建第一行 HSSFRow row = sheet.createRow(0); for(int i=0,len=names.size();i<len;i++){ //创建单元格 HSSFCell cell = row.createCell(i); //指定值 cell.setCellValue(names.get(i)); //指定宽度 sheet.setColumnWidth(i,5000); //设置样式 cell.setCellStyle(style); //宽度自适应 // sheet.autoSizeColumn(i); }
因为一个JavaBean有很多的属性,大部分情况下不会对全部的字段都需要导出,如何只导出指定对象的字段与值呢?作者在这里采用了注解来标识,利用Java反射获取对象的全部字段,但是却只对标识了注解的字段进行excel导出,还可以自己确定列名
注解代码:
/** * Created by oldfish on 2017-10-20. * 导出注解类,用于标识字段是否需要导出 */ @Target({ElementType.FIELD})//只作用在字段上 @Retention(RetentionPolicy.RUNTIME)//运行时有效 public @interface ExcelField { //导出字段在excel的名字 String title(); }
注解使用代码:
@ExcelField(title = "编号") private Integer id; // 编号 @ExcelField(title = "用户IP") private String userIp; // 用户IP @ExcelField(title = "评论内容") private String content; // 评论内容 private Blog blog; // 被评论的博客 @ExcelField(title = "评论日期") private Date commentDate; // 评论日期 private Integer blogId; @ExcelField(title = "审核状态") private Integer state; // 审核状态 0 待审核 1 审核通过 2 审核未通过 private String commentDateStart; //开始日期 用于条件查询 private String commentDateEnd;//结束日期 用于条件查询
获取了需要的字段名,并用数组存储好,就需要创建好第一行用来显示字段名,循环数组长度,确定有多少列,指定好列名(就是字段名),宽度与样式等,这里有个小问题,如果指定了列名的宽度就不要宽度自适应,两者只会产生一个效果
第三部分:
for(int j=0,l=list.size();j<l;j++){ Object temp = list.get(j); Class c = temp.getClass(); Field[] fields1 = c.getDeclaredFields(); //一个对象创建一个行,从第二行开始 HSSFRow row1 = sheet.createRow(j+1); //用于作序号,因为循环的序号可能会发生有些属性不注入,序号就会断层 //需要另外用变量来维持序号 int k = 0; for(int i=0,len=fields1.length;i<len;i++){ //只有 有标识注解的属性才导出 ExcelField excelField = fields1[i].getAnnotation(ExcelField.class); if(excelField!=null) { //根据指定的属性创建指定的单元格 HSSFCell cell = row1.createCell(k); //设置值,因为不能直接放置Object,所以需要确定类型再转换 try { fields1[i].setAccessible(true); Object value = fields1[i].get(temp); if (value instanceof String) { cell.setCellValue(value.toString()); } else if (value instanceof Date) { Date date = (Date) value; cell.setCellValue(DateUtil.formatDate(date, "yyyy-MM-dd")); } else if (value instanceof Integer) { cell.setCellValue((Integer) value); } else if (value instanceof Double) { cell.setCellValue((Double) value); } else if (value instanceof Boolean) { cell.setCellValue((Boolean) value); } else if (value instanceof Float) { cell.setCellValue((Float) value); } else if (value instanceof Short) { cell.setCellValue((Short) value); } else if (value instanceof Character) { cell.setCellValue((Character) value); } } catch (IllegalAccessException e) { throw new RuntimeException("类型转换错误"); } //设置样式 cell.setCellStyle(style); k++; } } }
然后就需要循环数据集合开始导出数据了,这里有个需要注意的地方就是第一行已经被列名占用了,所以创建行肯定是从第二行开始,同样需要判断字段有没有注解,然后反射获取值。因为单元格设置值的方法不能是Object,很蛋疼,所以需要判断类型,然后转换再赋值,如果有更好的办法,欢迎指点作者与广大读者。
还有一个坑的地方就是循环字段时,会发生某个字段不需要导出,然后顺序就会发生断层,创建单元格的时候肯定就不能用这个循环变量来创建,需要另外的循环变量,代码中已指出,如果有更简单,更效率的办法,我是很欢迎大家来指点的啦
第四部分:
response.setContentType("application/vnd.ms-excel;charset=utf-8"); //文件名使用uuid,避免重复 response.setHeader("Content-Disposition", "attachment;filename=" + UUID.randomUUID() + ".xls"); OutputStream ouputStream = null; try { ouputStream = response.getOutputStream(); wb.write(ouputStream); ouputStream.flush(); ouputStream.close(); } catch (IOException e) { throw new RuntimeException("IO异常"); }
最后用response对象设置Http协议并指定编码,用uuid指定文件名,防止重复,用输出流输出到客户端。这里有个不懂的地方就是大部分浏览器都会弹出下载框,而chrome浏览器则会直接下载到桌面,如果有知道的,请指教。。。
一个基本的excel导出通用工具类就完成了….
还是那句话,这只是作者自己写的一个不入流的工具类,肯定还会有更优秀的代码,欢迎大家指点,方便作者与读者学习交流
相关文章推荐
- 将Table数据导出至Excel文件(中国移动实现的方式)
- ApachePOI实现将数据库表中的信息导出到Excel文件中
- java实现 Excel文件的导入导出(1)
- 基于apache poi根据模板导出excel的实现方法
- 将数据库表导出到Excel,并生成文件(C#实现)
- 【JavaWeb开发】使用java实现简单的Excel文件的导入与导出(POI)
- Jsp中的table多表头导出excel文件具体实现
- Laravel 5 中使用 Laravel Excel 实现 Excel/CSV 文件导入导出功能
- DataSet导出到Excel,并生成文件(C#实现,可合并行和列)
- python 读取文件 并实现文件相关操作最后导出excel
- Java程序员从笨鸟到菜鸟之(一百零五)java操作office和pdf文件(三)利用jxl实现数据导出excel报表以及与POI的区别
- 如何利用PHPExcel实现数据导出成excel文件
- CI中在Linux服务器下面实现文件导出Excel的方法解决方案
- 实现将 GridView 导出到 Excel文件中
- Java 实现导出excel表 POI/Java实现不同excel格式(*.xls、*.xlsx)文件的读取
- 基于Spring3 MVC实现批量导出数据成Excel文件!
- Java程序员从笨鸟到菜鸟之(一百零五)java操作office和pdf文件(三)利用jxl实现数据导出excel报表以及与POI的区别
- php导出 excel文件 实现方式
- Coolite优化导出Excel文件实现代码
- 在 Laravel 5 中使用 Laravel Excel 实现 Excel/CSV 文件导入导出功能