Excel Downlaod Library First commit

This commit is contained in:
lannstark
2020-04-20 17:14:07 +09:00
commit 3f3fb90dcc
61 changed files with 1557 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,2 @@
#Mon Apr 20 16:58:16 KST 2020
gradle.version=5.2.1

Binary file not shown.

View File

11
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,11 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="105" />
<option name="WRAP_ON_TYPING" value="1" />
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

8
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
</annotationProcessing>
</component>
</project>

19
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="/usr/local/Cellar/gradle/5.5.1/libexec" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="useAutoImport" value="true" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>

20
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

7
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

65
.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="d4baa9bc-c7e9-478c-8fb3-f56ac2c1dee0" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="DefaultGradleProjectSettings">
<option name="isMigrated" value="true" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="ProjectId" id="1anRgVINiOqlJOrNOfbtP6Dc1Hi" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showExcludedFiles" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="aspect.path.notification.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/src/main/java/com/lannstark" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="settings.editor.selected.configurable" value="reference.projectsettings.compiler.annotationProcessors" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src/main/java/com/lannstark" />
</key>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="d4baa9bc-c7e9-478c-8fb3-f56ac2c1dee0" name="Default Changelist" comment="" />
<created>1587369482920</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1587369482920</updated>
<workItem from="1587369484233" duration="893000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="WindowStateProjectService">
<state x="3173" y="664" key="#com.intellij.ide.util.MemberChooser" timestamp="1587370329831">
<screen x="1680" y="23" width="3360" height="1867" />
</state>
<state x="3173" y="664" key="#com.intellij.ide.util.MemberChooser/1680.23.3360.1867/0.23.1680.982@1680.23.3360.1867" timestamp="1587370329831" />
<state x="3025" y="607" width="670" height="676" key="search.everywhere.popup" timestamp="1587369745376">
<screen x="1680" y="23" width="3360" height="1867" />
</state>
<state x="3025" y="607" width="670" height="676" key="search.everywhere.popup/1680.23.3360.1867/0.23.1680.982@1680.23.3360.1867" timestamp="1587369745376" />
</component>
</project>

17
build.gradle Normal file
View File

@@ -0,0 +1,17 @@
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.poi:poi:4.1.2'
compile 'org.apache.poi:poi-ooxml:4.1.2'
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

172
gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# 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\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
# 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
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
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" -a "$nonstop" = "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
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@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
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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="-Xmx64m"
@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 Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_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=%*
: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

2
settings.gradle Normal file
View File

@@ -0,0 +1,2 @@
rootProject.name = 'excel-download'

View File

@@ -0,0 +1,14 @@
package com.lannstark;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultContentsStyle {
ExcelColumnStyle style();
}

View File

@@ -0,0 +1,14 @@
package com.lannstark;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultHeaderStyle {
ExcelColumnStyle style();
}

View File

@@ -0,0 +1,19 @@
package com.lannstark;
import com.lannstark.style.NoExcelCellStyle;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelColumn {
String headerName() default "";
ExcelColumnStyle headerStyle() default @ExcelColumnStyle(excelCellStyleClass = NoExcelCellStyle.class);
ExcelColumnStyle contentsStyle() default @ExcelColumnStyle(excelCellStyleClass = NoExcelCellStyle.class);
}

View File

@@ -0,0 +1,23 @@
package com.lannstark;
import com.lannstark.style.ExcelCellStyle;
public @interface ExcelColumnStyle {
/**
* Enum implements {@link com.lannstark.style.ExcelCellStyle}
* Also, can use just class.
* If not use Enum, enumName will be ignored
* @see com.lannstark.style.DefaultExcelCellStyle
* @see com.lannstark.style.CustomExcelCellStyle
*/
Class<? extends ExcelCellStyle> excelCellStyleClass();
/**
* name of Enum implements {@link com.lannstark.style.ExcelCellStyle}
* if not use Enum, enumName will be ignored
*/
String enumName() default "";
}

View File

