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
================================================
4.0.0
com.wuwenze
ExcelKit
2.0.72
jar
ExcelKit
http://gitee.com/wuwenze/ExcelKit
Excel导入导出工具(简单、好用且轻量级的海量Excel文件导入导出解决方案.)
wuwenze
https://wuwenze.com
wenzewoo@gmail.com
The Apache Software License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0.txt
scm:git:git@gitee.com:wuwenze/ExcelKit.git
scm:git:git@gitee.com:wuwenze/ExcelKit.git
git@gitee.com:wuwenze/ExcelKit.git
UTF-8
1.6
3.17
1.6.1
1.1.6
2.11.0
18.0
org.apache.poi
poi-ooxml
${poi-version}
org.apache.poi
poi-ooxml-schemas
${poi-version}
dom4j
dom4j
${dom4j-version}
jaxen
jaxen
${jaxen-version}
xerces
xercesImpl
${xerces-version}
xml-apis
xml-apis
2.0.2
com.google.guava
guava
18.0
org.projectlombok
lombok
1.16.10
provided
javax.servlet
servlet-api
2.5
provided
commons-beanutils
commons-beanutils
1.9.3
junit
junit
4.12
test
org.apache.maven.plugins
maven-compiler-plugin
${jdk-version}
${jdk-version}
${encoding}
jdk-profile
true
${jdk-version}
${jdk-version}
${jdk-version}
${jdk-version}
release
org.apache.maven.plugins
maven-source-plugin
2.2.1
package
jar-no-fork
org.apache.maven.plugins
maven-javadoc-plugin
2.9.1
package
jar
org.apache.maven.plugins
maven-gpg-plugin
1.5
verify
sign
sonatype
https://oss.sonatype.org/content/repositories/snapshots/
sonatype
https://oss.sonatype.org/service/local/staging/deploy/maven2/
================================================
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 "";
/**
* 属性名, 仅在复杂数据类型时配置.
*
* (At)ExcelField(name="user.name");
* private User user;
*
*
* @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, ExcelMapping> mExcelMappingLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(100)
.build(new CacheLoader, ExcelMapping>() {
@Override
public ExcelMapping load(Class> key) {
return ExcelMappingFactory.loadExcelMappingByClass(key);
}
});
private final static List mClazzFields = Lists
.newArrayList("options", "writeConverter", "readConverter", "validator");
private final static List 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 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 + "] not found.");
}
Attribute nameAttr = rootElement.attribute("name");
if (null == nameAttr) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] attribute \"name\" not found.");
}
excelMapping.setName(nameAttr.getValue());
List propertyList = Lists.newArrayList();
Iterator elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element element = elementIterator.next();
if ("property".equals(element.getName())) {
List 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 + "] not found.");
}
excelMapping.setPropertyList(propertyList);
return excelMapping;
}
private static void checkXmlPropertyRequiredAttr(String configFile,
List attributes) {
Integer containsCount = 0;
for (Attribute attr : attributes) {
if (ExcelMappingFactory.mRequeridAttrs.contains(attr.getName())) {
containsCount++;
}
}
if (containsCount != ExcelMappingFactory.mRequeridAttrs.size()) {
throw new ExcelKitXmlAnalyzeException(
"[" + configFile + "] missing required attributes: "
+ ExcelMappingFactory.mRequeridAttrs
.toString());
}
}
private static Object validAndGetPropertyValue(
String configFile, String name, String value) {
String messageTemplate = String
.format("[%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 {
void onSuccess(int sheetIndex, int rowIndex, T entity);
void onError(int sheetIndex, int rowIndex, List 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 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 mDateFormatLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(5)
.build(new CacheLoader() {
@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 mRegexPatternLoadingCache =
CacheBuilder.newBuilder()
.maximumSize(5)
.build(new CacheLoader() {
@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