内容简介:为了准确性,演示的例子都是完整的单元测试代码,都可以在测试路径找到源代码,各位客官可以clone下来跑一下看效果,包括上面这个复杂例子(ApplicantExample)喔
Octopus
(就是一个名字而已~) 是一个简单的java excel导入导出工具。目的是不用接触Apache POI的API就可以完成简单的Excel导出导入。 同时,可以自定义表格样式,导入检验数据合法和转换数据。
最大的特点就是导出复杂结构对象时自动绘制表头
不BB,直接上图
为了准确性,演示的例子都是完整的单元测试代码,都可以在测试路径找到源代码,各位客官可以clone下来跑一下看效果,包括上面这个复杂例子(ApplicantExample)喔
从Maven导入
为了方便使用,直接用Github做了一个私人仓库
增加仓库
<repositories> <repository> <id>chenhuanming-repo</id> <name>chenhuanming-repo</name> <url>https://raw.githubusercontent.com/zerouwar/my-maven-repo/master</url> </repository> </repositories> 复制代码
引入依赖
<dependency> <groupId>cn.chenhuanming</groupId> <artifactId>octopus</artifactId> <version>1.0.0</version> </dependency> 复制代码
导出Excel
从最简单的例子开始
我们从最简单的例子开始——导出一些地址数据。 Address
类只有两个属性
@Data @AllArgsConstructor @NoArgsConstructor public class Address { private String city; private String detail; } 复制代码
在导出前,我们需要创建一个XML文件定义怎样去导出
<?xml version="1.0" encoding="UTF-8"?> <Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/zerouwar/my-maven-repo/master/cn/chenhuanming/octopus/1.0.0/octopus.xsd" class="cn.chenhuanming.octopus.entity.Address"> <Field name="city" description="City"/> <Field name="detail" description="Detail"/> </Root> 复制代码
首先,创建 Root
根元素。这里引用 octopus.xsd 文件帮助我们编写XML
然后,赋值 class
属性,代表我们要导出的类全限定名
最后,创建两个 Field
元素,代表要导出类的两个属性
name
属性值就是 Address
里的属性名,实际上Octopus调用其getter方法获取值,所以要确保有getter方法
description
属性会被用在绘制表头
我们可以开始做最后一件事,编写 Java 代码
public class AddressExample { List<Address> addresses; /** * make testing data */ @Before public void prepare() { addresses = new ArrayList<>(); DataFactory df = new DataFactory(); for (int i = 0; i < df.getNumberBetween(5, 10); i++) { addresses.add(new Address(df.getCity(), df.getAddress())); } } @Test public void export() throws FileNotFoundException { //where to export String rootPath = this.getClass().getClassLoader().getResource("").getPath(); FileOutputStream os = new FileOutputStream(rootPath + "/address.xlsx"); //read config from address.xml InputStream is = this.getClass().getClassLoader().getResourceAsStream("address.xml"); ConfigReader configReader = Octopus.getXMLConfigReader(is); try { Octopus.writeOneSheet(os, configReader, "address", addresses); } catch (IOException e) { System.out.println("export failed"); } } } 复制代码
这是一个完整的单元测试代码,不过导出Excel其实只要两步:
ConfigReader Octopus.writeOneSheet()
下面是导出的Excel文件
自动绘制表头
Octopus支持导出复杂对象时自动绘制表头
这次我们来导出一些公司数据,这里是 Company
类
@Data @AllArgsConstructor @NoArgsConstructor public class Company { private String name; private Address address; } 复制代码
然后我们创建一个 company.xml 配置文件
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/zerouwar/my-maven-repo/master/cn/chenhuanming/octopus/1.0.0/octopus.xsd" class="cn.chenhuanming.octopus.entity.Address"> <Field name="name" description="Name" color="#ff0000"/> <Header name="address" description="Address"> <Field name="city" description="City"/> <Field name="detail" description="Detail"/> </Header> </Root> 复制代码
我们用 Header
元素代表要导出 Company
的一个复杂属性,同时设置字体颜色是红色
Java代码基本跟之前的一样
public class CompanyExample { List<Company> companies; /** * make testing data */ @Before public void prepare() { companies = new ArrayList<>(); DataFactory df = new DataFactory(); for (int i = 0; i < df.getNumberBetween(5, 10); i++) { companies.add(new Company(df.getBusinessName(), new Address(df.getCity(), df.getAddress()))); } } @Test public void export() throws FileNotFoundException { //where to export String rootPath = this.getClass().getClassLoader().getResource("").getPath(); FileOutputStream os = new FileOutputStream(rootPath + "/company.xlsx"); //read config from company.xml InputStream is = this.getClass().getClassLoader().getResourceAsStream("company.xml"); ConfigReader configReader = Octopus.getXMLConfigReader(is); try { Octopus.writeOneSheet(os, configReader, "company", companies); } catch (IOException e) { System.out.println("export failed"); } } } 复制代码
最后是导出的Excel文件
Octopus可以处理更复杂的数据,你可以在 cn.chenhuanming.octopus.example.ApplicantExample
查看这个更复杂的例子
转换数据
有时你想转换导出的数据。例如,在上一个例子中,我们不想导出整个 Address
对象,把它当做一个字符串导出
我们所需要做的只是实现一个 Formatter
public class AddressFormatter implements Formatter<Address> { @Override public String format(Address address) { return address.getCity() + "," + address.getDetail(); } @Override public Address parse(String str) { String[] split = str.split(","); if (split.length != 2) { return null; } return new Address(split[0], split[1]); } } 复制代码
parse
方法用于导入Excel时,只要关注 format
方法。这里接受一个Address对象,返回一个字符串。
最后,配置 AddressFormatter
到XML文件
<Field name="name" description="Name" color="#ff0000"/> <Field name="address" description="Address" formatter="cn.chenhuanming.octopus.formatter.AddressFormatter"/> 复制代码
最后导出的结果
导入Excel
我们直接拿上一个例子的导出结果来演示导入,共用同一个 ConfigReader
,直接编写导入的代码
//First get the excel file FileInputStream fis = new FileInputStream(rootPath + "/company2.xlsx"); try { SheetReader<Company> importData = Octopus.readFirstSheet(fis, configReader, new DefaultCellPosition(1, 0)); for (Company company : importData) { System.out.println(company); } } catch (Exception e) { System.out.println("import failed"); } 复制代码
在控制台可以看到打印导入结果,可以看到,之前的 AddressFormatter
也完成了数据的转换工作
Company(name=Graham Motor Services, address=Address(city=Monroe, detail=666 Bonnair Ave)) Company(name=Social Circle Engineering, address=Address(city=Fort Gaines, detail=956 Third Ridge)) Company(name=Enigma Cafe, address=Address(city=Mcdonough, detail=1278 Midway Trail)) Company(name=Hapeville Studios, address=Address(city=Riceboro, detail=823 Tuscarawas Blvd)) Company(name=Thalman Gymnasium, address=Address(city=Ebenezer, detail=1225 Blackwood Avenue)) Company(name=Sparks Pro Services, address=Address(city=Darien, detail=1362 Woodlawn Lane)) Company(name=Toccoa Development, address=Address(city=Ridgeville, detail=1790 Lawn Ave)) 复制代码
导入校验数据
有时候我们对导入的数据有一定的要求,Octopus提供简单的数据校验配置
首先给我们的 Company
增加一个 status
属性,只能是 good , bad 和 closed 三个值其中一个,同时 name
不可以为空,看一下XML配置文件
<?xml version="1.0" encoding="UTF-8"?> <Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/zerouwar/my-maven-repo/master/cn/chenhuanming/octopus/1.0.0/octopus.xsd" class="cn.chenhuanming.octopus.entity.Company"> <Field name="name" description="Name" color="#ff0000" is-blankable="false"/> <Field name="address" description="Address" formatter="cn.chenhuanming.octopus.formatter.AddressFormatter" /> <Field name="status" description="Status" options="good|bad|closed"/> <!--| split options --> </Root> 复制代码
这是我们要导入的Excel,可以看到里面有非法数据
看一下怎么编写Java代码
@Test public void importCheckedData() throws IOException, InvalidFormatException { InputStream is = this.getClass().getClassLoader().getResourceAsStream("wrongCompany.xlsx"); ConfigReader configReader = new XmlConfigReader(this.getClass().getClassLoader().getResourceAsStream("company3.xml")); final SheetReader<CheckedData<Company>> sheetReader = Octopus.readFirstSheetWithValidation(is,configReader,new DefaultCellPosition(1,0)); for (CheckedData<Company> checkedData : sheetReader) { System.out.println(checkedData); } } 复制代码
这里我们调用 Octopus.readFirstSheetWithValidation
,获取带校验结果的 SheetReader
,看一下导入的结果
CheckedData(data=Company(name=Graham Motor Services, address=Address(city=Monroe, detail=666 Bonnair Ave), status=good), exceptions=[]) CheckedData(data=Company(name=Social Circle Engineering, address=Address(city=Fort Gaines, detail=956 Third Ridge), status=null), exceptions=[cn.chenhuanming.octopus.exception.NotAllowValueException]) CheckedData(data=Company(name=null, address=Address(city=Mcdonough, detail=1278 Midway Trail), status=null), exceptions=[cn.chenhuanming.octopus.exception.CanNotBeBlankException, cn.chenhuanming.octopus.exception.NotAllowValueException]) 复制代码
可以看到每一个 CheckData
有一个 data
属性和一个 exceptions
列表。 这个异常列表存放着导入时每一个单元格可能出现的校验错误,异常类型都是 ParseException
除了 is-blankable
和 options
,还可以通过 regex
配置正则表达式检查。当校验错误时,会抛出对应的 ParseException
子类
-
is-blankable
:抛出CanNotBeBlankException
-
options
:抛出NotAllowValueException
-
regex
:抛出PatternNotMatchException
你可以通过这些异常来进行跟进一步的处理。如果上面三种校验方式不能满足需求,在 Formatter
的 parse
抛出自定义的 ParseException
。Octopus会捕获它们放到 exceptions
列表中,并自动把单元格位置和你的配置内容塞到 ParseException
中,这样你可以自己选择处理这些异常数据
以上代码都可以在测试路径 cn.chenhuanming.octopus.example
找到,通过这些例子可以感受下Octopus的魅力
Q&A
没有Java注解配置?
目前只提供XML配置,因为XML和类文件解耦,有时候你无法修改类代码时,尤其是导出场景,XML会是更好的选择。如果你是"anti-xml",可以实现注解版 ConfigReader
,把注解配置转换成 Field
,这应该不会很难。后面我有空再弄注解配置吧~
以上所述就是小编给大家介绍的《不想用POI?几行代码完成Excel导出导入》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Phoenix 数据导入与导出
- Angular Excel 导入与导出
- MongoDB导入导出备份恢复实践
- JS module的导出和导入
- ASP.NET 开源导入导出库Magicodes.IE 导出Pdf教程
- 使用oracle自带的命令进行导入导出
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。