@@ -1,26 +1,3 @@ | |||
--------------------------- | |||
EasyPoi 文档 | |||
--------------------------- | |||
这几篇是旧的教程,不过和现在大同小异 | |||
[Excel 介绍篇](http://note.youdao.com/share/?id=ea5166076313d437abbfb28a18d85486&type=note) | |||
[Excel 工具类](http://note.youdao.com/share/?id=dcfef5355d1d75b718be8fd563ad5216&type=note) | |||
[Excel 注解介绍.第一篇](http://note.youdao.com/share/?id=9898d1777ca97b81d82a6e151b880dbb&type=note) | |||
[Excel 注解介绍.第二篇](http://note.youdao.com/share/?id=9898d1777ca97b81d82a6e151b880dbb&type=note) | |||
[Excel 实体类](http://note.youdao.com/share/?id=dab97eababf8e91356f87be204b581e8&type=note) | |||
[Word模板导出教程](http://note.youdao.com/share/?id=26794c8eb4a285828663178c0ae854a2&type=note) | |||
后面都是新的了 | |||
[EasyPoi 在spring mvc中简易开发方式](http://note.youdao.com/share/?id=8b04c4d88a0574a59aeaffd142c8e34b&type=note) | |||
[EasyPoi-新版自定义导出样式类型](http://note.youdao.com/share/?id=7937a9fe15f1016b8f39bf813be894f8&type=note) | |||
[EasyPoi-标签-模板导出的语法介绍](http://blog.csdn.net/qjueyue/article/details/45231801) | |||
-------------------------- | |||
EasyPoi 模板 表达式支持 | |||
-------------------------- | |||
@@ -1,30 +0,0 @@ | |||
apply plugin : "java" | |||
apply plugin : 'eclipse' | |||
allprojects { | |||
apply plugin: 'maven' | |||
group = 'org.jeecg' | |||
version = '2.3.0' | |||
} | |||
subprojects { | |||
apply plugin: 'java' | |||
sourceCompatibility = 1.7 | |||
targetCompatibility = 1.7 | |||
[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' | |||
task packageSources(type: Jar) { | |||
classifier = 'sources' | |||
from sourceSets.main.allSource | |||
} | |||
artifacts.archives packageSources | |||
repositories { | |||
mavenLocal() | |||
maven { url 'http://maven.oschina.net/content/groups/public/' } | |||
} | |||
} |
@@ -1,7 +0,0 @@ | |||
apply plugin : "java" | |||
apply plugin : 'eclipse' | |||
sourceCompatibility = 1.7 | |||
targetCompatibility = 1.7 | |||
[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' | |||
description = '' |
@@ -1,24 +0,0 @@ | |||
apply plugin: "java" | |||
apply plugin: "eclipse" | |||
sourceCompatibility = 1.7 | |||
targetCompatibility = 1.7 | |||
[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' | |||
description = '' | |||
dependencies { | |||
compile group: 'org.apache.poi', name: 'poi', version:'3.10-FINAL' | |||
compile group: 'org.apache.poi', name: 'poi-ooxml', version:'3.10-FINAL' | |||
compile(group: 'org.apache.poi', name: 'poi-ooxml-schemas', version:'3.10-FINAL') { | |||
exclude(module: 'xercesImpl') | |||
} | |||
compile group: 'xerces', name: 'xercesImpl', version:'2.9.1' | |||
compile group: 'org.apache.poi', name: 'poi-scratchpad', version:'3.10-FINAL' | |||
compile group: 'com.itextpdf', name: 'itextpdf', version:'5.5.6' | |||
compile group: 'com.itextpdf', name: 'itext-asian', version:'5.2.0' | |||
compile group: 'com.google.guava', name: 'guava', version:'16.0.1' | |||
compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.2.1' | |||
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.6.1' | |||
compile group: 'javax.validation', name: 'validation-api', version:'1.1.0.Final' | |||
compile project(':easypoi-annotation') | |||
} |
@@ -1,19 +0,0 @@ | |||
apply plugin: "java" | |||
apply plugin: "eclipse" | |||
sourceCompatibility = 1.7 | |||
targetCompatibility = 1.7 | |||
[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8' | |||
description = '' | |||
dependencies { | |||
compile group: 'org.springframework', name: 'spring-web', version:'3.1.1.RELEASE' | |||
compile group: 'org.springframework', name: 'spring-webmvc', version:'3.1.1.RELEASE' | |||
compile group: 'org.springframework', name: 'spring-core', version:'3.1.1.RELEASE' | |||
compile group: 'org.springframework', name: 'spring-core', version:'3.1.1.RELEASE' | |||
compile group: 'com.itextpdf', name: 'itextpdf', version:'5.5.6' | |||
compile project(':easypoi-base') | |||
compile(group: 'javax.servlet', name: 'servlet-api', version:'2.5') { | |||
/* This dependency was originally in the Maven provided scope, but the project was not of type war. | |||
This behavior is not yet supported by Gradle, so this dependency has been converted to a compile dependency. | |||
Please review and delete this closure when resolved. */ | |||
} | |||
} |
@@ -1,6 +0,0 @@ | |||
#Mon May 15 20:18:13 CST 2017 | |||
distributionBase=GRADLE_USER_HOME | |||
distributionPath=wrapper/dists | |||
zipStoreBase=GRADLE_USER_HOME | |||
zipStorePath=wrapper/dists | |||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-all.zip |
@@ -1,160 +0,0 @@ | |||
#!/usr/bin/env bash | |||
############################################################################## | |||
## | |||
## Gradle start up script for UN*X | |||
## | |||
############################################################################## | |||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
DEFAULT_JVM_OPTS="" | |||
APP_NAME="Gradle" | |||
APP_BASE_NAME=`basename "$0"` | |||
# Use the maximum available, or set MAX_FD != -1 to use that value. | |||
MAX_FD="maximum" | |||
warn ( ) { | |||
echo "$*" | |||
} | |||
die ( ) { | |||
echo | |||
echo "$*" | |||
echo | |||
exit 1 | |||
} | |||
# OS specific support (must be 'true' or 'false'). | |||
cygwin=false | |||
msys=false | |||
darwin=false | |||
case "`uname`" in | |||
CYGWIN* ) | |||
cygwin=true | |||
;; | |||
Darwin* ) | |||
darwin=true | |||
;; | |||
MINGW* ) | |||
msys=true | |||
;; | |||
esac | |||
# Attempt to set APP_HOME | |||
# Resolve links: $0 may be a link | |||
PRG="$0" | |||
# Need this for relative symlinks. | |||
while [ -h "$PRG" ] ; do | |||
ls=`ls -ld "$PRG"` | |||
link=`expr "$ls" : '.*-> \(.*\)$'` | |||
if expr "$link" : '/.*' > /dev/null; then | |||
PRG="$link" | |||
else | |||
PRG=`dirname "$PRG"`"/$link" | |||
fi | |||
done | |||
SAVED="`pwd`" | |||
cd "`dirname \"$PRG\"`/" >&- | |||
APP_HOME="`pwd -P`" | |||
cd "$SAVED" >&- | |||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |||
# Determine the Java command to use to start the JVM. | |||
if [ -n "$JAVA_HOME" ] ; then | |||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |||
# IBM's JDK on AIX uses strange locations for the executables | |||
JAVACMD="$JAVA_HOME/jre/sh/java" | |||
else | |||
JAVACMD="$JAVA_HOME/bin/java" | |||
fi | |||
if [ ! -x "$JAVACMD" ] ; then | |||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |||
Please set the JAVA_HOME variable in your environment to match the | |||
location of your Java installation." | |||
fi | |||
else | |||
JAVACMD="java" | |||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
Please set the JAVA_HOME variable in your environment to match the | |||
location of your Java installation." | |||
fi | |||
# Increase the maximum file descriptors if we can. | |||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then | |||
MAX_FD_LIMIT=`ulimit -H -n` | |||
if [ $? -eq 0 ] ; then | |||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |||
MAX_FD="$MAX_FD_LIMIT" | |||
fi | |||
ulimit -n $MAX_FD | |||
if [ $? -ne 0 ] ; then | |||
warn "Could not set maximum file descriptor limit: $MAX_FD" | |||
fi | |||
else | |||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |||
fi | |||
fi | |||
# For Darwin, add options to specify how the application appears in the dock | |||
if $darwin; then | |||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |||
fi | |||
# For Cygwin, switch paths to Windows format before running java | |||
if $cygwin ; then | |||
APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |||
JAVACMD=`cygpath --unix "$JAVACMD"` | |||
# We build the pattern for arguments to be converted via cygpath | |||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |||
SEP="" | |||
for dir in $ROOTDIRSRAW ; do | |||
ROOTDIRS="$ROOTDIRS$SEP$dir" | |||
SEP="|" | |||
done | |||
OURCYGPATTERN="(^($ROOTDIRS))" | |||
# Add a user-defined pattern to the cygpath arguments | |||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |||
fi | |||
# Now convert the arguments - kludge to limit ourselves to /bin/sh | |||
i=0 | |||
for arg in "$@" ; do | |||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |||
else | |||
eval `echo args$i`="\"$arg\"" | |||
fi | |||
i=$((i+1)) | |||
done | |||
case $i in | |||
(0) set -- ;; | |||
(1) set -- "$args0" ;; | |||
(2) set -- "$args0" "$args1" ;; | |||
(3) set -- "$args0" "$args1" "$args2" ;; | |||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |||
esac | |||
fi | |||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules | |||
function splitJvmOpts() { | |||
JVM_OPTS=("$@") | |||
} | |||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS | |||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" | |||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
@@ -1,90 +0,0 @@ | |||
@if "%DEBUG%" == "" @echo off | |||
@rem ########################################################################## | |||
@rem | |||
@rem Gradle startup script for Windows | |||
@rem | |||
@rem ########################################################################## | |||
@rem Set local scope for the variables with windows NT shell | |||
if "%OS%"=="Windows_NT" setlocal | |||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
set DEFAULT_JVM_OPTS= | |||
set DIRNAME=%~dp0 | |||
if "%DIRNAME%" == "" set DIRNAME=. | |||
set APP_BASE_NAME=%~n0 | |||
set APP_HOME=%DIRNAME% | |||
@rem Find java.exe | |||
if defined JAVA_HOME goto findJavaFromJavaHome | |||
set JAVA_EXE=java.exe | |||
%JAVA_EXE% -version >NUL 2>&1 | |||
if "%ERRORLEVEL%" == "0" goto init | |||
echo. | |||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
echo. | |||
echo Please set the JAVA_HOME variable in your environment to match the | |||
echo location of your Java installation. | |||
goto fail | |||
:findJavaFromJavaHome | |||
set JAVA_HOME=%JAVA_HOME:"=% | |||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |||
if exist "%JAVA_EXE%" goto init | |||
echo. | |||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |||
echo. | |||
echo Please set the JAVA_HOME variable in your environment to match the | |||
echo location of your Java installation. | |||
goto fail | |||
:init | |||
@rem Get command-line arguments, handling Windowz variants | |||
if not "%OS%" == "Windows_NT" goto win9xME_args | |||
if "%@eval[2+2]" == "4" goto 4NT_args | |||
:win9xME_args | |||
@rem Slurp the command line arguments. | |||
set CMD_LINE_ARGS= | |||
set _SKIP=2 | |||
:win9xME_args_slurp | |||
if "x%~1" == "x" goto execute | |||
set CMD_LINE_ARGS=%* | |||
goto execute | |||
:4NT_args | |||
@rem Get arguments from the 4NT Shell from JP Software | |||
set CMD_LINE_ARGS=%$ | |||
:execute | |||
@rem Setup the command line | |||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |||
@rem Execute Gradle | |||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |||
:end | |||
@rem End local scope for the variables with windows NT shell | |||
if "%ERRORLEVEL%"=="0" goto mainEnd | |||
:fail | |||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |||
rem the _cmd.exe /c_ return code! | |||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |||
exit /b 1 | |||
:mainEnd | |||
if "%OS%"=="Windows_NT" endlocal | |||
:omega |
@@ -1,8 +0,0 @@ | |||
rootProject.name = 'easypoi' | |||
include ':easypoi-base' | |||
include ':easypoi-web' | |||
include ':easypoi-annotation' | |||
project(':easypoi-base').projectDir = "$rootDir/easypoi-base" as File | |||
project(':easypoi-web').projectDir = "$rootDir/easypoi-web" as File | |||
project(':easypoi-annotation').projectDir = "$rootDir/easypoi-annotation" as File |
@@ -1,44 +0,0 @@ | |||
1.1 前言 | |||
=== | |||
easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 | |||
就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 | |||
语言(熟悉的表达式语法),完成以前复杂的写法 | |||
作者博客:http://blog.afterturn.cn/ | |||
作者邮箱: qrb.jueyue@gmail.com | |||
QQ群: 364192721 | |||
开发者:魔幻之翼 xf.key@163.com | |||
不如poi那么自定义,不如jxl那么多标签,但是我们就是写的少,写的少 | |||
**EasyPoi的主要特点** | |||
1.设计精巧,使用简单 | |||
2.接口丰富,扩展简单 | |||
3.默认值多,write less do more | |||
4.spring mvc支持,web导出可以简单明了 | |||
**功能** | |||
Excel自适应xls和xlsx两种格式,word只支持docx模式 | |||
1.Excel导入 | |||
- 注解导入 | |||
- Map导入 | |||
- 大数据量导入sax模式 | |||
- 导入文件保存 | |||
- 文件校验 | |||
- 字段校验 | |||
2.Excel导出 | |||
- 注解导出 | |||
- 模板导出 | |||
- html导出 | |||
3.Excel转html | |||
4.word导出 | |||
5.pdf导出 | |||
@@ -1,41 +0,0 @@ | |||
1.2 Easypoi介绍 | |||
=== | |||
Easypoi 为谁而开发 | |||
- 不太熟悉poi的 | |||
- 不想写太多重复太多的 | |||
- 只是简单的导入导出的 | |||
- 喜欢使用模板的 | |||
都可以使用easypoi | |||
Easypoi的目标是什么 | |||
Easypoi的目标不是替代poi,而是让一个不懂导入导出的快速使用poi完成Excel和word的各种操作,而不是看很多api才可以完成这样工作 | |||
为什么会写Easypoi | |||
以前的以前(岁月真TMD的快)我虽然写了不少代码但还是很少写poi,然后跳到一家公司之后就和业务人员聊上了,来这个需要个报表,这个报表样式是这样的,这个表头是这样的,就这样我写了大量的poi代码,每次都是大量的篇幅,copy to copy,无聊的一逼,然后加入了jeecg,jeecg中有一个小的工具类,虽然我也不知道是谁写的,然是可以用注解搞定最简单的导出,突然豁然开朗,我可以完善,让我从报表的苦海当中脱离出来,这样我花了一周的时间做了第一个版本支持导入导出放到了jeecg,发现还是不错的,慢慢的用的人越来越多,我就把这块独立出来了,再然后有人提出了模板,然后就加入了模板功能,提出了word的需求,加入了word的功能,后来工作忙了虽然没再参与jeecg,但还是一直维持这easypoi的更新,根据见识的增长也不断的重构这代码,直到现在 | |||
独特的功能 | |||
- 基于注解的导入导出,修改注解就可以修改Excel | |||
- 支持常用的样式自定义 | |||
- 基于map可以灵活定义的表头字段 | |||
- 支持一堆多的导出,导入 | |||
- 支持模板的导出,一些常见的标签,自定义标签 | |||
- 支持HTML/Excel转换,如果模板还不能满足用户的变态需求,请用这个功能 | |||
- 支持word的导出,支持图片,Excel | |||
小白如何开始 | |||
- 下载demo运行看看,基本上常见的用用法都在里面[easypoi-test](http://git.oschina.net/jueyue/easypoi-test) | |||
- 查看几个*Util的用法,Easypoi的主要输出就是这个 | |||
- 看看注解的意思 | |||
- 看看模板的标签用法 | |||
- 可以出师了 | |||
@@ -1,33 +0,0 @@ | |||
1.3 使用 | |||
=== | |||
- 1.easypoi 父包--作用大家都懂得 | |||
- 2.easypoi-annotation 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理 | |||
- 3.easypoi-base 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能 | |||
- 4.easypoi-web 耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能 | |||
- 5.sax 导入使用xercesImpl这个包(这个包可能造成奇怪的问题哈),word导出使用poi-scratchpad,都作为可选包了 | |||
如果不使用spring mvc的便捷福利,直接引入easypoi-base 就可以了,easypoi-annotation | |||
如果使用maven,请使用如下坐标 | |||
```xml | |||
<dependency> | |||
<groupId>cn.afterturn</groupId> | |||
<artifactId>easypoi-base</artifactId> | |||
<version>3.0.1-SNAPSHOT</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>cn.afterturn</groupId> | |||
<artifactId>easypoi-web</artifactId> | |||
<version>3.0.1-SNAPSHOT</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>cn.afterturn</groupId> | |||
<artifactId>easypoi-annotation</artifactId> | |||
<version>3.0.1-SNAPSHOT</version> | |||
</dependency> | |||
``` | |||
如果没有maven请直接下jar,在[alimaven](http://maven.aliyun.com/nexus/#nexus-search;quick~easypoi) | |||
@@ -1,10 +0,0 @@ | |||
2.1 Excel导入导出 | |||
=== | |||
Excel的导入导出是Easypoi的核心功能,前期基本也是围绕这个打造的,主要分为三种方式的处理,其中模板和Html目前只支持导出,因为支持Map.class其实导入应该是怎样都支持的 | |||
- 注解方式,注解变种方式 | |||
- 模板方式 | |||
- Html方式 | |||
下面分别就这三种方式进行讲解 | |||
@@ -1,3 +0,0 @@ | |||
2.10 Excel大数据导出 | |||
=== | |||
@@ -1,33 +0,0 @@ | |||
@Excel | |||
=== | |||
这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求,需要大家熟悉这个功能,主要分为基础,图片处理,时间处理,合并处理几块,name_id是上面讲的id用法,这里就不累言了 | |||
属性 | 类型 | 默认值 | 功能 | | |||
---|---|---|---| | |||
name | String | null | 列名,支持name_id | | |||
needMerge | boolean | fasle | 纵向合并单元格 | | |||
orderNum | String | "0" | 列的排序,支持name_id | | |||
replace | String[] | {} | 值得替换 导出是{a_id,b_id} 导入反过来 | | |||
savePath | String | "upload" | 导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/ | | |||
type | int | 1 | 导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 | | |||
width | double | 10 | 列宽 | | |||
height | double | 10 | **列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意** | | |||
isStatistics | boolean | fasle | 自动统计数据,在追加一行统计,把所有数据都和输出 | |||
** | |||
这个处理会吞没异常,请注意这一点** | |||
| | |||
isHyperlink | boolean | false | 超链接,如果是需要实现接口返回对象 | | |||
isImportField | boolean | true | 校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id | | |||
exportFormat | String | "" | 导出的时间格式,以这个是否为空来判断是否需要格式化日期 | | |||
importFormat | String | "" | 导入的时间格式,以这个是否为空来判断是否需要格式化日期 | | |||
format | String | "" | 时间格式,相当于同时设置了exportFormat 和 importFormat | | |||
databaseFormat | String | "yyyyMMddHHmmss" | 导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 | | |||
numFormat | String | "" | 数字格式化,参数是Pattern,使用的对象是DecimalFormat | | |||
imageType | int | 1 | 导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 | | |||
suffix | String | "" | 文字后缀,如% 90 变成90% | | |||
isWrap | boolean | true | 是否换行 即支持\n | | |||
mergeRely | int[] | {} | 合并单元格依赖关系,比如第二列合并是基于第一列 则{1}就可以了 | | |||
mergeVertical | boolean | fasle | 纵向合并内容相同的单元格 | | |||
@@ -1,12 +0,0 @@ | |||
@ExcelCollection | |||
=== | |||
一对多的集合注解,用以标记集合是否被数据以及集合的整体排序 | |||
属性 | 类型 | 默认值 | 功能 | | |||
---|---|---|---| | |||
id | String | null | 定义ID | | |||
name | String | null | 定义集合列名,支持nanm_id | | |||
orderNum | int | 0 | 排序,支持name_id | | |||
type | Class<?> | ArrayList.class | 导入时创建对象使用 | | |||
@@ -1,9 +0,0 @@ | |||
@ExcelEntity | |||
=== | |||
标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透,可以自定义内部id | |||
属性 | 类型 | 默认值 | 功能 | | |||
---|---|---|---| | |||
id | String | null | 定义ID | | |||
@@ -1,5 +0,0 @@ | |||
@ExcelIgnore | |||
=== | |||
忽略这个属性,多使用需循环引用中,无需多解释吧^^ | |||
@@ -1,11 +0,0 @@ | |||
@ExcelTarget | |||
=== | |||
限定一个到处实体的注解,以及一些通用设置,作用于最外面的实体 | |||
属性 | 类型 | 默认值 | 功能 | | |||
---|---|---|---| | |||
value | String | null | 定义ID | | |||
height | double | 10 | 设置行高 | | |||
fontSize | short | 11 | 设置文字大小 | | |||
@@ -1,27 +0,0 @@ | |||
注解介绍 | |||
=== | |||
easypoi起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model--row,filed--col 这样利用注解我们可以和容易做到excel到导入导出 | |||
经过一段时间发展,现在注解有5个类分别是 | |||
- @Excel 作用到filed上面,是对Excel一列的一个描述 | |||
- @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示 | |||
- @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段 | |||
- @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出 | |||
- @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理 | |||
注解中的ID的用法 | |||
这个ID算是一个比较独特的例子,比如 | |||
```java | |||
@ExcelTarget("teacherEntity") | |||
public class TeacherEntity implements java.io.Serializable { | |||
/** name */ | |||
@Excel(name = "主讲老师_teacherEntity,代课老师_absent", orderNum = "1", mergeVertical = true,needMerge=true,isImportField = "true_major,true_absent") | |||
private String name; | |||
``` | |||
这里的@ExcelTarget 表示使用teacherEntity这个对象是可以针对不同字段做不同处理 | |||
同样的ExcelEntity 和ExcelCollection 都支持这种方式 | |||
当导出这对象时,name这一列对应的是主讲老师,而不是代课老师还有很多字段都支持这种做法 | |||
@@ -1,47 +0,0 @@ | |||
2.3.1 对象定义 | |||
=== | |||
注解介绍了这么多,大家基本上也了解我们的注解是如何定义Excel的了吧,下面我们来跟着路飞实战吧 | |||
这天老师吧路飞叫到了办公室,让给给老师实现一个报表的需求,就是从教育平台把某个班级的人员导出来 | |||
需求是,导出我们班的所有学生的姓名,性别,出生日期,进校日期 | |||
正巧路飞刚看到Easypo,就打算用Easypoi来实现,实现方法如下: | |||
首先定义一个我们导出的对象,**_为了节省篇幅,统一忽略getter,setter_** | |||
```java | |||
public class StudentEntity implements java.io.Serializable { | |||
/** | |||
* id | |||
*/ | |||
private String id; | |||
/** | |||
* 学生姓名 | |||
*/ | |||
@Excel(name = "学生姓名", height = 20, width = 30, isImportField = "true_st") | |||
private String name; | |||
/** | |||
* 学生性别 | |||
*/ | |||
@Excel(name = "学生性别", replace = { "男_1", "女_2" }, suffix = "生", isImportField = "true_st") | |||
private int sex; | |||
@Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd", isImportField = "true_st", width = 20) | |||
private Date birthday; | |||
@Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd") | |||
private Date registrationDate; | |||
} | |||
``` | |||
这里设置我们的4列分别是学生姓名,学生性别,出生日期,进校日期 | |||
其中学生姓名定义了我们的列的行高,学生性别因为我们基本上都是存在数据库都是数字所以我们转换下,两个日期我们都是进行了格式化输出了,这样我们就完成了业务对我们Excel的样式需求,后面只有把这个学生列表输出就可以了 | |||
生成Excel代码如下 | |||
```java | |||
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("计算机一班学生","学生"), | |||
StudentEntity .class, list); | |||
``` | |||
这样我们就得到的一个java中的Excel,然后把这个输出就得到我们的Excel了https://static.oschina.net/uploads/space/2017/0622/212811_uh7e_1157922.png | |||
![](https://static.oschina.net/uploads/space/2017/0622/212811_uh7e_1157922.png) | |||
@@ -1,60 +0,0 @@ | |||
2.3.2 集合定义 | |||
=== | |||
路飞很快的完成了老师的任务,花了也就是喝杯茶的时间,就交差了,但过了一会就又被老师叫去了,让他给出一个某个班级选择选择某些课的学生以及对应的老师 | |||
路飞又很快的想到了Easypoi,其中有一对多的导出,这不正是一对多的体现吗,然后他继续定义实体: | |||
一个课程对应一个老师 | |||
一个课程对应N个学生 | |||
课程的实体 | |||
```java | |||
@ExcelTarget("courseEntity") | |||
public class CourseEntity implements java.io.Serializable { | |||
/** 主键 */ | |||
private String id; | |||
/** 课程名称 */ | |||
@Excel(name = "课程名称", orderNum = "1", width = 25) | |||
private String name; | |||
/** 老师主键 */ | |||
@ExcelEntity(id = "absent") | |||
private TeacherEntity mathTeacher; | |||
@ExcelCollection(name = "学生", orderNum = "4") | |||
private List<StudentEntity> students; | |||
} | |||
``` | |||
教师的实体 | |||
```java | |||
@ExcelTarget("teacherEntity") | |||
public class TeacherEntity implements java.io.Serializable { | |||
private String id; | |||
/** name */ | |||
@Excel(name = "主讲老师_major,代课老师_absent", orderNum = "1", isImportField = "true_major,true_absent") | |||
private String name; | |||
``` | |||
这里在课程这个实体里面就完成了一堆多的导出,达到了我们基础需求,同时使用了orderNum对我们的列进行了排序,满足老师的需求,导出代码如下 | |||
```java | |||
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("2412312", "测试", "测试"), | |||
CourseEntity.class, list); | |||
``` | |||
这样我们就完成了老师的需求,效果如图2.3.2-1 | |||
但是课程名和代课老师没有合并,不太美观 | |||
路飞又果断给课程名称和代课老师加了needMerge = true的属性,就可以完成单元格的合并 | |||
```java | |||
/** 课程名称 */ | |||
@Excel(name = "课程名称", orderNum = "1", width = 25,needMerge = true) | |||
private String name; | |||
//-------------------------------- | |||
/** name */ | |||
@Excel(name = "主讲老师_major,代课老师_absent", orderNum = "1",needMerge = true, isImportField = "true_major,true_absent") | |||
``` | |||
效果如图2.3.2-2 | |||
到这里,路飞就完美的完成了老师的任务,快乐的去交差了 | |||
![图2.3.2-1](https://static.oschina.net/uploads/space/2017/0622/221100_MD8y_1157922.png) | |||
![图2.3.2-2](https://static.oschina.net/uploads/space/2017/0622/222202_217m_1157922.png) | |||
@@ -1,131 +0,0 @@ | |||
2.4 注解变种-更自由的导出 | |||
=== | |||
这天老师又把路飞喊道的办公室,要求路飞导出班级学生的整体信息 | |||
```java | |||
@Excel(name = "学生姓名", height = 20, width = 30, isImportField = "true_st") | |||
private String name; | |||
@Excel(name = "学生性别", replace = { "男_1", "女_2" }, suffix = "生", isImportField = "true_st") | |||
private int sex; | |||
@Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd", isImportField = "true_st", width = 20) | |||
private Date birthday; | |||
@Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd") | |||
private Date registrationDate; | |||
``` | |||
路飞飞快的用到上面的学到的知识搞定了,这这时有一个老师把路飞叫去,说想要导出一个不要出生日期的Excel,感觉用户需求很无奈,路飞又造两个一个bean,把这个注解去掉了,来导出 | |||
```java | |||
@Excel(name = "学生姓名", height = 20, width = 30, isImportField = "true_st") | |||
private String name; | |||
@Excel(name = "学生性别", replace = { "男_1", "女_2" }, suffix = "生", isImportField = "true_st") | |||
private int sex; | |||
@Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd") | |||
private Date registrationDate; | |||
``` | |||
虽然解决了老师的需求,但这个并不是一个完美的解决方案,下面介绍一个更自由的解决方案 | |||
注解的导出,规定我们必须把model写好,并且注解写好,每次导出的Excel都是固定的,无法动态控制导出的列,虽然可以通过id来处理一个案例,但是自由度远远不够,这里介绍个变种支持,基本支持注解所有的功能 | |||
基于List<ExcelExportEntity> 的导出,ExcelExportEntity是注解经过处理翻译成的实体类,两者几乎是一对的,所以如果我们要动态自定义导出列,我们只要动态拼装ExcelExportEntity就可以了 | |||
下面我们看下这个类 | |||
```java | |||
/** | |||
* 如果是MAP导出,这个是map的key | |||
*/ | |||
private Object key; | |||
private double width = 10; | |||
private double height = 10; | |||
/** | |||
* 图片的类型,1是文件,2是数据库 | |||
*/ | |||
private int exportImageType = 0; | |||
/** | |||
* 排序顺序 | |||
*/ | |||
private int orderNum = 0; | |||
/** | |||
* 是否支持换行 | |||
*/ | |||
private boolean isWrap; | |||
/** | |||
* 是否需要合并 | |||
*/ | |||
private boolean needMerge; | |||
/** | |||
* 单元格纵向合并 | |||
*/ | |||
private boolean mergeVertical; | |||
/** | |||
* 合并依赖 | |||
*/ | |||
private int[] mergeRely; | |||
/** | |||
* 后缀 | |||
*/ | |||
private String suffix; | |||
/** | |||
* 统计 | |||
*/ | |||
private boolean isStatistics; | |||
private String numFormat; | |||
private List<ExcelExportEntity> list; | |||
``` | |||
基本上是和注解对应的, **List<ExcelExportEntity> list 这个是对应的一对多的导出,相当于集合,其他基本上都是和注解保持一致** | |||
下面给出正常的demo | |||
```java | |||
public void test() { | |||
try { | |||
List<ExcelExportEntity> entity = new ArrayList<ExcelExportEntity>(); | |||
//构造对象等同于@Excel | |||
ExcelExportEntity excelentity = new ExcelExportEntity("姓名", "name"); | |||
excelentity.setNeedMerge(true); | |||
entity.add(excelentity); | |||
entity.add(new ExcelExportEntity("性别", "sex")); | |||
excelentity = new ExcelExportEntity(null, "students"); | |||
List<ExcelExportEntity> temp = new ArrayList<ExcelExportEntity>(); | |||
temp.add(new ExcelExportEntity("姓名", "name")); | |||
temp.add(new ExcelExportEntity("性别", "sex")); | |||
//构造List等同于@ExcelCollection | |||
excelentity.setList(temp); | |||
entity.add(excelentity); | |||
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); | |||
//把我们构造好的bean对象放到params就可以了 | |||
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("测试", "测试"), entity, | |||
list); | |||
FileOutputStream fos = new FileOutputStream("D:/excel/ExcelExportForMap.tt.xls"); | |||
workbook.write(fos); | |||
fos.close(); | |||
} catch (FileNotFoundException e) { | |||
e.printStackTrace(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
``` | |||
路飞想到了这个方案,并且用上面做了测试可以完美解决所以他把之前的代码改为了(**代码有删减,基本上都是和注解对应的**) | |||
```java | |||
List<ExcelExportEntity> beanList = new ArrayList<ExcelExportEntity>(); | |||
beanList .add(new ExcelExportEntity(new ExcelExportEntity("学生姓名", "name")); | |||
beanList .add(new ExcelExportEntity("学生性别", "sex")); | |||
beanList .add(new ExcelExportEntity("进校日期", "registrationDate")); | |||
if(needBirthday()){ | |||
beanList .add(new ExcelExportEntity("出生日期", "birthday")); | |||
} | |||
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("测试", "测试"), beanList , | |||
list); | |||
``` | |||
用同一套代买完美了支持了老师的需求,心满意足的回宿舍了^^ | |||
@@ -1,22 +0,0 @@ | |||
2.5 Map导入,自由发挥 | |||
=== | |||
这天,老师把路飞叫到办公室,总是被叫,能者的悲哀啊,让他临时导入一批数据,到数据库,但是中间需要处理一些字段逻辑没办法直接导入到数据库, | |||
这时路飞首先想到构造一个bean然后标记注解,导入处理对象,但是想想一次的对象太过于浪费,不如用map试试,获取map处理map也是一样的 | |||
导入的逻辑就变成了 | |||
```java | |||
ImportParams params = new ImportParams(); | |||
params.setDataHandler(new MapImportHandler()); | |||
long start = new Date().getTime(); | |||
List<Map<String, Object>> list = ExcelImportUtil.importExcel( | |||
new File(FileUtilTest.getWebRootPath("import/check.xls")), Map.class, params); | |||
``` | |||
导入后,处理每个map,然后入库完美的解决了老师的需求,简单更快捷,和bean导入基础没有区别,省去了bean的构造时间 | |||
**PS:这个作者也只是在临时方案中或者一次性活当中使用,一般还是推荐注解这种方式,拥有更高的代码阅读性** | |||
@@ -1,46 +0,0 @@ | |||
2.6 Excel的样式自定义 | |||
=== | |||
"路飞,来办公室一趟",就这样路飞又被叫到了办公室,这次老师的需求是,想要一个漂亮点的Excel,希望路飞可以点缀下Excel,思来想去还是需要用poi的style来解决,但是如果每个都写style是不是太麻烦,而且Excel的styler数量是有限制的,这里就需要尽量复用已经创造的style,看看之前的Excel表格,大体上可以分为[标题,表头,表体],那可以说的就是创建一个接口每次调用这三个接口就可以了不说干就干 | |||
```java | |||
public interface IExcelExportStyler { | |||
/** | |||
* 列表头样式 | |||
* @param headerColor | |||
* @return | |||
*/ | |||
public CellStyle getHeaderStyle(short headerColor); | |||
/** | |||
* 标题样式 | |||
* @param color | |||
* @return | |||
*/ | |||
public CellStyle getTitleStyle(short color); | |||
/** | |||
* 获取样式方法 | |||
* @param Parity | |||
* @param entity | |||
* @return | |||
*/ | |||
public CellStyle getStyles(boolean Parity, ExcelExportEntity entity); | |||
} | |||
``` | |||
**实现类尽量复用已经创建的Styler,切记** | |||
这样路飞先造了一个带边框的styler ,**ExcelExportStylerBorderImpl** | |||
效果如下 | |||
![2.6-1](https://static.oschina.net/uploads/img/201707/11203544_eOw4.png "边框") | |||
然后路飞又手痒写了个带换行颜色的 **ExcelExportStylerColorImpl** | |||
效果如下 | |||
![2.6-2](https://static.oschina.net/uploads/img/201707/11203718_miwu.png "在这里输入图片标题") | |||
客官看到这里应该就大体理解了我们的实现方法了吧, | |||
最后路飞实现了一个复杂的按照老师要求的样式交差了 | |||
------------------------------------------------------ | |||
styler接口用法 | |||
上面两个表头和标题样式不用解释 | |||
后面这个是传入当前列的以及奇偶行,用户可以根据需求实现业务,包括去掉Excel的小箭头(也就是设置数字为数字格式的Cell),完成居中,字体等等各式各样的需求 | |||
但是这里无法实现特别没的Excel,如果有这种需求可以使用模板来实现,在Excel点点就可以完美实现 | |||
@@ -1,3 +0,0 @@ | |||
2.7 如何自定义数据处理 | |||
=== | |||
@@ -1,3 +0,0 @@ | |||
2.8 Excel导入校验 | |||
=== | |||
@@ -1,3 +0,0 @@ | |||
2.9 Excel 大批量读取 | |||
=== | |||