Repository: wuwz/ExcelKit
Branch: master
Commit: ccd3e660c19c
Files: 34
Total size: 94.0 KB
Directory structure:
gitextract_lm2w90xj/
├── .gitignore
├── README.md
├── pom.xml
└── src/
└── main/
└── java/
└── com/
└── wuwenze/
└── poi/
├── ExcelKit.java
├── annotation/
│ ├── Excel.java
│ └── ExcelField.java
├── config/
│ └── Options.java
├── convert/
│ ├── ReadConverter.java
│ └── WriteConverter.java
├── exception/
│ ├── ExcelKitAnnotationAnalyzeException.java
│ ├── ExcelKitConfigAnalyzeFailureException.java
│ ├── ExcelKitConfigFileNotFoundException.java
│ ├── ExcelKitEncounterNoNeedXmlException.java
│ ├── ExcelKitReadConverterException.java
│ ├── ExcelKitRuntimeException.java
│ ├── ExcelKitWriteConverterException.java
│ └── ExcelKitXmlAnalyzeException.java
├── factory/
│ └── ExcelMappingFactory.java
├── handler/
│ └── ExcelReadHandler.java
├── pojo/
│ ├── ExcelErrorField.java
│ ├── ExcelMapping.java
│ └── ExcelProperty.java
├── util/
│ ├── BeanUtil.java
│ ├── Const.java
│ ├── DateUtil.java
│ ├── POIUtil.java
│ ├── PathUtil.java
│ ├── RegexUtil.java
│ └── ValidatorUtil.java
├── validator/
│ ├── EmailValidator.java
│ ├── MobileValidator.java
│ └── Validator.java
└── xlsx/
├── ExcelXlsxReader.java
└── ExcelXlsxWriter.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
#eclipse files
.classpath
.project
/bin/
/target/
/.settings/
#idea files
target/
*.iml
*.ipr
*.iws
.idea/
================================================
FILE: README.md
================================================
# ExcelKit
> 简单、好用且轻量级的海量Excel文件导入导出解决方案。
# 注意
## 停止维护,建议使用EasyExcel:https://github.com/alibaba/easyexcel
## POM.xml
```xml
<dependency>
<groupId>com.wuwenze</groupId>
<artifactId>ExcelKit</artifactId>
<version>2.0.72</version>
</dependency>
```
## 示例
### 1. ExcelMapping (配置Excel与实体之间的映射关系)
> 现支持两种配置方式: 注解 或者 XML
```java
@Excel("用户信息")
public class User {
@ExcelField(value = "编号", width = 30)
private Integer userId;
@ExcelField(//
value = "用户名",//
required = true,//
validator = UsernameValidator.class,//
comment = "请填写用户名,最大长度为12,且不能重复"
)
private String username;
@ExcelField(value = "密码", required = true, maxLength = 32)
private String password;
@ExcelField(value = "邮箱", validator = UserEmailValidator.class)
private String email;
@ExcelField(//
value = "性别",//
readConverterExp = "未知=0,男=1,女=2",//
writeConverterExp = "0=未知,1=男,2=女",//
options = SexOptions.class//
)
private Integer sex;
@ExcelField(//
value = "用户组",//
name = "userGroup.name",//
options = UserGroupNameOptions.class
)
private UserGroup userGroup;
@ExcelField(value = "创建时间", dateFormat = "yyyy/MM/dd HH:mm:ss")
private Date createAt;
@ExcelField(//
value = "自定义字段",//
maxLength = 80,//
comment = "可以乱填,但是长度不能超过80,导入时最终会转换为数字",//
writeConverter = CustomizeFieldWriteConverter.class,// 写文件时,将数字转字符串
readConverter = CustomizeFieldReadConverter.class// 读文件时,将字符串转数字
)
private Integer customizeField;
// Getter and Setter ..
}
```
> XML 配置方式, 必须需将 xml 文件放置在`classpath:excel-mapping/{entityClassName}.xml`
```java
public class User2 {
private Integer userId;
private String username;
private String password;
private String email;
private Integer sex;
private UserGroup userGroup;
private Date createAt;
private Integer customizeField;
// Getter and Setter ..
}
```
> classpath:excel-mapping/com.wuwenze.entity.User2.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<excel-mapping name="用户信息">
<property name="userId" column="编号" width="30"/>
<property
name="username"
column="用户名"
required="true"
validator="com.wuwenze.validator.UsernameValidator"
comment="请填写用户名,最大长度为12,且不能重复"
/>
<property name="password" column="密码" required="true" maxLength="32"/>
<property name="email" column="邮箱" validator="com.wuwenze.validator.UserEmailValidator"/>
<property
name="sex"
column="性别"
readConverterExp="未知=0,男=1,女=2"
writeConverterExp="0=未知,1=男,2=女"
options="com.wuwenze.options.SexOptions"
/>
<property name="userGroup.name" column="用户组" options="com.wuwenze.options.UserGroupNameOptions"/>
<property name="createAt" column="创建时间" dateFormat="yyyy/MM/dd HH:mm:ss"/>
<property
name="customizeField"
column="自定义字段"
maxLength="80"
comment="可以乱填,但是长度不能超过80,导入时最终会转换为数字"
writeConverter="com.wuwenze.converter.CustomizeFieldWriteConverter"
readConverter="com.wuwenze.converter.CustomizeFieldReadConverter"
/>
</excel-mapping>
```
以上两种方式2选一即可, ExcelKit 会`优先装载 XML 配置文件`.
### 2. 实现相关的转换器
> 通过实现`com.wuwenze.poi.config.Options`自定义导入模板的下拉框数据源。
```java
public class UserGroupNameOptions implements Options {
@Override
public String[] get() {
return new String[]{"管理组", "普通会员组", "游客"};
}
}
```
> 通过实现`com.wuwenze.poi.validator.Validator`自定义单元格导入时的验证规则。
```java
public class UsernameValidator implements Validator {
final List<String> ERROR_USERNAME_LIST = Lists.newArrayList(
"admin", "root", "master", "administrator", "sb"
);
@Override
public String valid(Object o) {
String username = (String) o;
if (username.length() > 12) {
return "用户名不能超过12个字符。";
}
if (ERROR_USERNAME_LIST.contains(username)) {
return "用户名非法,不允许使用。";
}
return null;
}
}
```
> 实现`com.wuwenze.poi.convert.WriteConverter`以及`com.wuwenze.poi.convert.ReadConverter`单元格读写转换器。
```java
public class CustomizeFieldWriteConverter implements WriteConverter {
/**
* 写文件时,将值进行转换(此处示例为将数值拼接为指定格式的字符串)
*/
@Override
public String convert(Object o) throws ExcelKitWriteConverterException {
return (o + "_convertedValue");
}
}
public class CustomizeFieldReadConverter implements ReadConverter {
/**
* 读取单元格时,将值进行转换(此处示例为计算单元格字符串char的总和)
*/
@Override
public Object convert(Object o) throws ExcelKitReadConverterException {
String value = (String) o;
int convertedValue = 0;
for (char c : value.toCharArray()) {
convertedValue += Integer.valueOf(c);
}
return convertedValue;
}
}
```
### 3. 一行代码构建 Excel 导入模板
> 使用 ExcelKit 提供的API 构建导入模板, 会根据配置生成批注, 下拉框等
``` java
// 生成导入模板(含3条示例数据)
@RequestMapping(value = "/downTemplate", method = RequestMethod.GET)
public void downTemplate(HttpServletResponse response) {
List<User> userList = DbUtil.getUserList(3);
ExcelKit.$Export(User.class, response).downXlsx(userList, true);
}
```


### 4. 执行文件导入
> 使用边读边处理的方式, 无需担心内存溢出, 也不用理会 Excel 文件到底有多大.
``` java
@RequestMapping(value = "/importUser", method = RequestMethod.POST)
public ResponseEntity<?> importUser(@RequestParam MultipartFile file)
throws IOException {
long beginMillis = System.currentTimeMillis();
List<User> successList = Lists.newArrayList();
List<Map<String, Object>> errorList = Lists.newArrayList();
ExcelKit.$Import(User.class)
.readXlsx(file.getInputStream(), new ExcelReadHandler<User>() {
@Override
public void onSuccess(int sheetIndex, int rowIndex, User entity) {
successList.add(entity); // 单行读取成功,加入入库队列。
}
@Override
public void onError(int sheetIndex, int rowIndex,
List<ExcelErrorField> errorFields) {
// 读取数据失败,记录了当前行所有失败的数据
errorList.add(MapUtil.newHashMap(//
"sheetIndex", sheetIndex,//
"rowIndex", rowIndex,//
"errorFields", errorFields//
));
}
});
// TODO: 执行successList的入库操作。
return ResponseEntity.ok(MapUtil.newHashMap(
"data", successList,
"haveError", !CollectionUtil.isEmpty(errorList),
"error", errorList,
"timeConsuming", (System.currentTimeMillis() - beginMillis) / 1000L
));
}
```
> 全部导入成功示例:

> 部分导入失败示例(包含错误信息):

### 5. 一行代码执行 Excel 批量导出.
> 基于 Apache POI SXSSF 系列API实现导出, 大幅优化导出性能.
``` java
@RequestMapping(value = "/downXlsx", method = RequestMethod.GET)
public void downXlsx(HttpServletResponse response) {
long beginMillis = System.currentTimeMillis();
List<User> userList = DbUtil.getUserList(100000);// 生成10w条测试数据
ExcelKit.$Export(User.class, response).downXlsx(userList, false);
log.info("#ExcelKit.$Export success, size={},timeConsuming={}s",//
userList.size(), (System.currentTimeMillis() - beginMillis) / 1000L);
}
```

需要注意的是,虽然ExcelKit针对导出做了大量优化,但导出数据也需要量力而行。

================================================
FILE: pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wuwenze</groupId>
<artifactId>ExcelKit</artifactId>
<version>2.0.72</version>
<packaging>jar</packaging>
<name>ExcelKit</name>
<url>http://gitee.com/wuwenze/ExcelKit</url>
<description>Excel导入导出工具(简单、好用且轻量级的海量Excel文件导入导出解决方案.)</description>
<developers>
<developer>
<name>wuwenze</name>
<url>https://wuwenze.com</url>
<email>wenzewoo@gmail.com</email>
</developer>
</developers>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<scm>
<connection>scm:git:git@gitee.com:wuwenze/ExcelKit.git</connection>
<developerConnection>scm:git:git@gitee.com:wuwenze/ExcelKit.git</developerConnection>
<url>git@gitee.com:wuwenze/ExcelKit.git</url>
</scm>
<properties>
<encoding>UTF-8</encoding>
<jdk-version>1.6</jdk-version>
<poi-version>3.17</poi-version>
<dom4j-version>1.6.1</dom4j-version>
<jaxen-version>1.1.6</jaxen-version>
<xerces-version>2.11.0</xerces-version>
<guava-version>18.0</guava-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j-version}</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>${jaxen-version}</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>${xerces-version}</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>${jdk-version}</target>
<source>${jdk-version}</source>
<encoding>${encoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jdk-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>${jdk-version}</jdk>
</activation>
<properties>
<maven.compiler.source>${jdk-version}</maven.compiler.source>
<maven.compiler.target>${jdk-version}</maven.compiler.target>
<maven.compiler.compilerVersion>${jdk-version}</maven.compiler.compilerVersion>
</properties>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>
================================================
FILE: src/main/java/com/wuwenze/poi/ExcelKit.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi;
import com.wuwenze.poi.exception.ExcelKitRuntimeException;
import com.wuwenze.poi.factory.ExcelMappingFactory;
import com.wuwenze.poi.handler.ExcelReadHandler;
import com.wuwenze.poi.pojo.ExcelMapping;
import com.wuwenze.poi.util.Const;
import com.wuwenze.poi.util.POIUtil;
import com.wuwenze.poi.xlsx.ExcelXlsxReader;
import com.wuwenze.poi.xlsx.ExcelXlsxWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ExcelKit {
private Class<?> mClass = null;
private HttpServletResponse mResponse = null;
private OutputStream mOutputStream = null;
private Integer mMaxSheetRecords = 50000;
private String mCurrentOptionMode = ExcelKit.MODE_EXPORT;
private final static String MODE_EXPORT = "$MODE_EXPORT$";
private final static String MODE_BUILD = "$MODE_BUILD$";
private final static String MODE_IMPORT = "$MODE_IMPORT$";
/**
* 使用此构造器来执行浏览器导出
*
* @param clazz 导出实体对象
* @param response 原生 response 对象, 用于响应浏览器下载
* @return ExcelKit obj.
* @see ExcelKit#downXlsx(List, boolean)
*/
public static ExcelKit $Export(Class<?> clazz, HttpServletResponse response) {
return new ExcelKit(clazz, response);
}
public void downXlsx(List<?> data, boolean isTemplate) {
if (!mCurrentOptionMode.equals(ExcelKit.MODE_EXPORT)) {
throw new ExcelKitRuntimeException(
"请使用com.wuwenze.poi.ExcelKit.$Export(Class<?> clazz, HttpServletResponse response)构造器初始化参数.");
}
try {
ExcelMapping excelMapping = ExcelMappingFactory.get(mClass);
ExcelXlsxWriter excelXlsxWriter = new ExcelXlsxWriter(excelMapping,
mMaxSheetRecords);
SXSSFWorkbook workbook = excelXlsxWriter.generateXlsxWorkbook(data, isTemplate);
String fileName = isTemplate ? (excelMapping.getName() + "-导入模板.xlsx")
: (excelMapping.getName() + "-导出结果.xlsx");
POIUtil.download(workbook, mResponse, URLEncoder.encode(fileName, Const.ENCODING));
} catch (Throwable e) {
throw new ExcelKitRuntimeException("downXlsx error", e);
}
}
/**
* 使用此构造器来执行构建文件流.
*
* @param clazz 导出实体对象
* @param outputStream 输出流
* @return ExcelKit obj.
* @see ExcelKit#writeXlsx(List, boolean)
*/
public static ExcelKit $Builder(Class<?> clazz, OutputStream outputStream) {
return new ExcelKit(clazz, outputStream);
}
public void writeXlsx(List<?> data, boolean isTemplate) {
if (!mCurrentOptionMode.equals(ExcelKit.MODE_BUILD)) {
throw new ExcelKitRuntimeException(
"请使用com.wuwenze.poi.ExcelKit.$Builder(Class<?> clazz, OutputStream outputStream)构造器初始化参数.");
}
ExcelMapping excelMapping = ExcelMappingFactory.get(mClass);
ExcelXlsxWriter excelXlsxWriter = new ExcelXlsxWriter(excelMapping,
mMaxSheetRecords);
SXSSFWorkbook workbook = excelXlsxWriter.generateXlsxWorkbook(data, isTemplate);
POIUtil.write(workbook, mOutputStream);
}
/**
* 使用此构造器来执行Excel文件导入.
*
* @param clazz 导出实体对象
* @return ExcelKit obj.
* @see ExcelKit#readXlsx(File, Integer, ExcelReadHandler)
* @see ExcelKit#readXlsx(InputStream, Integer, ExcelReadHandler)
* @see ExcelKit#readXlsx(File, ExcelReadHandler)
* @see ExcelKit#readXlsx(InputStream, ExcelReadHandler)
*/
public static ExcelKit $Import(Class<?> clazz) {
return new ExcelKit(clazz);
}
public void readXlsx(File excelFile, ExcelReadHandler<?> excelReadHandler) {
readXlsx(excelFile, -1, excelReadHandler);
}
public void readXlsx(File excelFile, Integer sheetIndex,
ExcelReadHandler<?> excelReadHandler) {
try {
InputStream inputStream = new FileInputStream(excelFile);
readXlsx(inputStream, sheetIndex, excelReadHandler);
} catch (Throwable e) {
throw new ExcelKitRuntimeException("readXlsx error", e);
}
}
public void readXlsx(InputStream inputStream, ExcelReadHandler<?> excelReadHandler) {
readXlsx(inputStream, -1, excelReadHandler);
}
public void readXlsx(InputStream inputStream, Integer sheetIndex,
ExcelReadHandler<?> excelReadHandler) {
if (!mCurrentOptionMode.equals(ExcelKit.MODE_IMPORT)) {
throw new ExcelKitRuntimeException(
"请使用com.wuwenze.poi.ExcelKit.$Import(Class<?> clazz)构造器初始化参数.");
}
ExcelMapping excelMapping = ExcelMappingFactory.get(mClass);
ExcelXlsxReader excelXlsxReader = new ExcelXlsxReader(mClass, excelMapping,
excelReadHandler);
if (sheetIndex >= 0) {
excelXlsxReader.process(inputStream, sheetIndex);
return;
}
excelXlsxReader.process(inputStream);
}
public ExcelKit setMaxSheetRecords(Integer mMaxSheetRecords) {
this.mMaxSheetRecords = mMaxSheetRecords;
return this;
}
protected ExcelKit(Class<?> clazz) {
this(clazz, null, null);
mCurrentOptionMode = ExcelKit.MODE_IMPORT;
}
protected ExcelKit(Class<?> clazz, OutputStream outputStream) {
this(clazz, outputStream, null);
mCurrentOptionMode = ExcelKit.MODE_BUILD;
}
protected ExcelKit(Class<?> clazz, HttpServletResponse response) {
this(clazz, null, response);
mCurrentOptionMode = ExcelKit.MODE_EXPORT;
}
protected ExcelKit(
Class<?> clazz, OutputStream outputStream, HttpServletResponse response) {
mClass = clazz;
mOutputStream = outputStream;
mResponse = response;
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/annotation/Excel.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wuwenze
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Excel {
String value() default "";
}
================================================
FILE: src/main/java/com/wuwenze/poi/annotation/ExcelField.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.annotation;
import com.wuwenze.poi.config.Options;
import com.wuwenze.poi.convert.ReadConverter;
import com.wuwenze.poi.convert.WriteConverter;
import com.wuwenze.poi.validator.Validator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wuwenze
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelField {
/**
* @return 单元格名称(如 : id字段显示为 ' 编号 ') 默认为字段名
*/
String value() default "";
/**
* 属性名, 仅在复杂数据类型时配置.
* <pre>
* (At)ExcelField(name="user.name");
* private User user;
* </pre>
*
* @return 属性名
*/
String name() default "";
/**
* @return 单元格宽度[仅限表头] 默认-1(自动计算列宽)
*/
short width() default -1;
/**
* @return 是否必填
*/
boolean required() default false;
/**
* @return 批注信息, 生成模板时生效
*/
String comment() default "";
/**
* @return 最大长度, 读取时生效, 默认不限制
*/
int maxLength() default -1;
/**
* 日期格式, 如: yyyy/MM/dd
*
* @return 日期格式
*/
String dateFormat() default "";
/**
* @return 下拉框数据源, 生成模板和验证数据时生效
*/
Class<? extends Options> options() default Void.class;
/**
* 写入内容转换表达式 (如: 1=男,2=女), 与 writeConverter 二选一(优先级0)
*
* @return 写入内容转换表达式
* @see ExcelField#writeConverter()
*/
String writeConverterExp() default "";
/**
* 写入内容转换器, 与 writeConverterExp 二选一(优先级1)
*
* @return 写入内容转换器
* @see ExcelField#writeConverterExp()
*/
Class<? extends WriteConverter> writeConverter() default Void.class;
/**
* 读取内容转表达式 (如: 男=1,女=2), 与 readConverter 二选一(优先级0)
*
* @return 读取内容转表达式
* @see ExcelField#readConverter()
*/
String readConverterExp() default "";
/**
* 读取内容转换器, 与 readConverterExp 二选一(优先级1)
*
* @return 读取内容转换器
* @see ExcelField#readConverterExp()
*/
Class<? extends ReadConverter> readConverter() default Void.class;
/**
* 正则表达式, 读取时生效, 与 validator 二选一(优先级0)
*
* @return 正则表达式
* @see ExcelField#validator()
*/
String regularExp() default "";
/**
* 正则表达式验证失败时的错误消息, regularExp 配置后生效
*
* @return 正则表达式验证失败时的错误消息
* @see ExcelField#regularExp()
*/
String regularExpMessage() default "";
/**
* 自定义验证器, 读取时生效, 与 regularExp 二选一(优先级1)
*
* @return 自定义验证器
* @see ExcelField#regularExp()
*/
Class<? extends Validator> validator() default Void.class;
class Void implements Options, ReadConverter, WriteConverter, Validator {
@Override
public String[] get() {
return new String[0];
}
@Override
public String convert(Object value) {
return null;
}
@Override
public String valid(Object value) {
return null;
}
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/config/Options.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.config;
/**
* @author wuwenze
*/
public interface Options {
/**
* 指定excel单元格的下拉框数据源, 用于规范生成Excel模板的数据校验
*
* @return ["option1", "option2"]
*/
String[] get();
}
================================================
FILE: src/main/java/com/wuwenze/poi/convert/ReadConverter.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.convert;
import com.wuwenze.poi.exception.ExcelKitReadConverterException;
/**
* @author wuwenze
*/
public interface ReadConverter {
/**
* 将value转换成指定的值, 读取时映射到实体中
*
* @param value 当前单元格的值
* @return 转换后的值
*/
Object convert(Object value) throws ExcelKitReadConverterException;
}
================================================
FILE: src/main/java/com/wuwenze/poi/convert/WriteConverter.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.convert;
import com.wuwenze.poi.exception.ExcelKitWriteConverterException;
/**
* @author wuwenze
*/
public interface WriteConverter {
/**
* 将value转换成指定的值, 用于写入excel表格中
*
* @param value 当前单元格的值
* @return 转换后的值
*/
String convert(Object value) throws ExcelKitWriteConverterException;
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitAnnotationAnalyzeException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitAnnotationAnalyzeException extends ExcelKitRuntimeException {
private static final long serialVersionUID = -7412071094510468644L;
public ExcelKitAnnotationAnalyzeException(String message) {
super(message);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitConfigAnalyzeFailureException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitConfigAnalyzeFailureException extends ExcelKitRuntimeException {
private static final long serialVersionUID = -6037535579660494996L;
public ExcelKitConfigAnalyzeFailureException(String message) {
super(message);
}
public ExcelKitConfigAnalyzeFailureException(Throwable cause) {
super(cause);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitConfigFileNotFoundException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitConfigFileNotFoundException extends ExcelKitRuntimeException {
private static final long serialVersionUID = -5061679627805728661L;
public ExcelKitConfigFileNotFoundException(String message) {
super(message);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitEncounterNoNeedXmlException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitEncounterNoNeedXmlException extends ExcelKitRuntimeException {
private static final long serialVersionUID = 4096057792690617204L;
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitReadConverterException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitReadConverterException extends ExcelKitRuntimeException {
private static final long serialVersionUID = 2832313288988433562L;
public ExcelKitReadConverterException(String message) {
super(message);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitRuntimeException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1059413765208343152L;
public ExcelKitRuntimeException() {
}
public ExcelKitRuntimeException(String message) {
super(message);
}
public ExcelKitRuntimeException(String message, Throwable cause) {
super(message, cause);
}
public ExcelKitRuntimeException(Throwable cause) {
super(cause);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitWriteConverterException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitWriteConverterException extends ExcelKitRuntimeException {
private static final long serialVersionUID = 7989007279778794434L;
public ExcelKitWriteConverterException(String message) {
super(message);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitXmlAnalyzeException.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.exception;
/**
* @author wuwenze
*/
public class ExcelKitXmlAnalyzeException extends ExcelKitRuntimeException {
private static final long serialVersionUID = 2433077029852196265L;
public ExcelKitXmlAnalyzeException(String message) {
super(message);
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/factory/ExcelMappingFactory.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.factory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.wuwenze.poi.annotation.Excel;
import com.wuwenze.poi.annotation.ExcelField;
import com.wuwenze.poi.exception.ExcelKitAnnotationAnalyzeException;
import com.wuwenze.poi.exception.ExcelKitConfigAnalyzeFailureException;
import com.wuwenze.poi.exception.ExcelKitConfigFileNotFoundException;
import com.wuwenze.poi.exception.ExcelKitXmlAnalyzeException;
import com.wuwenze.poi.pojo.ExcelMapping;
import com.wuwenze.poi.pojo.ExcelProperty;
import com.wuwenze.poi.util.BeanUtil;
import com.wuwenze.poi.util.PathUtil;
import com.wuwenze.poi.util.ValidatorUtil;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExcelMappingFactory {
private final static LoadingCache<Class<?>, ExcelMapping> mExcelMappingLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(100)
.build(new CacheLoader<Class<?>, ExcelMapping>() {
@Override
public ExcelMapping load(Class<?> key) {
return ExcelMappingFactory.loadExcelMappingByClass(key);
}
});
private final static List<String> mClazzFields = Lists
.newArrayList("options", "writeConverter", "readConverter", "validator");
private final static List<String> mRequeridAttrs = Lists.newArrayList("name");
/**
* 获取指定实体的Excel映射信息
*
* @param clazz 实体
* @return ExcelMapping映射对象
*/
public static ExcelMapping get(Class<?> clazz) {
try {
return ExcelMappingFactory.mExcelMappingLoadingCache.get(clazz);
} catch (Exception e) {
throw new ExcelKitConfigAnalyzeFailureException(e);
}
}
private static ExcelMapping loadExcelMappingByClass(Class<?> clazz) {
// 1. 从配置文件加载 (classpath:excel-mapping/className.xml)
ExcelMapping excelMapping = null;
boolean xmlConfigFileNotFound = false;
String loadExcelMappingFailedMessage = null;
try {
excelMapping = ExcelMappingFactory.loadExcelMappingByXml(clazz.getName());
} catch (Exception e) {
xmlConfigFileNotFound = e instanceof ExcelKitConfigFileNotFoundException;
loadExcelMappingFailedMessage = e.getMessage();
}
// 2. 从注解加载配置信息 (当配置文件未找到时)
if (null == excelMapping && xmlConfigFileNotFound) {
try {
excelMapping = ExcelMappingFactory.loadExcelMappingByAnnotation(clazz);
} catch (Exception e) {
loadExcelMappingFailedMessage = e.getMessage();
}
}
// 3. 加载配置信息失败.
if (null == excelMapping && null != loadExcelMappingFailedMessage) {
throw new ExcelKitConfigAnalyzeFailureException(loadExcelMappingFailedMessage);
}
return excelMapping;
}
private static ExcelMapping loadExcelMappingByAnnotation(Class<?> clazz)
throws IllegalAccessException, InstantiationException {
ExcelMapping excelMapping = new ExcelMapping();
Excel excel = clazz.getAnnotation(Excel.class);
if (null == excel) {
throw new ExcelKitAnnotationAnalyzeException(
"[" + clazz.getName() + "] @Excel annotations not found.");
}
excelMapping.setName(excel.value());
ExcelProperty excelMappingProperty;
Field[] fields = clazz.getDeclaredFields();
List<ExcelProperty> propertyList = Lists.newArrayList();
for (Field field : fields) {
ExcelField excelField = field.getAnnotation(ExcelField.class);
if (null != excelField) {
Class<?> emptyClazz = ExcelField.Void.class;
excelMappingProperty = ExcelProperty.builder()
.name(ValidatorUtil.isEmpty(excelField.name()) ? field.getName() : excelField.name())
.required(excelField.required())
.column(
ValidatorUtil.isEmpty(excelField.value()) ? field.getName() : excelField.value())
.comment(excelField.comment())
.maxLength(excelField.maxLength())
.width(excelField.width())
.dateFormat(excelField.dateFormat())
.options(excelField.options() != emptyClazz ? excelField.options().newInstance() : null)
.writeConverterExp(excelField.writeConverterExp())
.writeConverter(excelField.writeConverter() != emptyClazz ? excelField.writeConverter()
.newInstance() : null)
.readConverterExp(excelField.readConverterExp())
.readConverter(
excelField.readConverter() != emptyClazz ? excelField.readConverter().newInstance()
: null)
.regularExp(excelField.regularExp())
.regularExpMessage(excelField.regularExpMessage())
.validator(
excelField.validator() != emptyClazz ? excelField.validator().newInstance() : null)
.build();
propertyList.add(excelMappingProperty);
}
}
if (propertyList.isEmpty()) {
throw new ExcelKitAnnotationAnalyzeException(
"[" + clazz.getName() + "] @ExcelField annotations not found.");
}
excelMapping.setPropertyList(propertyList);
return excelMapping;
}
private static ExcelMapping loadExcelMappingByXml(String clazzName) throws Exception {
ExcelMapping excelMapping = new ExcelMapping();
File config = PathUtil
.getFileByClasspath(String.format("excel-mapping/%s.xml", clazzName));
String configFile = "classpath:excel-mapping/" + config.getName();
if (!config.exists()) {
throw new ExcelKitConfigFileNotFoundException(
"[" + configFile + "] not found.");
}
SAXReader reader = new SAXReader();
Document document = reader.read(config);
Element rootElement = document.getRootElement();
if (!"excel-mapping".equals(rootElement.getName())) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] <excel-mapping /> not found.");
}
Attribute nameAttr = rootElement.attribute("name");
if (null == nameAttr) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] <excel-mapping> attribute \"name\" not found.");
}
excelMapping.setName(nameAttr.getValue());
List<ExcelProperty> propertyList = Lists.newArrayList();
Iterator<Element> elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element element = elementIterator.next();
if ("property".equals(element.getName())) {
List<Attribute> attributes = element.attributes();
ExcelMappingFactory.checkXmlPropertyRequiredAttr(configFile, attributes);
ExcelProperty excelMappingProperty = null;
for (Attribute attribute : attributes) {
if (null == excelMappingProperty) {
excelMappingProperty = new ExcelProperty();
}
String name = attribute.getName();
String value = attribute.getValue();
BeanUtil.setComplexProperty(excelMappingProperty, name,
ExcelMappingFactory.validAndGetPropertyValue(configFile, name, value));
}
if (null != excelMappingProperty) {
propertyList.add(excelMappingProperty);
}
}
}
if (propertyList.isEmpty()) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] <property /> not found.");
}
excelMapping.setPropertyList(propertyList);
return excelMapping;
}
private static void checkXmlPropertyRequiredAttr(String configFile,
List<Attribute> attributes) {
Integer containsCount = 0;
for (Attribute attr : attributes) {
if (ExcelMappingFactory.mRequeridAttrs.contains(attr.getName())) {
containsCount++;
}
}
if (containsCount != ExcelMappingFactory.mRequeridAttrs.size()) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] <property /> missing required attributes: "
+ ExcelMappingFactory.mRequeridAttrs
.toString());
}
}
private static Object validAndGetPropertyValue(
String configFile, String name, String value) {
String messageTemplate = String
.format("[%s] <property %s=\"%s\"/> Analyze failed: ", configFile, name, value);
if (ExcelMappingFactory.mClazzFields.contains(name)) {
try {
return Class.forName(value).newInstance();
} catch (Exception e) {
throw new ExcelKitXmlAnalyzeException(messageTemplate + e.getMessage());
}
}
if ("writeConverterExp".equals(name) || "readConverterExp".equals(name)) {
for (String item : value.split(",")) {
if (!item.contains("=")) {
throw new ExcelKitXmlAnalyzeException(messageTemplate
+ "Converter Expression error, Reference:[\"1=男,2=女\" or \"男=1,女=2\"].");
}
}
}
return value;
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/handler/ExcelReadHandler.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.handler;
import com.wuwenze.poi.pojo.ExcelErrorField;
import java.util.List;
/**
* @author wuwenze
*/
public interface ExcelReadHandler<T> {
void onSuccess(int sheetIndex, int rowIndex, T entity);
void onError(int sheetIndex, int rowIndex, List<ExcelErrorField> errorFields);
}
================================================
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelErrorField.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @author wuwenze
*/
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ExcelErrorField {
private Integer cellIndex;
private String name;
private String column;
private String errorMessage;
}
================================================
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelMapping.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.pojo;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @author wuwenze
*/
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ExcelMapping {
private String name;
private List<ExcelProperty> propertyList;
}
================================================
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelProperty.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.pojo;
import com.wuwenze.poi.config.Options;
import com.wuwenze.poi.convert.ReadConverter;
import com.wuwenze.poi.convert.WriteConverter;
import com.wuwenze.poi.validator.Validator;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @author wuwenze
*/
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ExcelProperty {
private String name;
private String column;
private Boolean required;
private Short width;
private String comment;
private Integer maxLength;
private String dateFormat;
private Options options;
private String writeConverterExp;
private WriteConverter writeConverter;
private String readConverterExp;
private ReadConverter readConverter;
private String regularExp;
private String regularExpMessage;
private Validator validator;
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/BeanUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.beanutils.converters.DateConverter;
import java.lang.reflect.InvocationTargetException;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanUtil extends org.apache.commons.beanutils.BeanUtils {
public static void setComplexProperty(Object bean, String name, Object value)
throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
//修复日期为空时bug
ConvertUtils.register(new DateConverter(null), java.util.Date.class);
if (!name.contains(".")) {
BeanUtil.setProperty(bean, name, value);
return;
}
PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
String[] propertyLevels = name.split("\\.");
String parentPropertyName = "";
for (int i = 0; i < propertyLevels.length; i++) {
String p = propertyLevels[i];
parentPropertyName = (parentPropertyName.equals("") ? p : parentPropertyName + "." + p);
if (i < (propertyLevels.length - 1) &&
propertyUtilsBean.getProperty(bean, parentPropertyName) != null) {
continue;
}
Class<?> parentClass = propertyUtilsBean.getPropertyType(bean, parentPropertyName);
if (i < (propertyLevels.length - 1)) {
BeanUtil.setProperty(bean,
parentPropertyName, parentClass.getConstructor().newInstance());
} else {
BeanUtil.setProperty(bean, parentPropertyName,
parentClass.getConstructor(String.class).newInstance(value));
}
}
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/Const.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Const {
public static final String ENCODING = "UTF-8";
public static final String XLSX_SUFFIX = ".xlsx";
public static final String XLSX_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
public static final String XLSX_HEADER_KEY = "Content-disposition";
public static final String XLSX_HEADER_VALUE_TEMPLATE = "attachment; filename=%s";
public static final String XLSX_DEFAULT_EMPTY_CELL_VALUE = "$EMPTY_CELL$";
public static final Integer XLSX_DEFAULT_BEGIN_READ_ROW_INDEX = 1;
public static final String SAX_PARSER_CLASS = "org.apache.xerces.parsers.SAXParser";
public static final String SAX_C_ELEMENT = "c";
public static final String SAX_R_ATTR = "r";
public static final String SAX_T_ELEMENT = "t";
public static final String SAX_S_ATTR_VALUE = "s";
public static final String SAX_RID_PREFIX = "rId";
public static final String SAX_ROW_ELEMENT = "row";
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/DateUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DateUtil {
public final static SimpleDateFormat ENGLISH_LOCAL_DF = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
private final static LoadingCache<String, SimpleDateFormat> mDateFormatLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(5)
.build(new CacheLoader<String, SimpleDateFormat>() {
@Override
public SimpleDateFormat load(String pattern) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
simpleDateFormat.setLenient(true);
return simpleDateFormat;
}
});
public static Date parse(String pattern, Object value) throws Exception {
String valueString = (String) value;
return DateUtil.mDateFormatLoadingCache.get(pattern).parse(valueString);
}
public static String format(String pattern, Date value) {
try {
return DateUtil.mDateFormatLoadingCache.get(pattern).format(value);
} catch (ExecutionException e) {
e.printStackTrace();
}
return value.toString();
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/POIUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import com.wuwenze.poi.config.Options;
import com.wuwenze.poi.exception.ExcelKitRuntimeException;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class POIUtil {
private static final int mDefaultRowAccessWindowSize = 100;
private static SXSSFWorkbook newSXSSFWorkbook(int rowAccessWindowSize) {
return new SXSSFWorkbook(rowAccessWindowSize);
}
public static SXSSFWorkbook newSXSSFWorkbook() {
return POIUtil.newSXSSFWorkbook(POIUtil.mDefaultRowAccessWindowSize);
}
public static SXSSFSheet newSXSSFSheet(SXSSFWorkbook wb, String sheetName) {
return wb.createSheet(sheetName);
}
public static SXSSFRow newSXSSFRow(SXSSFSheet sheet, int index) {
return sheet.createRow(index);
}
public static SXSSFCell newSXSSFCell(SXSSFRow row, int index) {
return row.createCell(index);
}
public static void setColumnWidth(
SXSSFSheet sheet, int index, Short width, String value) {
boolean widthNotHaveConfig = (null == width || width == -1);
if (widthNotHaveConfig && !ValidatorUtil.isEmpty(value)) {
sheet.setColumnWidth(index, (short) (value.length() * 2048));
} else {
width = widthNotHaveConfig ? 200 : width;
sheet.setColumnWidth(index, (short) (width * 35.7));
}
}
public static void setColumnCellRange(SXSSFSheet sheet, Options options,
int firstRow, int endRow,
int firstCell, int endCell) {
if (null != options) {
String[] datasource = options.get();
if (null != datasource && datasource.length > 0) {
if (datasource.length > 100) {
throw new ExcelKitRuntimeException("Options item too much.");
}
DataValidationHelper validationHelper = sheet.getDataValidationHelper();
DataValidationConstraint explicitListConstraint = validationHelper
.createExplicitListConstraint(datasource);
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCell,
endCell);
DataValidation validation = validationHelper
.createValidation(explicitListConstraint, regions);
validation.setSuppressDropDownArrow(true);
validation.createErrorBox("提示", "请从下拉列表选取");
validation.setShowErrorBox(true);
sheet.addValidationData(validation);
}
}
}
public static void write(SXSSFWorkbook wb, OutputStream out) {
try {
if (null != out) {
wb.write(out);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void download(
SXSSFWorkbook wb, HttpServletResponse response, String filename) {
try {
OutputStream out = response.getOutputStream();
response.setContentType(Const.XLSX_CONTENT_TYPE);
response.setHeader(Const.XLSX_HEADER_KEY,
String.format(Const.XLSX_HEADER_VALUE_TEMPLATE, filename));
POIUtil.write(wb, out);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object convertByExp(Object propertyValue, String converterExp)
throws Exception {
try {
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (itemArray[0].equals(propertyValue)) {
return itemArray[1];
}
}
} catch (Exception e) {
throw e;
}
return propertyValue;
}
public static int countNullCell(String ref, String ref2) {
// excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
String xfd = ref.replaceAll("\\d+", "");
String xfd_1 = ref2.replaceAll("\\d+", "");
xfd = POIUtil.fillChar(xfd, 3, '@', true);
xfd_1 = POIUtil.fillChar(xfd_1, 3, '@', true);
char[] letter = xfd.toCharArray();
char[] letter_1 = xfd_1.toCharArray();
int res =
(letter[0] - letter_1[0]) * 26 * 26 + (letter[1] - letter_1[1]) * 26 + (letter[2]
- letter_1[2]);
return res - 1;
}
private static String fillChar(String str, int len, char let, boolean isPre) {
int len_1 = str.length();
if (len_1 < len) {
if (isPre) {
for (int i = 0; i < (len - len_1); i++) {
str = let + str;
}
} else {
for (int i = 0; i < (len - len_1); i++) {
str = str + let;
}
}
}
return str;
}
public static void checkExcelFile(File file) {
String filename = null != file ? file.getAbsolutePath() : null;
if (null == filename || !file.exists()) {
throw new ExcelKitRuntimeException("Excel file[" + filename + "] does not exist.");
}
if (!filename.endsWith(Const.XLSX_SUFFIX)) {
throw new ExcelKitRuntimeException(
"[" + filename + "]Only .xlsx formatted files are supported.");
}
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/PathUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import java.io.File;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PathUtil {
public static String getClasspath() {
return PathUtil.class.getResource("/").getPath();
}
public static String getFilePathByClasspath(String name) {
return PathUtil.getClasspath() + name;
}
public static File getFileByClasspath(String name) {
return new File(PathUtil.getFilePathByClasspath(name));
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/RegexUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RegexUtil {
private final static LoadingCache<String, Pattern> mRegexPatternLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(5)
.build(new CacheLoader<String, Pattern>() {
@Override
public Pattern load(String pattern) {
return Pattern.compile(pattern);
}
});
public static Boolean isMatches(String pattern, Object value) {
try {
String valueString = (String) value;
return RegexUtil.mRegexPatternLoadingCache.get(pattern).matcher(valueString).matches();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/util/ValidatorUtil.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.util;
import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* @author wuwenze
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ValidatorUtil {
private static final Pattern PATTERN_NUMERIC = Pattern.compile("^(-?\\d+)(\\.\\d+)?$");
private static final Pattern PATTERN_EMAIL = Pattern
.compile("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$");
private static final Pattern PATTERN_MOBILE_PHONE = Pattern.compile("^(1)\\d{10}$");
public static boolean match(String value, String regularExp) {
return ValidatorUtil.isEmpty(value) ? false
: Pattern.compile(regularExp).matcher(value).matches();
}
/**
* 判断是否为浮点数或者整数
*
* @param value 字符串
* @return true Or false
*/
public static boolean isNumeric(String value) {
return ValidatorUtil.isEmpty(value) ? false
: ValidatorUtil.PATTERN_NUMERIC.matcher(value).matches();
}
/**
* 判断是否为正确的邮件格式
*
* @param value 字符串
* @return true Or false
*/
public static boolean isEmail(String value) {
return ValidatorUtil.isEmpty(value) ? false
: ValidatorUtil.PATTERN_EMAIL.matcher(value).matches();
}
/**
* 判断字符串是否为合法手机号
*
* @param value 字符串
* @return true Or false
*/
public static boolean isMobile(String value) {
return ValidatorUtil.isEmpty(value) ? false
: ValidatorUtil.PATTERN_MOBILE_PHONE.matcher(value).matches();
}
/**
* 判断是否为数字
*
* @param value 字符串
* @return true Or false
*/
public static boolean isNumber(String value) {
try {
Integer.parseInt(value);
} catch (Exception ex) {
return false;
}
return true;
}
/**
* 判断字符串是否为空
*
* @param value 字符串
* @return true Or false
*/
public static boolean isEmpty(String value) {
return null == value || "".equals(value.trim()) || "null".equalsIgnoreCase(value.trim());
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/validator/EmailValidator.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.validator;
import com.wuwenze.poi.util.ValidatorUtil;
/**
* @author wuwenze
*/
public class EmailValidator implements Validator {
@Override
public String valid(Object value) {
String valueString = (String) value;
return ValidatorUtil.isEmail(valueString) ? null : "[" + valueString + "]不是正确的EMail.";
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/validator/MobileValidator.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.validator;
import com.wuwenze.poi.util.ValidatorUtil;
/**
* @author wuwenze
*/
public class MobileValidator implements Validator {
@Override
public String valid(Object value) {
String valueString = (String) value;
return ValidatorUtil.isMobile(valueString) ? null : "[" + valueString + "]不是正确的手机号码.";
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/validator/Validator.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.validator;
/**
* @author wuwenze
*/
public interface Validator {
/**
* 验证单元格的值, 若验证失败, 请返回错误消息.
*
* @param value 当前单元格的值
* @return null or errorMessage
*/
String valid(Object value);
}
================================================
FILE: src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxReader.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.xlsx;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.wuwenze.poi.config.Options;
import com.wuwenze.poi.convert.ReadConverter;
import com.wuwenze.poi.exception.ExcelKitEncounterNoNeedXmlException;
import com.wuwenze.poi.exception.ExcelKitReadConverterException;
import com.wuwenze.poi.exception.ExcelKitRuntimeException;
import com.wuwenze.poi.handler.ExcelReadHandler;
import com.wuwenze.poi.pojo.ExcelErrorField;
import com.wuwenze.poi.pojo.ExcelMapping;
import com.wuwenze.poi.pojo.ExcelProperty;
import com.wuwenze.poi.util.*;
import com.wuwenze.poi.validator.Validator;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author wuwenze
*/
public class ExcelXlsxReader extends DefaultHandler {
private Integer mCurrentSheetIndex = -1, mCurrentRowIndex = 0, mCurrentCellIndex = 0;
private ExcelCellType mNextCellType = ExcelCellType.STRING;
private String mCurrentCellRef, mPreviousCellRef, mMaxCellRef;
private SharedStringsTable mSharedStringsTable;
private String mPreviousCellValue;
private StylesTable mStylesTable;
private Boolean mNextIsString = false;
private Short mFormatIndex;
private String mFormatString;
private final ExcelMapping mExcelMapping;
private final ExcelReadHandler mExcelReadHandler;
private final Class<? extends Object> mEntityClass;
private final List<Object> mExcelRowObjectData = Lists.newArrayList();
private Integer mBeginReadRowIndex = Const.XLSX_DEFAULT_BEGIN_READ_ROW_INDEX;
private final Object mEmptyCellValue = Const.XLSX_DEFAULT_EMPTY_CELL_VALUE;
private final DataFormatter formatter = new DataFormatter();
public ExcelXlsxReader(Class<? extends Object> entityClass,//
ExcelMapping excelMapping, //
ExcelReadHandler excelReadHandler) {
this(entityClass, excelMapping, null, excelReadHandler);
}
public ExcelXlsxReader(Class<? extends Object> entityClass,//
ExcelMapping excelMapping, //
Integer beginReadRowIndex,//
ExcelReadHandler excelReadHandler) {
mEntityClass = entityClass;
mExcelMapping = excelMapping;
if (null != beginReadRowIndex) {
mBeginReadRowIndex = beginReadRowIndex;
}
mExcelReadHandler = excelReadHandler;
}
public void process(String fileName) throws ExcelKitRuntimeException {
try {
processAll(OPCPackage.open(fileName));
} catch (Exception e) {
throw new ExcelKitRuntimeException("Only .xlsx formatted files are supported.", e);
}
}
public void process(InputStream in) throws ExcelKitRuntimeException {
try {
processAll(OPCPackage.open(in));
} catch (Exception e) {
throw new ExcelKitRuntimeException("Only .xlsx formatted files are supported.", e);
}
}
private void processAll(OPCPackage pkg)
throws IOException, OpenXML4JException, SAXException {
XSSFReader xssfReader = new XSSFReader(pkg);
mStylesTable = xssfReader.getStylesTable();
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XMLReader parser = this.fetchSheetParser(sst);
Iterator<InputStream> sheets = xssfReader.getSheetsData();
while (sheets.hasNext()) {
mCurrentRowIndex = 0;
mCurrentSheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
pkg.close();
}
public void process(String fileName, int sheetIndex) throws ExcelKitRuntimeException {
try {
this.processBySheet(sheetIndex, OPCPackage.open(fileName));
} catch (Exception e) {
throw new ExcelKitRuntimeException("Only .xlsx formatted files are supported.", e);
}
}
public void process(InputStream in, int sheetIndex) throws ExcelKitRuntimeException {
try {
this.processBySheet(sheetIndex, OPCPackage.open(in));
} catch (Exception e) {
throw new ExcelKitRuntimeException("Only .xlsx formatted files are supported.", e);
}
}
private void processBySheet(int sheetIndex, OPCPackage pkg)
throws IOException, OpenXML4JException, SAXException {
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
// 根据 rId# 或 rSheet# 查找sheet
InputStream sheet = r.getSheet(Const.SAX_RID_PREFIX + (sheetIndex + 1));
mCurrentSheetIndex++;
InputSource sheetSource = new InputSource(sheet);
try {
parser.parse(sheetSource);
} catch (ExcelKitEncounterNoNeedXmlException e) {
sheet = r.getSheet(Const.SAX_RID_PREFIX + (sheetIndex + 3));
sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
}
sheet.close();
pkg.close();
}
@Override
public void startElement(
String uri, String localName, String name, Attributes attributes) {
if ("sst".equals(name) || "styleSheet".equals(name)) {
throw new ExcelKitEncounterNoNeedXmlException();
}
// c => 单元格
if (Const.SAX_C_ELEMENT.equals(name)) {
String ref = attributes.getValue(Const.SAX_R_ATTR);
// 前一个单元格的位置
mPreviousCellRef = null == mPreviousCellRef ? ref : mCurrentCellRef;
// 当前单元格的位置
mCurrentCellRef = ref;
// Figure out if the value is an index in the SST
String cellType = attributes.getValue(Const.SAX_T_ELEMENT);
String cellStyleStr = attributes.getValue(Const.SAX_S_ATTR_VALUE);
mNextIsString = (null != cellType && cellType.equals(Const.SAX_S_ATTR_VALUE));
// 设定单元格类型
this.setNextCellType(cellType, cellStyleStr);
}
mPreviousCellValue = "";
}
@Override
public void endElement(String uri, String localName, String name) {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if (mNextIsString) {
int index = Integer.parseInt(mPreviousCellValue);
mPreviousCellValue = new XSSFRichTextString(mSharedStringsTable.getEntryAt(index))
.toString();
mNextIsString = false;
}
// 处理单元格数据
if (Const.SAX_C_ELEMENT.equals(name)) {
String value = this.getCellValue(mPreviousCellValue.trim());
// 空值补齐(中)
if (!mCurrentCellRef.equals(mPreviousCellRef)) {
for (int i = 0; i < POIUtil.countNullCell(mCurrentCellRef, mPreviousCellRef);
i++) {
mExcelRowObjectData.add(mCurrentCellIndex, mEmptyCellValue);
mCurrentCellIndex++;
}
}
mExcelRowObjectData.add(mCurrentCellIndex, value);
mCurrentCellIndex++;
}
// 如果标签名称为 row ,这说明已到行尾,通知回调处理当前行的数据
else if (Const.SAX_ROW_ELEMENT.equals(name)) {
if (mCurrentRowIndex == 0) {
mMaxCellRef = mCurrentCellRef;
}
// 空值补齐(后)
if (null != mMaxCellRef) {
for (int i = 0; i <= POIUtil.countNullCell(mMaxCellRef, mCurrentCellRef); i++) {
mExcelRowObjectData.add(mCurrentCellIndex, mEmptyCellValue);
mCurrentCellIndex++;
}
}
try {
this.performVerificationAndProcessFlowRow();
} catch (Exception e) {
e.printStackTrace();
} finally {
mExcelRowObjectData.clear();
mCurrentRowIndex++;
mCurrentCellIndex = 0;
mPreviousCellRef = null;
mCurrentCellRef = null;
}
}
}
@Override
public void characters(char[] chars, int start, int length) {
mPreviousCellValue = mPreviousCellValue.concat(new String(chars, start, length));
}
private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser = XMLReaderFactory.createXMLReader(Const.SAX_PARSER_CLASS);
mSharedStringsTable = sst;
parser.setContentHandler(this);
return parser;
}
enum ExcelCellType {
BOOL, ERROR, FORMULA, INLINESTR, STRING, NUMBER, DATE, NULL
}
private void setNextCellType(String cellType, String cellStyleStr) {
mNextCellType = ExcelCellType.STRING;
mFormatIndex = -1;
mFormatString = null;
if ("b".equals(cellType)) {
mNextCellType = ExcelCellType.BOOL;
} else if ("e".equals(cellType)) {
mNextCellType = ExcelCellType.ERROR;
} else if ("inlineStr".equals(cellType)) {
mNextCellType = ExcelCellType.INLINESTR;
} else if ("s".equals(cellType)) {
mNextCellType = ExcelCellType.STRING;
} else if ("str".equals(cellType)) {
mNextCellType = ExcelCellType.FORMULA;
}
if (null != cellStyleStr) {
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = mStylesTable.getStyleAt(styleIndex);
mFormatIndex = style.getDataFormat();
mFormatString = style.getDataFormatString();
if ("m/d/yy".equals(mFormatString)) {
mNextCellType = mNextCellType.DATE;
mFormatString = "yyyy-MM-dd hh:mm:ss.SSS";
}
if (null == mFormatString) {
mNextCellType = mNextCellType.NULL;
mFormatString = BuiltinFormats.getBuiltinFormat(mFormatIndex);
}
}
}
private String getCellValue(String value) {
String thisStr;
switch (mNextCellType) {
case BOOL:
return value.charAt(0) == '0' ? "FALSE" : "TRUE";
case ERROR:
return "\"ERROR:" + value + '"';
case FORMULA:
return '"' + value + '"';
case INLINESTR:
return new XSSFRichTextString(value).toString();
case STRING:
return String.valueOf(value);
case NUMBER:
if (mFormatString != null) {
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), mFormatIndex, mFormatString).trim();
} else {
thisStr = value;
}
thisStr = thisStr.replace("_", "").trim();
break;
case DATE:
thisStr = formatter.formatRawCellContents(Double.parseDouble(value), mFormatIndex, mFormatString);
// 对日期字符串作特殊处理
thisStr = thisStr.replace(" ", "T");
break;
default:
thisStr = "";
break;
}
return thisStr;
}
private final static String CHECK_MAP_KEY_OF_VALUE = "CELL_VALUE";
private final static String CHECK_MAP_KEY_OF_ERROR = "CELL_ERROR";
private void performVerificationAndProcessFlowRow() throws Exception {
if (mCurrentRowIndex >= mBeginReadRowIndex) {
List<ExcelProperty> propertyList = mExcelMapping.getPropertyList();
Integer excelRowDataSize = mExcelRowObjectData.size();
Integer excelMappingPropertySize = propertyList.size();
// 空值补齐(前)
for (int i = 0; i < excelMappingPropertySize - excelRowDataSize; i++) {
mExcelRowObjectData.add(i, mEmptyCellValue);
}
if (!this.rowObjectDataIsAllEmptyCellValue()) {
Object entity = mEntityClass.newInstance();
List<ExcelErrorField> errorFields = Lists.newArrayList();
for (int i = 0; i < propertyList.size(); i++) {
ExcelProperty property = propertyList.get(i);
Map<String, Object> checkAndConvertPropertyRetMap = this.checkAndConvertProperty(i, property, mExcelRowObjectData.get(i));
Object errorFieldObject = checkAndConvertPropertyRetMap.get(
ExcelXlsxReader.CHECK_MAP_KEY_OF_ERROR);
if (null != errorFieldObject) {
errorFields.add((ExcelErrorField) errorFieldObject);
}
if (errorFields.isEmpty()) {
Object propertyValue = checkAndConvertPropertyRetMap.get(
ExcelXlsxReader.CHECK_MAP_KEY_OF_VALUE);
BeanUtil.setComplexProperty(entity, property.getName(), propertyValue);
}
}
if (errorFields.isEmpty()) {
mExcelReadHandler.onSuccess(mCurrentSheetIndex, mCurrentRowIndex, entity);
return;
}
mExcelReadHandler.onError(mCurrentSheetIndex, mCurrentRowIndex, errorFields);
}
}
}
private boolean rowObjectDataIsAllEmptyCellValue() {
int emptyObjectCount = 0;
for (Object excelRowObjectData : mExcelRowObjectData) {
if ((null == excelRowObjectData) //
|| excelRowObjectData.equals(mEmptyCellValue) //
|| ValidatorUtil.isEmpty((String) excelRowObjectData)) {
emptyObjectCount++;
}
}
return emptyObjectCount == mExcelRowObjectData.size();
}
private Map<String, Object> checkAndConvertProperty(Integer cellIndex,
ExcelProperty property,
Object propertyValue) {
if(null == propertyValue || ValidatorUtil.isEmpty((String) propertyValue) || Const.XLSX_DEFAULT_EMPTY_CELL_VALUE.equals(propertyValue)) {
// required
Boolean required = property.getRequired();
if (null != required && required) {
return this.buildCheckAndConvertPropertyRetMap(cellIndex, property, propertyValue, "单元格的值必须填写");
}
// empty cell doesn't need to check anymore
return this.buildCheckAndConvertPropertyRetMap(cellIndex, property, null, null);
}
// maxLength
Integer maxLength = property.getMaxLength();
if (-1 != maxLength) {
if (String.valueOf(propertyValue).length() > maxLength) {
return this.buildCheckAndConvertPropertyRetMap(cellIndex, property, propertyValue, "超过最大长度: " + maxLength);
}
}
// dateFormat
String dateFormat = property.getDateFormat();
if (!ValidatorUtil.isEmpty(dateFormat)) {
try {
// 时间格式转换后,直接返回。
Date parseDateValue = DateUtil.parse(dateFormat, propertyValue);
return this.buildCheckAndConvertPropertyRetMap(cellIndex, property, parseDateValue, null);
} catch (Exception e) {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, "时间格式解析失败 [" + dateFormat + "]");
}
}
// options
Options options = property.getOptions();
if (null != options) {
Object[] values = options.get();
if (null != values && values.length > 0) {
boolean containInOptions = false;
for (Object value : values) {
if (propertyValue.equals(value)) {
containInOptions = true;
break;
}
}
if (!containInOptions) {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, "[" + propertyValue + "]不是规定的下拉框的值");
}
}
}
// regularExp
String regularExp = property.getRegularExp();
if (!ValidatorUtil.isEmpty(regularExp)) {
if (!RegexUtil.isMatches(regularExp, propertyValue)) {
String regularExpMessage = property.getRegularExpMessage();
String validErrorMessage = !ValidatorUtil.isEmpty(regularExpMessage) ?
regularExpMessage : "正则表达式校验失败 [" + regularExp + "]";
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, validErrorMessage);
}
}
// validator
Validator validator = property.getValidator();
if (null != validator) {
String validErrorMessage = validator.valid(propertyValue);
if (null != validErrorMessage) {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, validErrorMessage);
}
}
// readConverterExp && readConverter (按照优先级处理)
String readConverterExp = property.getReadConverterExp();
ReadConverter readConverter = property.getReadConverter();
if (!ValidatorUtil.isEmpty(readConverterExp)) {
try {
Object convertPropertyValue = POIUtil.convertByExp(propertyValue, readConverterExp);
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, convertPropertyValue, null);
} catch (Exception e) {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, "由于readConverterExp表达式的值不规范导致转换失败");
}
} else if (null != readConverter) {
try {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, readConverter.convert(propertyValue), null);
} catch (ExcelKitReadConverterException e) {
return this.buildCheckAndConvertPropertyRetMap(//
cellIndex, property, propertyValue, e.getMessage());
}
}
return this.buildCheckAndConvertPropertyRetMap(cellIndex, property, propertyValue, null);
}
private Map<String, Object> buildCheckAndConvertPropertyRetMap(Integer cellIndex,
ExcelProperty property,//
Object propertyValue, String validErrorMessage) {
Map<String, Object> resultMap = Maps.newHashMap();
resultMap.put(ExcelXlsxReader.CHECK_MAP_KEY_OF_VALUE, propertyValue);
if (null != validErrorMessage) {
resultMap.put(ExcelXlsxReader.CHECK_MAP_KEY_OF_ERROR, ExcelErrorField.builder()//
.cellIndex(cellIndex)//
.column(property.getColumn())//
.name(property.getName())//
.errorMessage(validErrorMessage)//
.build());
}
return resultMap;
}
}
================================================
FILE: src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxWriter.java
================================================
/*
* Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wuwenze.poi.xlsx;
import com.wuwenze.poi.convert.WriteConverter;
import com.wuwenze.poi.exception.ExcelKitRuntimeException;
import com.wuwenze.poi.pojo.ExcelMapping;
import com.wuwenze.poi.pojo.ExcelProperty;
import com.wuwenze.poi.util.DateUtil;
import com.wuwenze.poi.util.POIUtil;
import com.wuwenze.poi.util.ValidatorUtil;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFDrawing;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
/**
* @author wuwenze
*/
public class ExcelXlsxWriter {
private final ExcelMapping mExcelMapping;
private final Integer mMaxSheetRecords;
public ExcelXlsxWriter(ExcelMapping excelMapping, Integer maxSheetRecords) {
mExcelMapping = excelMapping;
mMaxSheetRecords = maxSheetRecords;
}
/**
* 构建xlsxWorkbook对象
*
* @param data 数据集
* @param isTemplate 是否是导出模板
* @return SXSSFWorkbook
*/
public SXSSFWorkbook generateXlsxWorkbook(List<?> data, boolean isTemplate) {
SXSSFWorkbook workbook = POIUtil.newSXSSFWorkbook();
List<ExcelProperty> propertyList = mExcelMapping.getPropertyList();
double sheetNo = Math.ceil(data.size() / (double) mMaxSheetRecords);
for (int index = 0; index <= (sheetNo == 0.0 ? sheetNo : sheetNo - 1); index++) {
String sheetName = mExcelMapping.getName() + (index == 0 ? "" : "_" + index);
SXSSFSheet sheet = generateXlsxHeader(workbook, propertyList, sheetName, isTemplate);
if (null != data && data.size() > 0) {
int startNo = index * mMaxSheetRecords;
int endNo = Math.min(startNo + mMaxSheetRecords, data.size());
for (int i = startNo; i < endNo; i++) {
SXSSFRow bodyRow = POIUtil.newSXSSFRow(sheet, i + 1 - startNo);
for (int j = 0; j < propertyList.size(); j++) {
SXSSFCell cell = POIUtil.newSXSSFCell(bodyRow, j);
ExcelXlsxWriter.buildCellValueByExcelProperty(cell, data.get(i), propertyList.get(j));
}
}
}
}
return workbook;
}
private SXSSFSheet generateXlsxHeader(SXSSFWorkbook workbook,
List<ExcelProperty> propertyList,
String sheetName, boolean isTemplate) {
SXSSFDrawing sxssfDrawing = null;
SXSSFSheet sheet = POIUtil.newSXSSFSheet(workbook, sheetName);
SXSSFRow headerRow = POIUtil.newSXSSFRow(sheet, 0);
for (int i = 0; i < propertyList.size(); i++) {
ExcelProperty property = propertyList.get(i);
SXSSFCell cell = POIUtil.newSXSSFCell(headerRow, i);
POIUtil.setColumnWidth(sheet, i, property.getWidth(), property.getColumn());
if (isTemplate) {
// cell range
POIUtil.setColumnCellRange(sheet, property.getOptions(), 1, mMaxSheetRecords, i, i);
// cell comment.
if (null == sxssfDrawing) {
sxssfDrawing = sheet.createDrawingPatriarch();
}
if (!ValidatorUtil.isEmpty(property.getComment())) {
// int col1, int row1, int col2, int row2
Comment cellComment = sxssfDrawing.createCellComment(//
new XSSFClientAnchor(0, 0, 0, 0, i, 0,i+2, i+2));
XSSFRichTextString xssfRichTextString = new XSSFRichTextString(
property.getComment());
Font commentFormatter = workbook.createFont();
xssfRichTextString.applyFont(commentFormatter);
cellComment.setString(xssfRichTextString);
cell.setCellComment(cellComment);
}
}
cell.setCellStyle(getHeaderCellStyle(workbook));
String headerColumnValue = property.getColumn();
if (isTemplate && null != property.getRequired() && property.getRequired()) {
headerColumnValue = (headerColumnValue + "[*]");
}
cell.setCellValue(headerColumnValue);
}
return sheet;
}
private static void buildCellValueByExcelProperty(SXSSFCell cell, Object entity,
ExcelProperty property) {
Object cellValue;
try {
cellValue = BeanUtils.getProperty(entity, property.getName());
} catch (Throwable e) {
throw new ExcelKitRuntimeException(e);
}
if (null != cellValue) {
String dateFormat = property.getDateFormat();
if (!ValidatorUtil.isEmpty(dateFormat)) {
if (cellValue instanceof Date) {
cell.setCellValue(DateUtil.format(dateFormat, (Date) cellValue));
} else if (cellValue instanceof String) {
try {
Date parse = DateUtil.ENGLISH_LOCAL_DF.parse((String) cellValue);
cell.setCellValue(DateUtil.format(dateFormat, parse));
} catch (ParseException e) {
e.printStackTrace();
}
return;
}
}
// writeConverterExp && writeConverter
String writeConverterExp = property.getWriteConverterExp();
WriteConverter writeConverter = property.getWriteConverter();
if (!ValidatorUtil.isEmpty(writeConverterExp)) {
try {
cellValue = POIUtil.convertByExp(cellValue, writeConverterExp);
} catch (Throwable e) {
throw new ExcelKitRuntimeException(e);
}
} else if (null != writeConverter) {
cell.setCellValue(writeConverter.convert(cellValue));
return;
}
cell.setCellValue(String.valueOf(cellValue));
}
}
private CellStyle mHeaderCellStyle = null;
public CellStyle getHeaderCellStyle(SXSSFWorkbook wb) {
if (null == mHeaderCellStyle) {
mHeaderCellStyle = wb.createCellStyle();
Font font = wb.createFont();
mHeaderCellStyle.setFillForegroundColor((short) 12);
mHeaderCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
mHeaderCellStyle.setBorderTop(BorderStyle.DOTTED);
mHeaderCellStyle.setBorderRight(BorderStyle.DOTTED);
mHeaderCellStyle.setBorderBottom(BorderStyle.DOTTED);
mHeaderCellStyle.setBorderLeft(BorderStyle.DOTTED);
mHeaderCellStyle.setAlignment(HorizontalAlignment.LEFT);// 对齐
mHeaderCellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.GREEN.getIndex());
mHeaderCellStyle.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.GREEN.getIndex());
font.setColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
// 应用标题字体到标题样式
mHeaderCellStyle.setFont(font);
//设置单元格文本形式
DataFormat dataFormat = wb.createDataFormat();
mHeaderCellStyle.setDataFormat(dataFormat.getFormat("@"));
}
return mHeaderCellStyle;
}
}
gitextract_lm2w90xj/
├── .gitignore
├── README.md
├── pom.xml
└── src/
└── main/
└── java/
└── com/
└── wuwenze/
└── poi/
├── ExcelKit.java
├── annotation/
│ ├── Excel.java
│ └── ExcelField.java
├── config/
│ └── Options.java
├── convert/
│ ├── ReadConverter.java
│ └── WriteConverter.java
├── exception/
│ ├── ExcelKitAnnotationAnalyzeException.java
│ ├── ExcelKitConfigAnalyzeFailureException.java
│ ├── ExcelKitConfigFileNotFoundException.java
│ ├── ExcelKitEncounterNoNeedXmlException.java
│ ├── ExcelKitReadConverterException.java
│ ├── ExcelKitRuntimeException.java
│ ├── ExcelKitWriteConverterException.java
│ └── ExcelKitXmlAnalyzeException.java
├── factory/
│ └── ExcelMappingFactory.java
├── handler/
│ └── ExcelReadHandler.java
├── pojo/
│ ├── ExcelErrorField.java
│ ├── ExcelMapping.java
│ └── ExcelProperty.java
├── util/
│ ├── BeanUtil.java
│ ├── Const.java
│ ├── DateUtil.java
│ ├── POIUtil.java
│ ├── PathUtil.java
│ ├── RegexUtil.java
│ └── ValidatorUtil.java
├── validator/
│ ├── EmailValidator.java
│ ├── MobileValidator.java
│ └── Validator.java
└── xlsx/
├── ExcelXlsxReader.java
└── ExcelXlsxWriter.java
SYMBOL INDEX (125 symbols across 30 files)
FILE: src/main/java/com/wuwenze/poi/ExcelKit.java
class ExcelKit (line 40) | @NoArgsConstructor(access = AccessLevel.PROTECTED)
method $Export (line 60) | public static ExcelKit $Export(Class<?> clazz, HttpServletResponse res...
method downXlsx (line 64) | public void downXlsx(List<?> data, boolean isTemplate) {
method $Builder (line 91) | public static ExcelKit $Builder(Class<?> clazz, OutputStream outputStr...
method writeXlsx (line 95) | public void writeXlsx(List<?> data, boolean isTemplate) {
method $Import (line 117) | public static ExcelKit $Import(Class<?> clazz) {
method readXlsx (line 122) | public void readXlsx(File excelFile, ExcelReadHandler<?> excelReadHand...
method readXlsx (line 126) | public void readXlsx(File excelFile, Integer sheetIndex,
method readXlsx (line 136) | public void readXlsx(InputStream inputStream, ExcelReadHandler<?> exce...
method readXlsx (line 140) | public void readXlsx(InputStream inputStream, Integer sheetIndex,
method setMaxSheetRecords (line 156) | public ExcelKit setMaxSheetRecords(Integer mMaxSheetRecords) {
method ExcelKit (line 161) | protected ExcelKit(Class<?> clazz) {
method ExcelKit (line 166) | protected ExcelKit(Class<?> clazz, OutputStream outputStream) {
method ExcelKit (line 171) | protected ExcelKit(Class<?> clazz, HttpServletResponse response) {
method ExcelKit (line 176) | protected ExcelKit(
FILE: src/main/java/com/wuwenze/poi/annotation/ExcelField.java
class Void (line 138) | class Void implements Options, ReadConverter, WriteConverter, Validator {
method get (line 140) | @Override
method convert (line 145) | @Override
method valid (line 150) | @Override
FILE: src/main/java/com/wuwenze/poi/config/Options.java
type Options (line 21) | public interface Options {
method get (line 28) | String[] get();
FILE: src/main/java/com/wuwenze/poi/convert/ReadConverter.java
type ReadConverter (line 23) | public interface ReadConverter {
method convert (line 31) | Object convert(Object value) throws ExcelKitReadConverterException;
FILE: src/main/java/com/wuwenze/poi/convert/WriteConverter.java
type WriteConverter (line 23) | public interface WriteConverter {
method convert (line 31) | String convert(Object value) throws ExcelKitWriteConverterException;
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitAnnotationAnalyzeException.java
class ExcelKitAnnotationAnalyzeException (line 21) | public class ExcelKitAnnotationAnalyzeException extends ExcelKitRuntimeE...
method ExcelKitAnnotationAnalyzeException (line 25) | public ExcelKitAnnotationAnalyzeException(String message) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitConfigAnalyzeFailureException.java
class ExcelKitConfigAnalyzeFailureException (line 21) | public class ExcelKitConfigAnalyzeFailureException extends ExcelKitRunti...
method ExcelKitConfigAnalyzeFailureException (line 25) | public ExcelKitConfigAnalyzeFailureException(String message) {
method ExcelKitConfigAnalyzeFailureException (line 29) | public ExcelKitConfigAnalyzeFailureException(Throwable cause) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitConfigFileNotFoundException.java
class ExcelKitConfigFileNotFoundException (line 21) | public class ExcelKitConfigFileNotFoundException extends ExcelKitRuntime...
method ExcelKitConfigFileNotFoundException (line 25) | public ExcelKitConfigFileNotFoundException(String message) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitEncounterNoNeedXmlException.java
class ExcelKitEncounterNoNeedXmlException (line 21) | public class ExcelKitEncounterNoNeedXmlException extends ExcelKitRuntime...
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitReadConverterException.java
class ExcelKitReadConverterException (line 21) | public class ExcelKitReadConverterException extends ExcelKitRuntimeExcep...
method ExcelKitReadConverterException (line 25) | public ExcelKitReadConverterException(String message) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitRuntimeException.java
class ExcelKitRuntimeException (line 20) | public class ExcelKitRuntimeException extends RuntimeException {
method ExcelKitRuntimeException (line 24) | public ExcelKitRuntimeException() {
method ExcelKitRuntimeException (line 27) | public ExcelKitRuntimeException(String message) {
method ExcelKitRuntimeException (line 31) | public ExcelKitRuntimeException(String message, Throwable cause) {
method ExcelKitRuntimeException (line 35) | public ExcelKitRuntimeException(Throwable cause) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitWriteConverterException.java
class ExcelKitWriteConverterException (line 21) | public class ExcelKitWriteConverterException extends ExcelKitRuntimeExce...
method ExcelKitWriteConverterException (line 25) | public ExcelKitWriteConverterException(String message) {
FILE: src/main/java/com/wuwenze/poi/exception/ExcelKitXmlAnalyzeException.java
class ExcelKitXmlAnalyzeException (line 21) | public class ExcelKitXmlAnalyzeException extends ExcelKitRuntimeException {
method ExcelKitXmlAnalyzeException (line 25) | public ExcelKitXmlAnalyzeException(String message) {
FILE: src/main/java/com/wuwenze/poi/factory/ExcelMappingFactory.java
class ExcelMappingFactory (line 47) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method load (line 54) | @Override
method get (line 69) | public static ExcelMapping get(Class<?> clazz) {
method loadExcelMappingByClass (line 77) | private static ExcelMapping loadExcelMappingByClass(Class<?> clazz) {
method loadExcelMappingByAnnotation (line 103) | private static ExcelMapping loadExcelMappingByAnnotation(Class<?> clazz)
method loadExcelMappingByXml (line 152) | private static ExcelMapping loadExcelMappingByXml(String clazzName) th...
method checkXmlPropertyRequiredAttr (line 205) | private static void checkXmlPropertyRequiredAttr(String configFile,
method validAndGetPropertyValue (line 221) | private static Object validAndGetPropertyValue(
FILE: src/main/java/com/wuwenze/poi/handler/ExcelReadHandler.java
type ExcelReadHandler (line 24) | public interface ExcelReadHandler<T> {
method onSuccess (line 26) | void onSuccess(int sheetIndex, int rowIndex, T entity);
method onError (line 28) | void onError(int sheetIndex, int rowIndex, List<ExcelErrorField> error...
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelErrorField.java
class ExcelErrorField (line 27) | @Data
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelMapping.java
class ExcelMapping (line 28) | @Data
FILE: src/main/java/com/wuwenze/poi/pojo/ExcelProperty.java
class ExcelProperty (line 31) | @Data
FILE: src/main/java/com/wuwenze/poi/util/BeanUtil.java
class BeanUtil (line 29) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method setComplexProperty (line 32) | public static void setComplexProperty(Object bean, String name, Object...
FILE: src/main/java/com/wuwenze/poi/util/Const.java
class Const (line 24) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
FILE: src/main/java/com/wuwenze/poi/util/DateUtil.java
class DateUtil (line 32) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method load (line 42) | @Override
method parse (line 50) | public static Date parse(String pattern, Object value) throws Exception {
method format (line 55) | public static String format(String pattern, Date value) {
FILE: src/main/java/com/wuwenze/poi/util/POIUtil.java
class POIUtil (line 38) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method newSXSSFWorkbook (line 44) | private static SXSSFWorkbook newSXSSFWorkbook(int rowAccessWindowSize) {
method newSXSSFWorkbook (line 48) | public static SXSSFWorkbook newSXSSFWorkbook() {
method newSXSSFSheet (line 52) | public static SXSSFSheet newSXSSFSheet(SXSSFWorkbook wb, String sheetN...
method newSXSSFRow (line 56) | public static SXSSFRow newSXSSFRow(SXSSFSheet sheet, int index) {
method newSXSSFCell (line 60) | public static SXSSFCell newSXSSFCell(SXSSFRow row, int index) {
method setColumnWidth (line 64) | public static void setColumnWidth(
method setColumnCellRange (line 75) | public static void setColumnCellRange(SXSSFSheet sheet, Options options,
method write (line 100) | public static void write(SXSSFWorkbook wb, OutputStream out) {
method download (line 119) | public static void download(
method convertByExp (line 132) | public static Object convertByExp(Object propertyValue, String convert...
method countNullCell (line 148) | public static int countNullCell(String ref, String ref2) {
method fillChar (line 164) | private static String fillChar(String str, int len, char let, boolean ...
method checkExcelFile (line 180) | public static void checkExcelFile(File file) {
FILE: src/main/java/com/wuwenze/poi/util/PathUtil.java
class PathUtil (line 25) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method getClasspath (line 28) | public static String getClasspath() {
method getFilePathByClasspath (line 32) | public static String getFilePathByClasspath(String name) {
method getFileByClasspath (line 36) | public static File getFileByClasspath(String name) {
FILE: src/main/java/com/wuwenze/poi/util/RegexUtil.java
class RegexUtil (line 29) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method load (line 37) | @Override
method isMatches (line 43) | public static Boolean isMatches(String pattern, Object value) {
FILE: src/main/java/com/wuwenze/poi/util/ValidatorUtil.java
class ValidatorUtil (line 25) | @NoArgsConstructor(access = AccessLevel.PRIVATE)
method match (line 33) | public static boolean match(String value, String regularExp) {
method isNumeric (line 44) | public static boolean isNumeric(String value) {
method isEmail (line 55) | public static boolean isEmail(String value) {
method isMobile (line 66) | public static boolean isMobile(String value) {
method isNumber (line 77) | public static boolean isNumber(String value) {
method isEmpty (line 92) | public static boolean isEmpty(String value) {
FILE: src/main/java/com/wuwenze/poi/validator/EmailValidator.java
class EmailValidator (line 23) | public class EmailValidator implements Validator {
method valid (line 25) | @Override
FILE: src/main/java/com/wuwenze/poi/validator/MobileValidator.java
class MobileValidator (line 23) | public class MobileValidator implements Validator {
method valid (line 25) | @Override
FILE: src/main/java/com/wuwenze/poi/validator/Validator.java
type Validator (line 21) | public interface Validator {
method valid (line 29) | String valid(Object value);
FILE: src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxReader.java
class ExcelXlsxReader (line 57) | public class ExcelXlsxReader extends DefaultHandler {
method ExcelXlsxReader (line 79) | public ExcelXlsxReader(Class<? extends Object> entityClass,//
method ExcelXlsxReader (line 85) | public ExcelXlsxReader(Class<? extends Object> entityClass,//
method process (line 97) | public void process(String fileName) throws ExcelKitRuntimeException {
method process (line 105) | public void process(InputStream in) throws ExcelKitRuntimeException {
method processAll (line 113) | private void processAll(OPCPackage pkg)
method process (line 131) | public void process(String fileName, int sheetIndex) throws ExcelKitRu...
method process (line 139) | public void process(InputStream in, int sheetIndex) throws ExcelKitRun...
method processBySheet (line 147) | private void processBySheet(int sheetIndex, OPCPackage pkg)
method startElement (line 169) | @Override
method endElement (line 193) | @Override
method characters (line 245) | @Override
method fetchSheetParser (line 250) | private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXE...
type ExcelCellType (line 257) | enum ExcelCellType {
method setNextCellType (line 261) | private void setNextCellType(String cellType, String cellStyleStr) {
method getCellValue (line 293) | private String getCellValue(String value) {
method performVerificationAndProcessFlowRow (line 330) | private void performVerificationAndProcessFlowRow() throws Exception {
method rowObjectDataIsAllEmptyCellValue (line 366) | private boolean rowObjectDataIsAllEmptyCellValue() {
method checkAndConvertProperty (line 378) | private Map<String, Object> checkAndConvertProperty(Integer cellIndex,
method buildCheckAndConvertPropertyRetMap (line 479) | private Map<String, Object> buildCheckAndConvertPropertyRetMap(Integer...
FILE: src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxWriter.java
class ExcelXlsxWriter (line 48) | public class ExcelXlsxWriter {
method ExcelXlsxWriter (line 53) | public ExcelXlsxWriter(ExcelMapping excelMapping, Integer maxSheetReco...
method generateXlsxWorkbook (line 65) | public SXSSFWorkbook generateXlsxWorkbook(List<?> data, boolean isTemp...
method generateXlsxHeader (line 87) | private SXSSFSheet generateXlsxHeader(SXSSFWorkbook workbook,
method buildCellValueByExcelProperty (line 127) | private static void buildCellValueByExcelProperty(SXSSFCell cell, Obje...
method getHeaderCellStyle (line 170) | public CellStyle getHeaderCellStyle(SXSSFWorkbook wb) {
Condensed preview — 34 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (107K chars).
[
{
"path": ".gitignore",
"chars": 108,
"preview": "#eclipse files\n.classpath\n.project\n\n/bin/\n/target/\n/.settings/\n\n#idea files\ntarget/\n*.iml\n*.ipr\n*.iws\n.idea/"
},
{
"path": "README.md",
"chars": 7486,
"preview": "# ExcelKit\n> 简单、好用且轻量级的海量Excel文件导入导出解决方案。\n\n# 注意\n## 停止维护,建议使用EasyExcel:https://github.com/alibaba/easyexcel\n\n## POM.xml\n`"
},
{
"path": "pom.xml",
"chars": 5786,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n xmlns:xsi=\"http://www.w3.org"
},
{
"path": "src/main/java/com/wuwenze/poi/ExcelKit.java",
"chars": 6454,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/annotation/Excel.java",
"chars": 987,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/annotation/ExcelField.java",
"chars": 3553,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/config/Options.java",
"chars": 843,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/convert/ReadConverter.java",
"chars": 967,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/convert/WriteConverter.java",
"chars": 973,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitAnnotationAnalyzeException.java",
"chars": 944,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitConfigAnalyzeFailureException.java",
"chars": 1011,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitConfigFileNotFoundException.java",
"chars": 946,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitEncounterNoNeedXmlException.java",
"chars": 830,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitReadConverterException.java",
"chars": 908,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitRuntimeException.java",
"chars": 1107,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitWriteConverterException.java",
"chars": 910,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/exception/ExcelKitXmlAnalyzeException.java",
"chars": 929,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/factory/ExcelMappingFactory.java",
"chars": 9951,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/handler/ExcelReadHandler.java",
"chars": 951,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/pojo/ExcelErrorField.java",
"chars": 1010,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/pojo/ExcelMapping.java",
"chars": 1025,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/pojo/ExcelProperty.java",
"chars": 1585,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/util/BeanUtil.java",
"chars": 2348,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/util/Const.java",
"chars": 1764,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/util/DateUtil.java",
"chars": 2140,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/util/POIUtil.java",
"chars": 6384,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/util/PathUtil.java",
"chars": 1192,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/util/RegexUtil.java",
"chars": 1668,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/util/ValidatorUtil.java",
"chars": 2648,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/validator/EmailValidator.java",
"chars": 987,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/validator/MobileValidator.java",
"chars": 988,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/validator/Validator.java",
"chars": 872,
"preview": "/*\r\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxReader.java",
"chars": 18253,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
},
{
"path": "src/main/java/com/wuwenze/poi/xlsx/ExcelXlsxWriter.java",
"chars": 7719,
"preview": "/*\n * Copyright (c) 2018, 吴汶泽 (wenzewoo@gmail.com).\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n "
}
]
About this extraction
This page contains the full source code of the wuwz/ExcelKit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 34 files (94.0 KB), approximately 24.7k tokens, and a symbol index with 125 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.