@@ -0,0 +1,9 @@
package com.lannstark;
public class ExcelException extends RuntimeException {
public ExcelException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,10 @@
package com.lannstark.excel;
import java.io.IOException;
import java.io.OutputStream;
public interface ExcelFile {
void write(OutputStream stream) throws IOException;
}

View File

@@ -0,0 +1,98 @@
package com.lannstark.excel;
import com.lannstark.exception.ExcelInternalException;
import com.lannstark.resource.DataFormatDecider;
import com.lannstark.resource.DefaultDataFormatDecider;
import com.lannstark.resource.ExcelRenderLocation;
import com.lannstark.resource.ExcelRenderResource;
import com.lannstark.resource.ExcelRenderResourceFactory;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.List;
import static com.lannstark.utils.SuperClassReflectionUtils.getField;
public abstract class SXSSFExcelFile<T> implements ExcelFile {
protected static final SpreadsheetVersion supplyExcelVersion = SpreadsheetVersion.EXCEL2007;
protected SXSSFWorkbook wb;
protected Sheet sheet;
protected ExcelRenderResource resource;
/**
* OneSheetExcelFile
* @param data List Data to render excel file. data should have at least one @ExcelColumn on fields
* @param type Class type to be rendered
*/
public SXSSFExcelFile(List<T> data, Class<T> type) {
this.wb = new SXSSFWorkbook();
this.resource = ExcelRenderResourceFactory.prepareRenderResource(type, wb, new DefaultDataFormatDecider());
renderExcel(data);
}
/**
* OneSheetExcelFile
* @param data List Data to render excel file. data should have at least one @ExcelColumn on fields
* @param type Class type to be rendered
* @param dataFormatDecider Custom DataFormatDecider
*/
public SXSSFExcelFile(List<T> data, Class<T> type, DataFormatDecider dataFormatDecider) {
this.wb = new SXSSFWorkbook();
this.resource = ExcelRenderResourceFactory.prepareRenderResource(type, wb, dataFormatDecider);
renderExcel(data);
}
protected abstract void renderExcel(List<T> data);
protected void renderHeadersWithNewSheet(Sheet sheet, int rowIndex, int columnStartIndex) {
Row row = sheet.createRow(rowIndex);
int columnIndex = columnStartIndex;
for (String dataFieldName : resource.getDataFieldNames()) {
Cell cell = row.createCell(columnIndex++);
cell.setCellStyle(resource.getCellStyle(dataFieldName, ExcelRenderLocation.HEADER));
cell.setCellValue(resource.getExcelHeaderName(dataFieldName));
}
}
protected void renderContent(Object data, int rowIndex, int columnStartIndex) {
Row row = sheet.createRow(rowIndex);
int columnIndex = columnStartIndex;
for (String dataFieldName : resource.getDataFieldNames()) {
Cell cell = row.createCell(columnIndex++);
try {
Field field = getField(data.getClass(), (dataFieldName));
field.setAccessible(true);
cell.setCellStyle(resource.getCellStyle(dataFieldName, ExcelRenderLocation.CONTENTS));
Object cellValue = field.get(data);
renderCellValue(cell, cellValue);
} catch (Exception e) {
throw new ExcelInternalException(e.getMessage(), e);
}
}
}
private void renderCellValue(Cell cell, Object cellValue) {
if (cellValue instanceof Number) {
Number numberValue = (Number) cellValue;
cell.setCellValue(numberValue.doubleValue());
return;
}
cell.setCellValue(cellValue == null ? "" : cellValue.toString());
}
public void write(OutputStream stream) throws IOException {
wb.write(stream);
wb.close();
wb.dispose();
stream.close();
}
}

View File

@@ -0,0 +1,65 @@
package com.lannstark.excel.multiplesheet;
import com.lannstark.excel.SXSSFExcelFile;
import com.lannstark.resource.DataFormatDecider;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import java.util.List;
/**
* MultiSheetExcelFile
*
* - support Excel Version over 2007
* - support multi sheet rendering
* - support Dffierent DataFormat by Class Type
* - support Custom CellStyle according to (header or contents) and data field
*/
public class MultiSheetExcelFile<T> extends SXSSFExcelFile<T> {
private static final int maxRowCanBeRendered = supplyExcelVersion.getMaxRows() - 1;
private static final int ROW_START_INDEX = 0;
private static final int COLUMN_START_INDEX = 0;
/*
* If you use SXSSF with hug data, you need to set zip mode
* see http://apache-poi.1045710.n5.nabble.com/Bug-62872-New-Writing-large-files-with-800k-rows-gives-java-io-IOException-This-archive-contains-unc-td5732006.html
*/
public MultiSheetExcelFile(List<T> data, Class<T> type) {
super(data, type);
wb.setZip64Mode(Zip64Mode.Always);
}
public MultiSheetExcelFile(List<T> data, Class<T> type, DataFormatDecider dataFormatDecider) {
super(data, type, dataFormatDecider);
wb.setZip64Mode(Zip64Mode.Always);
}
@Override
protected void renderExcel(List<T> data) {
// 1. Create header and return if data is empty
if (data.isEmpty()) {
createNewSheetWithHeader();
return ;
}
createNewSheetWithHeader();
int renderedDataCnt = 0;
int rowIndex = ROW_START_INDEX + 1;
for (Object renderedData : data) {
renderContent(renderedData, rowIndex++, COLUMN_START_INDEX);
renderedDataCnt ++;
if (renderedDataCnt == maxRowCanBeRendered) {
renderedDataCnt = 0;
rowIndex = 1;
createNewSheetWithHeader();
}
}
}
private void createNewSheetWithHeader() {
sheet = wb.createSheet();
renderHeadersWithNewSheet(sheet, ROW_START_INDEX, COLUMN_START_INDEX);
}
}

View File

@@ -0,0 +1,56 @@
package com.lannstark.excel.onesheet;
import com.lannstark.excel.SXSSFExcelFile;
import com.lannstark.resource.DataFormatDecider;
import java.util.List;
/**
* OneSheetExcelFile
*
* - support Excel Version over 2007
* - support one sheet rendering
* - support Dffierent DataFormat by Class Type
* - support Custom CellStyle according to (header or contents) and data field
*/
public final class OneSheetExcelFile<T> extends SXSSFExcelFile<T> {
private static final int ROW_START_INDEX = 0;
private static final int COLUMN_START_INDEX = 0;
public OneSheetExcelFile(List<T> data, Class<T> type) {
super(data, type);
validateMaxRow(data);
}
public OneSheetExcelFile(List<T> data, Class<T> type, DataFormatDecider dataFormatDecider) {
super(data, type, dataFormatDecider);
validateMaxRow(data);
}
private void validateMaxRow(List<?> data) {
int maxRows = supplyExcelVersion.getMaxRows();
if (data.size() > maxRows) {
throw new IllegalArgumentException(
String.format("This concrete ExcelFile does not support over %s rows", maxRows));
}
}
@Override
public void renderExcel(List<T> data) {
// 1. Create sheet and renderHeader
sheet = wb.createSheet();
renderHeadersWithNewSheet(sheet, ROW_START_INDEX, COLUMN_START_INDEX);
if (data.isEmpty()) {
return;
}
// 2. Render Contents
int rowIndex = ROW_START_INDEX + 1;
for (Object renderedData : data) {
renderContent(renderedData, rowIndex++, COLUMN_START_INDEX);
}
}
}

View File

@@ -0,0 +1,11 @@
package com.lannstark.exception;
import com.lannstark.ExcelException;
public class ExcelInternalException extends ExcelException {
public ExcelInternalException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,11 @@
package com.lannstark.exception;
import com.lannstark.ExcelException;
public class InvalidExcelCellStyleException extends ExcelException {
public InvalidExcelCellStyleException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,11 @@
package com.lannstark.exception;
import com.lannstark.ExcelException;
public class NoExcelColumnAnnotationsException extends ExcelException {
public NoExcelColumnAnnotationsException(String message) {
super(message, null);
}
}

View File

@@ -0,0 +1,11 @@
package com.lannstark.exception;
import com.lannstark.ExcelException;
public class UnSupportedExcelTypeException extends ExcelException {
public UnSupportedExcelTypeException(String message) {
super(message, null);
}
}

View File

@@ -0,0 +1,9 @@
package com.lannstark.resource;
import org.apache.poi.ss.usermodel.DataFormat;
public interface DataFormatDecider {
short getDataFormat(DataFormat dataFormat, Class<?> type);
}

View File

@@ -0,0 +1,33 @@
package com.lannstark.resource;
import org.apache.poi.ss.usermodel.DataFormat;
import java.util.Arrays;
import java.util.List;
public class DefaultDataFormatDecider implements DataFormatDecider {
private static final String CURRENT_FORMAT = "#,##0";
private static final String DEFAULT_FORMAT = "";
@Override
public short getDataFormat(DataFormat dataFormat, Class<?> type) {
if (isNumericType(type)) {
return dataFormat.getFormat(CURRENT_FORMAT);
}
return dataFormat.getFormat(DEFAULT_FORMAT);
}
private boolean isNumericType(Class<?> type) {
List<Class<?>> numericTypes = Arrays.asList(
Byte.class, byte.class,
Short.class, short.class,
Integer.class, int.class,
Long.class, long.class,
Float.class, float.class,
Double.class, double.class
);
return numericTypes.contains(type);
}
}

View File

@@ -0,0 +1,34 @@
package com.lannstark.resource;
import java.util.Objects;
public final class ExcelCellKey {
private final String dataFieldName;
private final ExcelRenderLocation excelRenderLocation;
private ExcelCellKey(String dataFieldName, ExcelRenderLocation excelRenderLocation) {
this.dataFieldName = dataFieldName;
this.excelRenderLocation = excelRenderLocation;
}
public static ExcelCellKey of(String fieldName, ExcelRenderLocation excelRenderLocation) {
assert excelRenderLocation != null;
return new ExcelCellKey(fieldName, excelRenderLocation);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExcelCellKey that = (ExcelCellKey) o;
return Objects.equals(dataFieldName, that.dataFieldName) &&
excelRenderLocation == that.excelRenderLocation;
}
@Override
public int hashCode() {
return Objects.hash(dataFieldName, excelRenderLocation);
}
}

View File

@@ -0,0 +1,7 @@
package com.lannstark.resource;
public enum ExcelRenderLocation {
HEADER, CONTENTS
}

View File

@@ -0,0 +1,44 @@
package com.lannstark.resource;
import com.lannstark.resource.collection.PreCalculatedCellStyleMap;
import org.apache.poi.ss.usermodel.CellStyle;
import java.util.List;
import java.util.Map;
public class ExcelRenderResource {
private PreCalculatedCellStyleMap styleMap;
// TODO dataFieldName -> excelHeaderName Map Abstraction
private Map<String, String> excelHeaderNames;
private List<String> dataFieldNames;
public ExcelRenderResource(PreCalculatedCellStyleMap styleMap,
Map<String, String> excelHeaderNames, List<String> dataFieldNames) {
this.styleMap = styleMap;
this.excelHeaderNames = excelHeaderNames;
this.dataFieldNames = dataFieldNames;
}
public CellStyle getCellStyle(String dataFieldName, ExcelRenderLocation excelRenderLocation) {
return styleMap.get(ExcelCellKey.of(dataFieldName, excelRenderLocation));
}
public String getExcelHeaderName(String dataFieldName) {
return excelHeaderNames.get(dataFieldName);
}
public PreCalculatedCellStyleMap getStyleMap() {
return styleMap;
}
public Map<String, String> getExcelHeaderNames() {
return excelHeaderNames;
}
public List<String> getDataFieldNames() {
return dataFieldNames;
}
}

View File

@@ -0,0 +1,114 @@
package com.lannstark.resource;
import com.lannstark.DefaultContentsStyle;
import com.lannstark.DefaultHeaderStyle;
import com.lannstark.ExcelColumn;
import com.lannstark.ExcelColumnStyle;
import com.lannstark.exception.InvalidExcelCellStyleException;
import com.lannstark.exception.NoExcelColumnAnnotationsException;
import com.lannstark.resource.collection.PreCalculatedCellStyleMap;
import com.lannstark.style.ExcelCellStyle;
import com.lannstark.style.NoExcelCellStyle;
import org.apache.poi.ss.usermodel.Workbook;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static com.lannstark.utils.SuperClassReflectionUtils.getAllFields;
import static com.lannstark.utils.SuperClassReflectionUtils.getAnnotation;
/**
* ExcelRenderResourceFactory
*
*/
public final class ExcelRenderResourceFactory {
public static ExcelRenderResource prepareRenderResource(Class<?> type, Workbook wb,
DataFormatDecider dataFormatDecider) {
PreCalculatedCellStyleMap styleMap = new PreCalculatedCellStyleMap(dataFormatDecider);
Map<String, String> headerNamesMap = new LinkedHashMap<>();
List<String> fieldNames = new ArrayList<>();
ExcelColumnStyle classDefinedHeaderStyle = getHeaderExcelColumnStyle(type);
ExcelColumnStyle classDefinedContentsStyle = getContentsExcelColumnStyle(type);
for (Field field : getAllFields(type)) {
if (field.isAnnotationPresent(ExcelColumn.class)) {
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
styleMap.put(
String.class,
ExcelCellKey.of(field.getName(), ExcelRenderLocation.HEADER),
getCellStyle(decideAppliedStyleAnnotation(classDefinedHeaderStyle, annotation.headerStyle())), wb);
Class<?> fieldType = field.getType();
styleMap.put(
fieldType,
ExcelCellKey.of(field.getName(), ExcelRenderLocation.CONTENTS),
getCellStyle(decideAppliedStyleAnnotation(classDefinedContentsStyle, annotation.contentsStyle())), wb);
fieldNames.add(field.getName());
headerNamesMap.put(field.getName(), annotation.headerName());
}
}
if (styleMap.isEmpty()) {
throw new NoExcelColumnAnnotationsException(String.format("Class %s has not @ExcelColumn at all", type));
}
return new ExcelRenderResource(styleMap, headerNamesMap, fieldNames);
}
private static ExcelColumnStyle getHeaderExcelColumnStyle(Class<?> clazz) {
Annotation annotation = getAnnotation(clazz, DefaultHeaderStyle.class);
if (annotation == null) {
return null;
}
return ((DefaultHeaderStyle) annotation).style();
}
private static ExcelColumnStyle getContentsExcelColumnStyle(Class<?> clazz) {
Annotation annotation = getAnnotation(clazz, DefaultContentsStyle.class);
if (annotation == null) {
return null;
}
return ((DefaultContentsStyle) annotation).style();
}
private static ExcelColumnStyle decideAppliedStyleAnnotation(ExcelColumnStyle classAnnotation,
ExcelColumnStyle fieldAnnotation) {
if (fieldAnnotation.excelCellStyleClass().equals(NoExcelCellStyle.class) && classAnnotation != null) {
return classAnnotation;
}
return fieldAnnotation;
}
private static ExcelCellStyle getCellStyle(ExcelColumnStyle excelColumnStyle) {
Class<? extends ExcelCellStyle> excelCellStyleClass = excelColumnStyle.excelCellStyleClass();
// 1. Case of Enum
if (excelCellStyleClass.isEnum()) {
String enumName = excelColumnStyle.enumName();
return findExcelCellStyle(excelCellStyleClass, enumName);
}
// 2. Case of Class
try {
return excelCellStyleClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new InvalidExcelCellStyleException(e.getMessage(), e);
}
}
@SuppressWarnings("unchecked")
private static ExcelCellStyle findExcelCellStyle(Class excelCellStyles, String enumName) {
try {
return (ExcelCellStyle) Enum.valueOf((Class<Enum>) excelCellStyles, enumName);
} catch (NullPointerException e) {
throw new InvalidExcelCellStyleException("enumName must not be null", e);
} catch (IllegalArgumentException e) {
throw new InvalidExcelCellStyleException(
String.format("Enum %s does not name %s", excelCellStyles.getName(), enumName), e);
}
}
}

View File

@@ -0,0 +1,46 @@
package com.lannstark.resource.collection;
import com.lannstark.resource.DataFormatDecider;
import com.lannstark.resource.ExcelCellKey;
import com.lannstark.style.ExcelCellStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.HashMap;
import java.util.Map;
/**
* PreCalculatedCellStyleMap
*
* Determines cell's style
* In currently, PreCalculatedCellSylteMap determines {org.apache.poi.ss.usermodel.DataFormat}
*
*/
public class PreCalculatedCellStyleMap {
private final DataFormatDecider store;
public PreCalculatedCellStyleMap(DataFormatDecider store) {
this.store = store;
}
private final Map<ExcelCellKey, CellStyle> cellStyleMap = new HashMap<>();
public void put(Class<?> fieldType, ExcelCellKey excelCellKey, ExcelCellStyle excelCellStyle, Workbook wb) {
CellStyle cellStyle = wb.createCellStyle();
DataFormat dataFormat = wb.createDataFormat();
cellStyle.setDataFormat(store.getDataFormat(dataFormat, fieldType));
excelCellStyle.apply(cellStyle);
cellStyleMap.put(excelCellKey, cellStyle);
}
public CellStyle get(ExcelCellKey excelCellKey) {
return cellStyleMap.get(excelCellKey);
}
public boolean isEmpty() {
return cellStyleMap.isEmpty();
}
}

View File

@@ -0,0 +1,21 @@
package com.lannstark.style;
import com.lannstark.style.configurer.ExcelCellStyleConfigurer;
import org.apache.poi.ss.usermodel.CellStyle;
public abstract class CustomExcelCellStyle implements ExcelCellStyle {
private ExcelCellStyleConfigurer configurer = new ExcelCellStyleConfigurer();
public CustomExcelCellStyle() {
configure(configurer);
}
public abstract void configure(ExcelCellStyleConfigurer configurer);
@Override
public void apply(CellStyle cellStyle) {
configurer.configure(cellStyle);
}
}

View File

@@ -0,0 +1,44 @@
package com.lannstark.style;
import com.lannstark.style.align.DefaultExcelAlign;
import com.lannstark.style.align.ExcelAlign;
import com.lannstark.style.border.DefaultExcelBorders;
import com.lannstark.style.border.ExcelBorderStyle;
import com.lannstark.style.color.DefaultExcelColor;
import com.lannstark.style.color.ExcelColor;
import org.apache.poi.ss.usermodel.CellStyle;
/**
* Example of using ExcelCellStyle as Enum
*/
public enum DefaultExcelCellStyle implements ExcelCellStyle {
GREY_HEADER(DefaultExcelColor.rgb(217, 217, 217),
DefaultExcelBorders.newInstance(ExcelBorderStyle.THIN), DefaultExcelAlign.CENTER_CENTER),
BLUE_HEADER(DefaultExcelColor.rgb(223, 235, 246),
DefaultExcelBorders.newInstance(ExcelBorderStyle.THIN), DefaultExcelAlign.CENTER_CENTER),
CONTENTS(DefaultExcelColor.rgb(255, 255, 255),
DefaultExcelBorders.newInstance(ExcelBorderStyle.THIN), DefaultExcelAlign.RIGHT_CENTER);
private final ExcelColor backgroundColor;
/**
* like CSS margin or padding rule,
* List<DefaultExcelBorder> represents rgb TOP RIGHT BOTTOM LEFT
*/
private final DefaultExcelBorders borders;
private final ExcelAlign align;
DefaultExcelCellStyle(ExcelColor backgroundColor, DefaultExcelBorders borders, ExcelAlign align) {
this.backgroundColor = backgroundColor;
this.borders = borders;
this.align = align;
}
@Override
public void apply(CellStyle cellStyle) {
backgroundColor.applyForeground(cellStyle);
borders.apply(cellStyle);
align.apply(cellStyle);
}
}

View File

@@ -0,0 +1,9 @@
package com.lannstark.style;
import org.apache.poi.ss.usermodel.CellStyle;
public interface ExcelCellStyle {
void apply(CellStyle cellStyle);
}

View File

@@ -0,0 +1,12 @@
package com.lannstark.style;
import org.apache.poi.ss.usermodel.CellStyle;
public class NoExcelCellStyle implements ExcelCellStyle {
@Override
public void apply(CellStyle cellStyle) {
// Do nothing
}
}

View File

@@ -0,0 +1,80 @@
package com.lannstark.style.align;
import jdk.nashorn.internal.objects.annotations.Getter;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* DefaultExcelAlign
*
* Can be used with {@link com.lannstark.style.CustomExcelCellStyle}
* see {@link org.apache.poi.ss.usermodel.VerticalAlignment} and
* {@link org.apache.poi.ss.usermodel.HorizontalAlignment} for detail explanation
*/
public enum DefaultExcelAlign implements ExcelAlign {
GENERAL_TOP(HorizontalAlignment.GENERAL, VerticalAlignment.TOP),
GENERAL_CENTER(HorizontalAlignment.GENERAL, VerticalAlignment.CENTER),
GENERAL_BOTTOM(HorizontalAlignment.GENERAL, VerticalAlignment.BOTTOM),
GENERAL_JUSTIFY(HorizontalAlignment.GENERAL, VerticalAlignment.JUSTIFY),
GENERAL_DISTRIBUTED(HorizontalAlignment.GENERAL, VerticalAlignment.DISTRIBUTED),
LEFT_TOP(HorizontalAlignment.LEFT, VerticalAlignment.TOP),
LEFT_CENTER(HorizontalAlignment.LEFT, VerticalAlignment.CENTER),
LEFT_BOTTOM(HorizontalAlignment.LEFT, VerticalAlignment.BOTTOM),
LEFT_JUSTIFY(HorizontalAlignment.LEFT, VerticalAlignment.JUSTIFY),
LEFT_DISTRIBUTED(HorizontalAlignment.LEFT, VerticalAlignment.DISTRIBUTED),
CENTER_TOP(HorizontalAlignment.CENTER, VerticalAlignment.TOP),
CENTER_CENTER(HorizontalAlignment.CENTER, VerticalAlignment.CENTER),
CENTER_BOTTOM(HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM),
CENTER_JUSTIFY(HorizontalAlignment.CENTER, VerticalAlignment.JUSTIFY),
CENTER_DISTRIBUTED(HorizontalAlignment.CENTER, VerticalAlignment.DISTRIBUTED),
RIGHT_TOP(HorizontalAlignment.RIGHT, VerticalAlignment.TOP),
RIGHT_CENTER(HorizontalAlignment.RIGHT, VerticalAlignment.CENTER),
RIGHT_BOTTOM(HorizontalAlignment.RIGHT, VerticalAlignment.BOTTOM),
RIGHT_JUSTIFY(HorizontalAlignment.RIGHT, VerticalAlignment.JUSTIFY),
RIGHT_DISTRIBUTED(HorizontalAlignment.RIGHT, VerticalAlignment.DISTRIBUTED),
FILL_TOP(HorizontalAlignment.FILL, VerticalAlignment.TOP),
FILL_CENTER(HorizontalAlignment.FILL, VerticalAlignment.CENTER),
FILL_BOTTOM(HorizontalAlignment.FILL, VerticalAlignment.BOTTOM),
FILL_JUSTIFY(HorizontalAlignment.FILL, VerticalAlignment.JUSTIFY),
FILL_DISTRIBUTED(HorizontalAlignment.FILL, VerticalAlignment.DISTRIBUTED),
JUSTIFY_TOP(HorizontalAlignment.JUSTIFY, VerticalAlignment.TOP),
JUSTIFY_CENTER(HorizontalAlignment.JUSTIFY, VerticalAlignment.CENTER),
JUSTIFY_BOTTOM(HorizontalAlignment.JUSTIFY, VerticalAlignment.BOTTOM),
JUSTIFY_JUSTIFY(HorizontalAlignment.JUSTIFY, VerticalAlignment.JUSTIFY),
JUSTIFY_DISTRIBUTED(HorizontalAlignment.JUSTIFY, VerticalAlignment.DISTRIBUTED),
CENTER_SELECTION_TOP(HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.TOP),
CENTER_SELECTION_CENTER(HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.CENTER),
CENTER_SELECTION_BOTTOM(HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.BOTTOM),
CENTER_SELECTION_JUSTIFY(HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.JUSTIFY),
CENTER_SELECTION_DISTRIBUTED(HorizontalAlignment.CENTER_SELECTION, VerticalAlignment.DISTRIBUTED),
DISTRIBUTED_TOP(HorizontalAlignment.DISTRIBUTED, VerticalAlignment.TOP),
DISTRIBUTED_CENTER(HorizontalAlignment.DISTRIBUTED, VerticalAlignment.CENTER),
DISTRIBUTED_BOTTOM(HorizontalAlignment.DISTRIBUTED, VerticalAlignment.BOTTOM),
DISTRIBUTED_JUSTIFY(HorizontalAlignment.DISTRIBUTED, VerticalAlignment.JUSTIFY),
DISTRIBUTED_DISTRIBUTED(HorizontalAlignment.DISTRIBUTED, VerticalAlignment.DISTRIBUTED);
private final HorizontalAlignment horizontalAlignment;
private final VerticalAlignment verticalAlignment;
DefaultExcelAlign(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) {
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
}
@Override
public void apply(CellStyle cellStyle) {
cellStyle.setAlignment(horizontalAlignment);
cellStyle.setVerticalAlignment(verticalAlignment);
}
public HorizontalAlignment getHorizontalAlignment() {
return horizontalAlignment;
}
public VerticalAlignment getVerticalAlignment() {
return verticalAlignment;
}
}

View File

@@ -0,0 +1,9 @@
package com.lannstark.style.align;
import org.apache.poi.ss.usermodel.CellStyle;
public interface ExcelAlign {
void apply(CellStyle cellStyle);
}

View File

@@ -0,0 +1,12 @@
package com.lannstark.style.align;
import org.apache.poi.ss.usermodel.CellStyle;
public class NoExcelAlign implements ExcelAlign {
@Override
public void apply(CellStyle cellStyle) {
// Do nothing
}
}

View File

@@ -0,0 +1,33 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.CellStyle;
public final class DefaultExcelBorder implements ExcelBorder {
private ExcelBorderStyle borderStyle;
public DefaultExcelBorder(ExcelBorderStyle borderStyle) {
this.borderStyle = borderStyle;
}
@Override
public void applyTop(CellStyle cellStyle) {
cellStyle.setBorderTop(borderStyle.getStyle());
}
@Override
public void applyRight(CellStyle cellStyle) {
cellStyle.setBorderRight(borderStyle.getStyle());
}
@Override
public void applyBottom(CellStyle cellStyle) {
cellStyle.setBorderBottom(borderStyle.getStyle());
}
@Override
public void applyLeft(CellStyle cellStyle) {
cellStyle.setBorderLeft(borderStyle.getStyle());
}
}

View File

@@ -0,0 +1,38 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.CellStyle;
import java.util.ArrayList;
import java.util.List;
public final class DefaultExcelBorders implements ExcelBorders {
private List<? extends ExcelBorder> borders;
public DefaultExcelBorders(List<? extends ExcelBorder> borders) {
validateBorders(borders);
this.borders = borders;
}
public static DefaultExcelBorders newInstance(ExcelBorderStyle style) {
List<DefaultExcelBorder> excelBorders = new ArrayList<>();
for (int i = 0; i < 4; i++) {
excelBorders.add(new DefaultExcelBorder(style));
}
return new DefaultExcelBorders(excelBorders);
}
private void validateBorders(List<? extends ExcelBorder> borders) {
if (borders.size() != 4) {
throw new IllegalArgumentException("Should be initialized with TOP RIGHT LEFT BOTTOM borders");
}
}
public void apply(CellStyle cellStyle) {
borders.get(0).applyTop(cellStyle);
borders.get(1).applyRight(cellStyle);
borders.get(2).applyBottom(cellStyle);
borders.get(3).applyLeft(cellStyle);
}
}

View File

@@ -0,0 +1,15 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.CellStyle;
public interface ExcelBorder {
void applyTop(CellStyle cellStyle);
void applyRight(CellStyle cellStyle);
void applyBottom(CellStyle cellStyle);
void applyLeft(CellStyle cellStyle);
}

View File

@@ -0,0 +1,35 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.BorderStyle;
/**
* Wrapper enum for {@link org.apache.poi.ss.usermodel.BorderStyle}
*/
public enum ExcelBorderStyle {
NONE(BorderStyle.NONE),
THIN(BorderStyle.THIN),
MEDIUM(BorderStyle.MEDIUM),
DASHED(BorderStyle.DASHED),
DOTTED(BorderStyle.DOTTED),
THICK(BorderStyle.THICK),
DOUBLE(BorderStyle.DOUBLE),
HAIR(BorderStyle.HAIR),
MEDIUM_DASHED(BorderStyle.MEDIUM_DASHED),
DASH_DOT(BorderStyle.DASH_DOT),
MEDIUM_DASH_DOT(BorderStyle.MEDIUM_DASH_DOT),
DASH_DOT_DOT(BorderStyle.DASH_DOT_DOT),
MEDIUM_DASH_DOT_DOT(BorderStyle.MEDIUM_DASH_DOT_DOT),
SLANTED_DASH_DOT(BorderStyle.SLANTED_DASH_DOT);
private final BorderStyle borderStyle;
ExcelBorderStyle(BorderStyle borderStyle) {
this.borderStyle = borderStyle;
}
public BorderStyle getStyle() {
return borderStyle;
}
}

View File

@@ -0,0 +1,9 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.CellStyle;
public interface ExcelBorders {
void apply(CellStyle cellStyle);
}

View File

@@ -0,0 +1,12 @@
package com.lannstark.style.border;
import org.apache.poi.ss.usermodel.CellStyle;
public final class NoExcelBorders implements ExcelBorders {
@Override
public void apply(CellStyle cellStyle) {
// Do nothing
}
}

View File

@@ -0,0 +1,51 @@
package com.lannstark.style.color;
import com.lannstark.exception.UnSupportedExcelTypeException;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
public class DefaultExcelColor implements ExcelColor {
private static final int MIN_RGB = 0;
private static final int MAX_RGB = 255;
private byte red;
private byte green;
private byte blue;
private DefaultExcelColor(byte red, byte green, byte blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public static DefaultExcelColor rgb(int red, int green, int blue) {
if (red < MIN_RGB || red > MAX_RGB || green < MIN_RGB ||
green > MAX_RGB || blue < MIN_RGB || blue > MAX_RGB) {
throw new IllegalArgumentException(
String.format("Wrong RGB(%s %s %s)", red, green, blue)
);
}
return new DefaultExcelColor((byte) red, (byte) green, (byte) blue);
}
/**
* applyForeground
* In current, only supports XSSFCellStyle because can not find HSSFCellStyle RGB configuration
* Please share if you find the HSSFCellStyle RGB configuration
*/
@Override
public void applyForeground(CellStyle cellStyle) {
try {
XSSFCellStyle xssfCellStyle = (XSSFCellStyle) cellStyle;
xssfCellStyle.setFillForegroundColor(new XSSFColor(new byte[]{red, green, blue}, new DefaultIndexedColorMap()));
} catch (Exception e) {
throw new UnSupportedExcelTypeException(String.format("Excel Type %s is not supported now", cellStyle.getClass()));
}
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}
}

View File

@@ -0,0 +1,9 @@
package com.lannstark.style.color;
import org.apache.poi.ss.usermodel.CellStyle;
public interface ExcelColor {
void applyForeground(CellStyle cellStyle);
}

View File

@@ -0,0 +1,12 @@
package com.lannstark.style.color;
import org.apache.poi.ss.usermodel.CellStyle;
public class NoExcelColor implements ExcelColor {
@Override
public void applyForeground(CellStyle cellStyle) {
// Do nothing
}
}

View File

@@ -0,0 +1,43 @@
package com.lannstark.style.configurer;
import com.lannstark.style.align.ExcelAlign;
import com.lannstark.style.align.NoExcelAlign;
import com.lannstark.style.border.ExcelBorders;
import com.lannstark.style.border.NoExcelBorders;
import com.lannstark.style.color.DefaultExcelColor;
import com.lannstark.style.color.ExcelColor;
import com.lannstark.style.color.NoExcelColor;
import org.apache.poi.ss.usermodel.CellStyle;
public class ExcelCellStyleConfigurer {
private ExcelAlign excelAlign = new NoExcelAlign();
private ExcelColor foregroundColor = new NoExcelColor();
private ExcelBorders excelBorders = new NoExcelBorders();
public ExcelCellStyleConfigurer() {
}
public ExcelCellStyleConfigurer excelAlign(ExcelAlign excelAlign) {
this.excelAlign = excelAlign;
return this;
}
public ExcelCellStyleConfigurer foregroundColor(int red, int blue, int green) {
this.foregroundColor = DefaultExcelColor.rgb(red, blue, green);
return this;
}
public ExcelCellStyleConfigurer excelBorders(ExcelBorders excelBorders) {
this.excelBorders = excelBorders;
return this;
}
public void configure(CellStyle cellStyle) {
excelAlign.apply(cellStyle);
foregroundColor.applyForeground(cellStyle);
excelBorders.apply(cellStyle);
}
}

View File

@@ -0,0 +1,57 @@
package com.lannstark.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class SuperClassReflectionUtils {
private SuperClassReflectionUtils() {
}
public static List<Field> getAllFields(Class<?> clazz) {
List<Field> fields = new ArrayList<>();
for (Class clazzInClasses : getAllClassesIncludingSuperClasses(clazz, true)) {
fields.addAll(Arrays.asList(clazzInClasses.getDeclaredFields()));
}
return fields;
}
public static Annotation getAnnotation(Class<?> clazz,
Class<? extends Annotation> targetAnnotation) {
for (Class clazzInClasses : getAllClassesIncludingSuperClasses(clazz, false)) {
if (clazzInClasses.isAnnotationPresent(targetAnnotation)) {
return clazzInClasses.getAnnotation(targetAnnotation);
}
}
return null;
}
public static Field getField(Class<?> clazz, String name) throws Exception {
for (Class clazzInClasses : getAllClassesIncludingSuperClasses(clazz, false)) {
for (Field field : clazzInClasses.getDeclaredFields()) {
if (field.getName().equals(name)) {
return clazzInClasses.getDeclaredField(name);
}
}
}
throw new NoSuchFieldException();
}
private static List<Class> getAllClassesIncludingSuperClasses(Class<?> clazz, boolean fromSuper) {
List<Class> classes = new ArrayList<>();
while (clazz != null) {
classes.add(clazz);
clazz = clazz.getSuperclass();
}
if (fromSuper) {
Collections.reverse(classes);
}
return classes;
}
}