项目地址:http://git.oschina.net/lis1314/easy-exceljava
使用easy-excel 完成Excel导入导出功能git
下面有以下的几个模型spring
学生模型,图书模型,做者模型数据库
//学生模型 public class StudentModel { /** ID */ protected String id; /** 建立时间 */ protected Date createTime; /** 姓名 */ private String name; /** 年龄 */ private Integer age; /** 学号 */ private String studentNo; /** 建立人 */ private String createUser; /** 建立人ID */ private String createUserId; /** 状态 */ private Integer status; /** 图书信息 */ private BookModel book; //略 getter setter... } //图书模型 public class BookModel { /** 图书名称 */ private String bookName; /** 做者信息 */ private AuthorModel author; //略 getter setter... } //做者模型 public class AuthorModel { /** 做者姓名 */ private String authorName; //略 getter setter... }
有以下的Excel文件格式,须要映射成学生实体类app
那么使用easy-excel 如何导入呢?jvm
前两行是属于不规则的数据,从标题行之后才是规则的数据,也就是从规则数据以后才能正常转换成JavaBean。maven
下面使用easy-excel进行导入测试
一、下载easy-excel,引入到本身的工程,它是一个jar的maven工程,直接添加依赖便可字体
http://git.oschina.net/lis1314/easy-excelui
二、具体实现代码,首先编写配置文件:excel-config.xml
<excels> <excel id="student" class="org.easy.excel.test.model.StudentModel"> <field name="id" title="ID"/> <field name="name" title="学生姓名"/> <field name="age" title="年龄" isNull="false" regex="^[1-9]\d*$" regexErrMsg="必须是数字"/> <field name="studentNo" title="学号" isNull="false" /> <field name="createTime" title="建立时间" pattern="yyyy-MM-dd,yyyy/MM/dd"/> <field name="status" title="状态" format="1:正常,0:禁用,-1:无效" /> <field name="createUser" title="建立人"/> <!-- 复杂对象 --> <field name="book.bookName" title="图书名称" /> <field name="book.author.authorName" title="做者名称"/> </excel> </excels>
解释,每一个excel表示一种Excel文件到JavaBean的映射规则,该规则能够是导入和导出
标签解释
配置了一个id为student的映射,要映射对应的JavaBean实体为 StudentModel
<excel id="student" class="org.easy.excel.test.model.StudentModel">
excel文件中标题为ID的列,把它的值映射到 StudentModel .id属性上
<field name="id" title="ID"/>
isNull属性,表示在excel文件中标题为【年龄】的单元格的值不能为空,而且符合正则【 regex 】,当正则校验没有经过时,会提示【xxx行,[ 年龄 ]必须是数字,若是为空同理,xxx行[年龄]不能为空】
<field name="age" title="年龄" isNull="false" regex="^[1-9]\d*$" regexErrMsg="必须是数字"/>
pattern:不作过多解释,SimpleDateFormat(pattern),导入数据时字符串的值如何转换成日期
支持多种映射pattern,使用【英文逗号】进行分割
<field name="createTime" title="建立时间" pattern="yyyy-MM-dd,yyyy/MM/dd"/>
format属性,观察上面的excel文件结构会发现状态列是中文,那么导入时,可能javaBean中并非中文,而是数字或其余,那么如何把它转换成数字呢?format就是作这个事情的。导入时它会以【,分割:前面的做为导入时使用的值,:后面的做为导出时使用的值】:后面值进行逆推,导出时同理。思考一个问题?若是这个值不肯定如何解决,或者这个值须要到数据库校验?好比是个城市地址,这个时候是须要查询数据库进行比对的,若是地址不存在则抛出错误提示信息的,就说这么多,easy-excel已经作好了,支持自定义的转换器能够解决。
<field name="status" title="状态" format="1:正常,0:禁用,-1:无效" />
把excel文件标题为【图书名称】的值映射到 StudentModel 类中的book类中的bookName属性上
<field name="book.bookName" title="图书名称" />
-----------不每条配置都解释了,明白标签的做用我想你们能看懂。下面展现Java代码
public class ImportTest { public static void main(String[] args) throws Exception { //准备excel文件流 InputStream excelStream = new FileInputStream("C:/Users/Administrator/Desktop/stu.xlsx"); //建立excel上下文实例,它的构成须要配置文件的路径 ExcelContext context = new ExcelContext("excel-config.xml"); //按照xml配置中id为student的配置形式读取excel文件,并转换成StudentModel //这里的第二个参数是值,标题是第几行开始,以前也说了标题以前的数据并非规则的数据 ExcelImportResult result = context.readExcel("student", 2,excelStream); //打印导入结果,查看标题以前不规则的数据 List<List<Object>> header = result.getHeader(); System.out.println(header.get(0)); System.out.println(header.get(1)); //查看学生集合导入结果 List<StudentModel> students = result.getListBean(); for(StudentModel stu:students){ System.out.println(stu); } } }
运行结果:
[共导出【10】条数据] [本次批次号为:XXX] StudentModel [id=1, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三0, age=20, studentNo=Stu_0, createUser=王五0, createUserId=null, status=1, book=BookModel [bookName=Thinking in java, author=AuthorModel [authorName=Bruce Eckel]]] StudentModel [id=2, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三1, age=21, studentNo=Stu_1, createUser=王五1, createUserId=null, status=0, book=null] StudentModel [id=3, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三2, age=22, studentNo=Stu_2, createUser=王五2, createUserId=null, status=1, book=BookModel [bookName=Thinking in java, author=AuthorModel [authorName=Bruce Eckel]]] StudentModel [id=4, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三3, age=23, studentNo=Stu_3, createUser=王五3, createUserId=null, status=0, book=null] StudentModel [id=5, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三4, age=24, studentNo=Stu_4, createUser=王五4, createUserId=null, status=1, book=BookModel [bookName=Thinking in java, author=AuthorModel [authorName=Bruce Eckel]]] StudentModel [id=6, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三5, age=25, studentNo=Stu_5, createUser=王五5, createUserId=null, status=0, book=null] StudentModel [id=7, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三6, age=26, studentNo=Stu_6, createUser=王五6, createUserId=null, status=1, book=BookModel [bookName=Thinking in java, author=AuthorModel [authorName=Bruce Eckel]]] StudentModel [id=8, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三7, age=27, studentNo=Stu_7, createUser=王五7, createUserId=null, status=0, book=null] StudentModel [id=9, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三8, age=28, studentNo=Stu_8, createUser=王五8, createUserId=null, status=1, book=BookModel [bookName=Thinking in java, author=AuthorModel [authorName=Bruce Eckel]]] StudentModel [id=10, createTime=Sat Jun 18 00:00:00 GMT+08:00 2016, name=张三9, age=29, studentNo=Stu_9, createUser=王五9, createUserId=null, status=0, book=null]
导入结束,完美导入,其实上面的代码有些都不少余,那么核心的代码是哪几行?
//准备excel文件流 InputStream excelStream = new FileInputStream("C:/Users/Administrator/Desktop/stu.xlsx"); //建立excel上下文实例,它的构成须要配置文件的路径 ExcelContext context = new ExcelContext("excel-config.xml"); //按照xml配置中id为student的配置形式读取excel文件,并转换成StudentModel //这里的第二个参数是值,标题是第几行开始,以前也说了标题以前的数据并非规则的数据 ExcelImportResult result = context.readExcel("student", 2,excelStream);
只有准备数据、建立上下文、读取excel。。一般在真实的常见建立上下文均可以省略了,由于它会交给spring容器管理,整个jvm中,只保持一个实例就够了。
关于导入配置的一个很重要的属性:cellValueConverter
在上面并无配置它,这个属性就是能够解决以前我标记为红色的问题。那么它是什么?
它是一个CellValueConverter接口的实现类:假设咱们的Excel中有地址,或者结合业务中多是其余,都是须要查询数据库,或者通过更复杂的业务逻辑进行校验的,那么咱们能够配置它。咱们来观察这个接口作了什么事?
/** * CellValue转换器,用于解析cell值的规则 * @author lisuo * */ public interface CellValueConverter { /** * 操做类型,导入或导出 */ enum Type { EXPORT, IMPORT } /** * 转换cell的值 * @param bean Excel配置的JavaBean对象 * @param value Excel原值 * @param fieldValue FieldValue信息 * @param type 导入或导出 * @param rowNum 行号 * @return 解析结果对应的value * @throws Exception */ public Object convert(Object bean,Object value, FieldValue fieldValue, Type type,int rowNum) throws Exception; }
核心只有一个方法convert
咱们能够自定义它的实现类,而后把全类名注册到 cellValueConverter属性上
如:假设建立人是须要查询用户表进行校验,若是没有则不容许导入,咱们则能够在自定义的实现类抛出一个异常, 能够精准的提示用户多少行,哪个字段【标题】的值错误了。
这里不在展现代码了,具体查看http://git.oschina.net/lis1314/easy-excel中的源代码
<field name="createUser" title="建立人" cellValueConverter="org.easy.excel.test.converter.CreateUserCellValueConverter"/>
如何使用easy-excel 进行导出?
以前的配置信息彻底不变,直接上java代码
public class ExportTest { public static void main(String[] args) throws Exception { //准备excel输出流 OutputStream ops = new FileOutputStream("C:/Users/Administrator/Desktop/exportStudent.xlsx"); //建立excel上下文实例,它的构成须要配置文件的路径 ExcelContext context = new ExcelContext("excel-config.xml"); //获取POI建立结果 Workbook workbook = context.createExcel("student",getStudents()); workbook.write(ops); ops.close(); workbook.close(); } //获取模拟数据,数据库数据... public static List<StudentModel> getStudents(){ int size = 10; List<StudentModel> students = new ArrayList<>(size); for(int i=0;i<size;i++){ StudentModel stu = new StudentModel(); stu.setId(""+(i+1)); stu.setName("张三"+i); stu.setAge(20+i); stu.setStudentNo("Stu_"+i); stu.setCreateTime(new Date()); stu.setStatus(i%2==0?1:0); stu.setCreateUser("王五"+i); //建立复杂对象 if(i % 2==0){ BookModel book = new BookModel(); book.setBookName("Thinking in java"); AuthorModel author = new AuthorModel(); author.setAuthorName("Bruce Eckel"); book.setAuthor(author); stu.setBook(book); } students.add(stu); } return students; } }
运行结果生成文件:
其余更多导出示例参看http://http://git.oschina.net/lis1314/easy-excel中的源代码
导出的一些疑问?支持样式么?支持在标题以前建立点其余的信息么?
目前支持cell宽度设置,sheet名称自定义,标题背景颜色,标题字体颜色,标题对齐方式,单元格样式是否与标题统同样式,默认cell对齐方式
对应相关标签
columnWidth,sheetname,titleBgColor,titleFountColor,align,enableStyle,defaultAlign。
支持导出前自定义头信息。
--上面红色标签部分为最新加入标签
补充:如何在本身工程中与spring无缝集成以及使用?
在你的spring.xml配置文件中加入
<!-- Excel上下文 --> <bean id="excelContext" class="org.easy.excel.ExcelContext"> <constructor-arg> <!--你本身的excel配置文件路径,支持classpath前缀,若是不写前缀,默认为classpath:--> <value>excel-config.xml</value> </constructor-arg> </bean> <!-- 初始化SpringUtil --> <bean id="springUtil" class="org.easy.util.SpringUtil"/>
关于海量数据导出问题,看以下代码,很是easy
/*** * 导出测试,分屡次导出 * @throws Exception */ @Test public void testExporPart()throws Exception{ //需求概述.数据量较大,可能大批量数据导出,会对DB形成压力,这里分批次检索数据,一部分一部分向Excel中写 OutputStream ops = new FileOutputStream(path); ExcelExportResult exportResult = context.createExcelForPart(excelId,getStudents()); //假设这是第二次从数据库或其余平台查询到到数据 exportResult.append(getStudents()); //第n次.... exportResult.append(getStudents()); exportResult.append(getStudents()); exportResult.append(getStudents()); exportResult.append(getStudents()); Workbook workbook = exportResult.build(); workbook.write(ops); ops.close(); workbook.close(); }
2016-09-02加入一下4个标签:
otherConfig:以下面XML注释,我遇到额需求是处理字典,只有Key不一样,其余逻辑如出一辙。那么我经过otherConfig达到动态传参的功能。
<!-- 当一个转换器处理多个字段时,可能逻辑同样,只有个别的参数不同,那么可使用otherConfig,动态传递 --> <field name="createUser" title="建立人" cellValueConverter="org.easy.excel.test.converter.CreateUserFieldValueConverter" otherConfig="Test动态传递的一个变量"/>
defaultValue:不管是导入仍是导出都给一个默认值
<!-- defaultValue,不管是导入仍是导出当值为空给一个默认值 --> <field name="book.price" title="图书价格" columnWidth="6000" defaultValue="0.00"/>
decimalFormatPattern:Number格式处理
<!-- 对Number类型进行处理,好比(12345.12),转换成(123,45.12),导入的规则是从字符到Number,导出是从Number到字符,基于标准的java.text.DecimalFormat --> <field name="book.price" title="图书价格" columnWidth="6000" decimalFormatPattern="###,##0.00" defaultValue="0.00"/>
roundingMode:结合上么的decimalFormatPattern标签,对于小数位数处理方案进行配置,默认向下取整
<!-- 当处理字符时,假设保留2位小数,那么遇到3位甚至更多的位数如何处理?经过该配置能够指定处理方式,默认向下取整 --> <field name="book.price" title="图书价格" columnWidth="6000" decimalFormatPattern="###,##0.00" roundingMode="up" defaultValue="0.00"/>
2017-03-21 变动:
主要对工程进行了重构,对一些包从新进行了划分以及命名
重命名resolveFieldValueConverterName配置为cellValueConverter
在ExcelDefinition中增长了
sheetIndex属性,支持指定sheet形式读取内容
增长了
ExcelUtil ,用于读取没有规则的Excel文件
ExcelDownLoadUtil,用于WEB环境Excel文件的下载
SpringMvcExcelView,用于WEB环境使用SpringMvc轻松实现下载
与SpringMvc整合
正常整合,把org.easy.util.view.SpringMvcExcelView添加到SpringMvc容器中,使用标准的Spring自定义视图跳转便可,参看org.easy.util.view.SpringMvcExcelView这个类的注释部分
2017-03-30 变动:支持多行导入校验
例子代码
//具体参看 ImportMultiValidateTest 测试类 ExcelImportResult result = context.readExcel(excelId, titleIndex, excelStream,true); //经过导入结果集的hasErrors方法判断 if(result.hasErrors()){ System.out.println("导入包含错误,下面是错误信息:"); for (ExcelError err:result.getErrors()) { System.out.println(err.getErrorMsg()); } } //运行结果 导入包含错误,下面是错误信息: 第[1行],[建立时间][D]不能转换成日期,正确的格式应该是:[yyyy-MM-dd] 第[1行],[状态][不正常]取值错误 第[2行],[做者名称]不能为空 第[4行],[做者名称]不能为空
更多信息请参考源代码工程中的org.easy.excel.test包下的几个类