Browse Source

优化写入样式代码

pull/2079/head
Jiaju Zhuang 3 years ago
parent
commit
aafb3e9a43
  1. 7
      README.md
  2. 2
      pom.xml
  3. 4
      src/main/java/com/alibaba/excel/annotation/format/DateTimeFormat.java
  4. 8
      src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java
  5. 33
      src/main/java/com/alibaba/excel/annotation/write/style/ContentStyle.java
  6. 12
      src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java
  7. 33
      src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java
  8. 33
      src/main/java/com/alibaba/excel/enums/BooleanEnum.java
  9. 95
      src/main/java/com/alibaba/excel/enums/poi/BorderStyleEnum.java
  10. 119
      src/main/java/com/alibaba/excel/enums/poi/FillPatternTypeEnum.java
  11. 94
      src/main/java/com/alibaba/excel/enums/poi/HorizontalAlignmentEnum.java
  12. 71
      src/main/java/com/alibaba/excel/enums/poi/VerticalAlignmentEnum.java
  13. 20
      src/main/java/com/alibaba/excel/metadata/data/DataFormatData.java
  14. 11
      src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java
  15. 23
      src/main/java/com/alibaba/excel/metadata/property/DateTimeFormatProperty.java
  16. 140
      src/main/java/com/alibaba/excel/metadata/property/FontProperty.java
  17. 128
      src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java
  18. 13
      src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
  19. 28
      src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java
  20. 7
      src/main/java/com/alibaba/excel/write/handler/context/CellWriteHandlerContext.java
  21. 199
      src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java
  22. 41
      src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java
  23. 15
      src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java
  24. 46
      src/main/java/com/alibaba/excel/write/style/DefaultStyle.java
  25. 21
      src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java
  26. 19
      src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java
  27. 24
      src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java
  28. 26
      src/test/java/com/alibaba/easyexcel/test/demo/write/CustomSheetWriteHandler.java
  29. 11
      src/test/java/com/alibaba/easyexcel/test/demo/write/DemoStyleData.java
  30. 96
      src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java
  31. 190
      src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java
  32. 5
      src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java
  33. 5
      src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java
  34. 5
      update.md

7
README.md

@ -29,9 +29,10 @@ Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都
* 3+ 版本至少 Java8 * 3+ 版本至少 Java8
### 关于版本升级 ### 关于版本升级
* 不建议跨大版本升级 尤其跨2个大版本 * 不建议跨大版本升级 尤其跨2个大版本
* 2+ 升级到 3+ * 2+ 升级到 3+ 一些不兼容的地方
* 使用了自定义拦截器去修改样式的会出问题 * 使用了自定义拦截器去修改样式的会出问题(不会编译报错)
* 读的时候`invoke`里面抛出异常,不会再额外封装一层`ExcelAnalysisException` * 读的时候`invoke`里面抛出异常,不会再额外封装一层`ExcelAnalysisException` (不会编译报错)
* 样式等注解涉及到 `boolean` or 一些枚举 值的 有变动,新增默认值(会编译报错,注解改就行)
* 大版本升级后建议相关内容重新测试下 * 大版本升级后建议相关内容重新测试下
## 人员招募 ## 人员招募

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId> <artifactId>easyexcel</artifactId>
<version>3.0.0-beta1</version> <version>3.0.0-beta2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>easyexcel</name> <name>easyexcel</name>

4
src/main/java/com/alibaba/excel/annotation/format/DateTimeFormat.java

@ -6,6 +6,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.alibaba.excel.enums.BooleanEnum;
/** /**
* Convert date format. * Convert date format.
* *
@ -34,5 +36,5 @@ public @interface DateTimeFormat {
* *
* @return True if date uses 1904 windowing, or false if using 1900 date windowing. * @return True if date uses 1904 windowing, or false if using 1900 date windowing.
*/ */
boolean use1904windowing() default false; BooleanEnum use1904windowing() default BooleanEnum.DEFAULT;
} }

8
src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java

@ -6,6 +6,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.alibaba.excel.enums.BooleanEnum;
import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font;
@ -34,12 +36,12 @@ public @interface ContentFontStyle {
/** /**
* Whether to use italics or not * Whether to use italics or not
*/ */
boolean italic() default false; BooleanEnum italic() default BooleanEnum.DEFAULT;
/** /**
* Whether to use a strikeout horizontal line through the text or not * Whether to use a strikeout horizontal line through the text or not
*/ */
boolean strikeout() default false; BooleanEnum strikeout() default BooleanEnum.DEFAULT;
/** /**
* The color for the font * The color for the font
@ -85,5 +87,5 @@ public @interface ContentFontStyle {
/** /**
* Bold * Bold
*/ */
boolean bold() default false; BooleanEnum bold() default BooleanEnum.DEFAULT;
} }

33
src/main/java/com/alibaba/excel/annotation/write/style/ContentStyle.java

@ -6,13 +6,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.apache.poi.ss.usermodel.BorderStyle; import com.alibaba.excel.enums.BooleanEnum;
import com.alibaba.excel.enums.poi.BorderStyleEnum;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IgnoredErrorType; import org.apache.poi.ss.usermodel.IgnoredErrorType;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/** /**
* Custom content styles * Custom content styles
@ -31,36 +34,36 @@ public @interface ContentStyle {
/** /**
* Set the cell's using this style to be hidden * Set the cell's using this style to be hidden
*/ */
boolean hidden() default false; BooleanEnum hidden() default BooleanEnum.DEFAULT;
/** /**
* Set the cell's using this style to be locked * Set the cell's using this style to be locked
*/ */
boolean locked() default false; BooleanEnum locked() default BooleanEnum.DEFAULT;
/** /**
* Turn on or off "Quote Prefix" or "123 Prefix" for the style, which is used to tell Excel that the thing which * Turn on or off "Quote Prefix" or "123 Prefix" for the style, which is used to tell Excel that the thing which
* looks like a number or a formula shouldn't be treated as on. Turning this on is somewhat (but not completely, see * looks like a number or a formula shouldn't be treated as on. Turning this on is somewhat (but not completely, see
* {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel * {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel
*/ */
boolean quotePrefix() default false; BooleanEnum quotePrefix() default BooleanEnum.DEFAULT;
/** /**
* Set the type of horizontal alignment for the cell * Set the type of horizontal alignment for the cell
*/ */
HorizontalAlignment horizontalAlignment() default HorizontalAlignment.GENERAL; HorizontalAlignmentEnum horizontalAlignment() default HorizontalAlignmentEnum.DEFAULT;
/** /**
* Set whether the text should be wrapped. Setting this flag to <code>true</code> make all content visible within a * Set whether the text should be wrapped. Setting this flag to <code>true</code> make all content visible within a
* cell by displaying it on multiple lines * cell by displaying it on multiple lines
* *
*/ */
boolean wrapped() default false; BooleanEnum wrapped() default BooleanEnum.DEFAULT;
/** /**
* Set the type of vertical alignment for the cell * Set the type of vertical alignment for the cell
*/ */
VerticalAlignment verticalAlignment() default VerticalAlignment.CENTER; VerticalAlignmentEnum verticalAlignment() default VerticalAlignmentEnum.DEFAULT;
/** /**
* Set the degree of rotation for the text in the cell. * Set the degree of rotation for the text in the cell.
@ -80,22 +83,22 @@ public @interface ContentStyle {
/** /**
* Set the type of border to use for the left border of the cell * Set the type of border to use for the left border of the cell
*/ */
BorderStyle borderLeft() default BorderStyle.NONE; BorderStyleEnum borderLeft() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the right border of the cell * Set the type of border to use for the right border of the cell
*/ */
BorderStyle borderRight() default BorderStyle.NONE; BorderStyleEnum borderRight() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the top border of the cell * Set the type of border to use for the top border of the cell
*/ */
BorderStyle borderTop() default BorderStyle.NONE; BorderStyleEnum borderTop() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the bottom border of the cell * Set the type of border to use for the bottom border of the cell
*/ */
BorderStyle borderBottom() default BorderStyle.NONE; BorderStyleEnum borderBottom() default BorderStyleEnum.DEFAULT;
/** /**
* Set the color to use for the left border * Set the color to use for the left border
@ -133,7 +136,7 @@ public @interface ContentStyle {
* *
* @see FillPatternType#SOLID_FOREGROUND * @see FillPatternType#SOLID_FOREGROUND
*/ */
FillPatternType fillPatternType() default FillPatternType.NO_FILL; FillPatternTypeEnum fillPatternType() default FillPatternTypeEnum.DEFAULT;
/** /**
* Set the background fill color. * Set the background fill color.
@ -154,6 +157,6 @@ public @interface ContentStyle {
/** /**
* Controls if the Cell should be auto-sized to shrink to fit if the text is too long * Controls if the Cell should be auto-sized to shrink to fit if the text is too long
*/ */
boolean shrinkToFit() default false; BooleanEnum shrinkToFit() default BooleanEnum.DEFAULT;
} }

12
src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java

@ -6,6 +6,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import com.alibaba.excel.enums.BooleanEnum;
import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font;
@ -24,22 +26,22 @@ public @interface HeadFontStyle {
/** /**
* The name for the font (i.e. Arial) * The name for the font (i.e. Arial)
*/ */
String fontName() default "宋体"; String fontName() default "";
/** /**
* Height in the familiar unit of measure - points * Height in the familiar unit of measure - points
*/ */
short fontHeightInPoints() default 14; short fontHeightInPoints() default -1;
/** /**
* Whether to use italics or not * Whether to use italics or not
*/ */
boolean italic() default false; BooleanEnum italic() default BooleanEnum.DEFAULT;
/** /**
* Whether to use a strikeout horizontal line through the text or not * Whether to use a strikeout horizontal line through the text or not
*/ */
boolean strikeout() default false; BooleanEnum strikeout() default BooleanEnum.DEFAULT;
/** /**
* The color for the font * The color for the font
@ -85,5 +87,5 @@ public @interface HeadFontStyle {
/** /**
* Bold * Bold
*/ */
boolean bold() default true; BooleanEnum bold() default BooleanEnum.DEFAULT;
} }

33
src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java

@ -6,13 +6,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.apache.poi.ss.usermodel.BorderStyle; import com.alibaba.excel.enums.BooleanEnum;
import com.alibaba.excel.enums.poi.BorderStyleEnum;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IgnoredErrorType; import org.apache.poi.ss.usermodel.IgnoredErrorType;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/** /**
* Custom header styles * Custom header styles
@ -31,35 +34,35 @@ public @interface HeadStyle {
/** /**
* Set the cell's using this style to be hidden * Set the cell's using this style to be hidden
*/ */
boolean hidden() default false; BooleanEnum hidden() default BooleanEnum.DEFAULT;
/** /**
* Set the cell's using this style to be locked * Set the cell's using this style to be locked
*/ */
boolean locked() default true; BooleanEnum locked() default BooleanEnum.DEFAULT;
/** /**
* Turn on or off "Quote Prefix" or "123 Prefix" for the style, which is used to tell Excel that the thing which * Turn on or off "Quote Prefix" or "123 Prefix" for the style, which is used to tell Excel that the thing which
* looks like a number or a formula shouldn't be treated as on. Turning this on is somewhat (but not completely, see * looks like a number or a formula shouldn't be treated as on. Turning this on is somewhat (but not completely, see
* {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel * {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel
*/ */
boolean quotePrefix() default false; BooleanEnum quotePrefix() default BooleanEnum.DEFAULT;
/** /**
* Set the type of horizontal alignment for the cell * Set the type of horizontal alignment for the cell
*/ */
HorizontalAlignment horizontalAlignment() default HorizontalAlignment.CENTER; HorizontalAlignmentEnum horizontalAlignment() default HorizontalAlignmentEnum.DEFAULT;
/** /**
* Set whether the text should be wrapped. Setting this flag to <code>true</code> make all content visible within a * Set whether the text should be wrapped. Setting this flag to <code>true</code> make all content visible within a
* cell by displaying it on multiple lines * cell by displaying it on multiple lines
*/ */
boolean wrapped() default true; BooleanEnum wrapped() default BooleanEnum.DEFAULT;
/** /**
* Set the type of vertical alignment for the cell * Set the type of vertical alignment for the cell
*/ */
VerticalAlignment verticalAlignment() default VerticalAlignment.CENTER; VerticalAlignmentEnum verticalAlignment() default VerticalAlignmentEnum.DEFAULT;
/** /**
* Set the degree of rotation for the text in the cell. * Set the degree of rotation for the text in the cell.
@ -79,22 +82,22 @@ public @interface HeadStyle {
/** /**
* Set the type of border to use for the left border of the cell * Set the type of border to use for the left border of the cell
*/ */
BorderStyle borderLeft() default BorderStyle.THIN; BorderStyleEnum borderLeft() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the right border of the cell * Set the type of border to use for the right border of the cell
*/ */
BorderStyle borderRight() default BorderStyle.THIN; BorderStyleEnum borderRight() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the top border of the cell * Set the type of border to use for the top border of the cell
*/ */
BorderStyle borderTop() default BorderStyle.THIN; BorderStyleEnum borderTop() default BorderStyleEnum.DEFAULT;
/** /**
* Set the type of border to use for the bottom border of the cell * Set the type of border to use for the bottom border of the cell
*/ */
BorderStyle borderBottom() default BorderStyle.THIN; BorderStyleEnum borderBottom() default BorderStyleEnum.DEFAULT;
/** /**
* Set the color to use for the left border * Set the color to use for the left border
@ -129,7 +132,7 @@ public @interface HeadStyle {
* *
* @see FillPatternType#SOLID_FOREGROUND * @see FillPatternType#SOLID_FOREGROUND
*/ */
FillPatternType fillPatternType() default FillPatternType.SOLID_FOREGROUND; FillPatternTypeEnum fillPatternType() default FillPatternTypeEnum.DEFAULT;
/** /**
* Set the background fill color. * Set the background fill color.
@ -148,6 +151,6 @@ public @interface HeadStyle {
/** /**
* Controls if the Cell should be auto-sized to shrink to fit if the text is too long * Controls if the Cell should be auto-sized to shrink to fit if the text is too long
*/ */
boolean shrinkToFit() default false; BooleanEnum shrinkToFit() default BooleanEnum.DEFAULT;
} }

33
src/main/java/com/alibaba/excel/enums/BooleanEnum.java

@ -0,0 +1,33 @@
package com.alibaba.excel.enums;
import lombok.Getter;
/**
* Default values cannot be used for annotations.
* So an additional an enumeration to determine whether the user has added the enumeration.
*
* @author Jiaju Zhuang
*/
@Getter
public enum BooleanEnum {
/**
* NULL
*/
DEFAULT(null),
/**
* TRUE
*/
TRUE(Boolean.TRUE),
/**
* FALSE
*/
FALSE(Boolean.FALSE),
;
Boolean booleanValue;
BooleanEnum(Boolean booleanValue) {
this.booleanValue = booleanValue;
}
}

95
src/main/java/com/alibaba/excel/enums/poi/BorderStyleEnum.java

@ -0,0 +1,95 @@
package com.alibaba.excel.enums.poi;
import lombok.Getter;
import org.apache.poi.ss.usermodel.BorderStyle;
/**
* The enumeration value indicating the line style of a border in a cell,
* i.e., whether it is bordered dash dot, dash dot dot, dashed, dotted, double, hair, medium,
* medium dash dot, medium dash dot dot, medium dashed, none, slant dash dot, thick or thin.
*
* @author Jiaju Zhuang
*/
@Getter
public enum BorderStyleEnum {
/**
* null
*/
DEFAULT(null),
/**
* No border (default)
*/
NONE(BorderStyle.NONE),
/**
* Thin border
*/
THIN(BorderStyle.THIN),
/**
* Medium border
*/
MEDIUM(BorderStyle.MEDIUM),
/**
* dash border
*/
DASHED(BorderStyle.DASHED),
/**
* dot border
*/
DOTTED(BorderStyle.DOTTED),
/**
* Thick border
*/
THICK(BorderStyle.THICK),
/**
* double-line border
*/
DOUBLE(BorderStyle.DOUBLE),
/**
* hair-line border
*/
HAIR(BorderStyle.HAIR),
/**
* Medium dashed border
*/
MEDIUM_DASHED(BorderStyle.MEDIUM_DASHED),
/**
* dash-dot border
*/
DASH_DOT(BorderStyle.DASH_DOT),
/**
* medium dash-dot border
*/
MEDIUM_DASH_DOT(BorderStyle.MEDIUM_DASH_DOT),
/**
* dash-dot-dot border
*/
DASH_DOT_DOT(BorderStyle.DASH_DOT_DOT),
/**
* medium dash-dot-dot border
*/
MEDIUM_DASH_DOT_DOT(BorderStyle.MEDIUM_DASH_DOT_DOT),
/**
* slanted dash-dot border
*/
SLANTED_DASH_DOT(BorderStyle.SLANTED_DASH_DOT);
BorderStyle poiBorderStyle;
BorderStyleEnum(BorderStyle poiBorderStyle) {
this.poiBorderStyle = poiBorderStyle;
}
}

119
src/main/java/com/alibaba/excel/enums/poi/FillPatternTypeEnum.java

@ -0,0 +1,119 @@
package com.alibaba.excel.enums.poi;
import lombok.Getter;
import org.apache.poi.ss.usermodel.FillPatternType;
/**
* The enumeration value indicating the style of fill pattern being used for a cell format.
*
* @author Jiaju Zhuang
*/
@Getter
public enum FillPatternTypeEnum {
/**
* null
*/
DEFAULT(null),
/**
* No background
*/
NO_FILL(FillPatternType.NO_FILL),
/**
* Solidly filled
*/
SOLID_FOREGROUND(FillPatternType.SOLID_FOREGROUND),
/**
* Small fine dots
*/
FINE_DOTS(FillPatternType.FINE_DOTS),
/**
* Wide dots
*/
ALT_BARS(FillPatternType.ALT_BARS),
/**
* Sparse dots
*/
SPARSE_DOTS(FillPatternType.SPARSE_DOTS),
/**
* Thick horizontal bands
*/
THICK_HORZ_BANDS(FillPatternType.THICK_HORZ_BANDS),
/**
* Thick vertical bands
*/
THICK_VERT_BANDS(FillPatternType.THICK_VERT_BANDS),
/**
* Thick backward facing diagonals
*/
THICK_BACKWARD_DIAG(FillPatternType.THICK_BACKWARD_DIAG),
/**
* Thick forward facing diagonals
*/
THICK_FORWARD_DIAG(FillPatternType.THICK_FORWARD_DIAG),
/**
* Large spots
*/
BIG_SPOTS(FillPatternType.BIG_SPOTS),
/**
* Brick-like layout
*/
BRICKS(FillPatternType.BRICKS),
/**
* Thin horizontal bands
*/
THIN_HORZ_BANDS(FillPatternType.THIN_HORZ_BANDS),
/**
* Thin vertical bands
*/
THIN_VERT_BANDS(FillPatternType.THIN_VERT_BANDS),
/**
* Thin backward diagonal
*/
THIN_BACKWARD_DIAG(FillPatternType.THIN_BACKWARD_DIAG),
/**
* Thin forward diagonal
*/
THIN_FORWARD_DIAG(FillPatternType.THIN_FORWARD_DIAG),
/**
* Squares
*/
SQUARES(FillPatternType.SQUARES),
/**
* Diamonds
*/
DIAMONDS(FillPatternType.DIAMONDS),
/**
* Less Dots
*/
LESS_DOTS(FillPatternType.LESS_DOTS),
/**
* Least Dots
*/
LEAST_DOTS(FillPatternType.LEAST_DOTS);
FillPatternType poiFillPatternType;
FillPatternTypeEnum(FillPatternType poiFillPatternType) {
this.poiFillPatternType = poiFillPatternType;
}
}

94
src/main/java/com/alibaba/excel/enums/poi/HorizontalAlignmentEnum.java

@ -0,0 +1,94 @@
package com.alibaba.excel.enums.poi;
import lombok.Getter;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
/**
* The enumeration value indicating horizontal alignment of a cell,
* i.e., whether it is aligned general, left, right, horizontally centered, filled (replicated),
* justified, centered across multiple cells, or distributed.
* @author Jiaju Zhuang
*/
@Getter
public enum HorizontalAlignmentEnum {
/**
* null
*/
DEFAULT(null),
/**
* The horizontal alignment is general-aligned. Text data is left-aligned.
* Numbers, dates, and times are rightaligned. Boolean types are centered.
* Changing the alignment does not change the type of data.
*/
GENERAL(HorizontalAlignment.GENERAL),
/**
* The horizontal alignment is left-aligned, even in Rightto-Left mode.
* Aligns contents at the left edge of the cell. If an indent amount is specified, the contents of
* the cell is indented from the left by the specified number of character spaces. The character spaces are
* based on the default font and font size for the workbook.
*/
LEFT(HorizontalAlignment.LEFT),
/**
* The horizontal alignment is centered, meaning the text is centered across the cell.
*/
CENTER(HorizontalAlignment.CENTER),
/**
* The horizontal alignment is right-aligned, meaning that cell contents are aligned at the right edge of the cell,
* even in Right-to-Left mode.
*/
RIGHT(HorizontalAlignment.RIGHT),
/**
* Indicates that the value of the cell should be filled
* across the entire width of the cell. If blank cells to the right also have the fill alignment,
* they are also filled with the value, using a convention similar to centerContinuous.
* <p>
* Additional rules:
* <ol>
* <li>Only whole values can be appended, not partial values.</li>
* <li>The column will not be widened to 'best fit' the filled value</li>
* <li>If appending an additional occurrence of the value exceeds the boundary of the cell
* left/right edge, don't append the additional occurrence of the value.</li>
* <li>The display value of the cell is filled, not the underlying raw number.</li>
* </ol>
* </p>
*/
FILL(HorizontalAlignment.FILL),
/**
* The horizontal alignment is justified (flush left and right).
* For each line of text, aligns each line of the wrapped text in a cell to the right and left
* (except the last line). If no single line of text wraps in the cell, then the text is not justified.
*/
JUSTIFY(HorizontalAlignment.JUSTIFY),
/**
* The horizontal alignment is centered across multiple cells.
* The information about how many cells to span is expressed in the Sheet Part,
* in the row of the cell in question. For each cell that is spanned in the alignment,
* a cell element needs to be written out, with the same style Id which references the centerContinuous alignment.
*/
CENTER_SELECTION(HorizontalAlignment.CENTER_SELECTION),
/**
* Indicates that each 'word' in each line of text inside the cell is evenly distributed
* across the width of the cell, with flush right and left margins.
* <p>
* When there is also an indent value to apply, both the left and right side of the cell
* are padded by the indent value.
* </p>
* <p> A 'word' is a set of characters with no space character in them. </p>
* <p> Two lines inside a cell are separated by a carriage return. </p>
*/
DISTRIBUTED(HorizontalAlignment.DISTRIBUTED);
HorizontalAlignment poiHorizontalAlignment;
HorizontalAlignmentEnum(HorizontalAlignment poiHorizontalAlignment) {
this.poiHorizontalAlignment = poiHorizontalAlignment;
}
}

71
src/main/java/com/alibaba/excel/enums/poi/VerticalAlignmentEnum.java

@ -0,0 +1,71 @@
package com.alibaba.excel.enums.poi;
import lombok.Getter;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* This enumeration value indicates the type of vertical alignment for a cell, i.e.,
* whether it is aligned top, bottom, vertically centered, justified or distributed.
*
* <!-- FIXME: Identical to {@link org.apache.poi.ss.usermodel.VerticalAlignment}. Should merge these to
* {@link org.apache.poi.common.usermodel}.VerticalAlignment in the future. -->
*
* @author Jiaju Zhuang
*/
@Getter
public enum VerticalAlignmentEnum {
/**
* null
*/
DEFAULT(null),
/**
* The vertical alignment is aligned-to-top.
*/
TOP(VerticalAlignment.TOP),
/**
* The vertical alignment is centered across the height of the cell.
*/
CENTER(VerticalAlignment.CENTER),
/**
* The vertical alignment is aligned-to-bottom. (typically the default value)
*/
BOTTOM(VerticalAlignment.BOTTOM),
/**
* <p>
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
* where each line of text inside the cell is evenly distributed across the height of the cell,
* with flush top and bottom margins.
* </p>
* <p>
* When text direction is vertical: similar behavior as horizontal justification.
* The alignment is justified (flush top and bottom in this case). For each line of text, each
* line of the wrapped text in a cell is aligned to the top and bottom (except the last line).
* If no single line of text wraps in the cell, then the text is not justified.
* </p>
*/
JUSTIFY(VerticalAlignment.JUSTIFY),
/**
* <p>
* When text direction is horizontal: the vertical alignment of lines of text is distributed vertically,
* where each line of text inside the cell is evenly distributed across the height of the cell,
* with flush top
* </p>
* <p>
* When text direction is vertical: behaves exactly as distributed horizontal alignment.
* The first words in a line of text (appearing at the top of the cell) are flush
* with the top edge of the cell, and the last words of a line of text are flush with the bottom edge of the cell,
* and the line of text is distributed evenly from top to bottom.
* </p>
*/
DISTRIBUTED(VerticalAlignment.DISTRIBUTED);
VerticalAlignment poiVerticalAlignmentEnum;
VerticalAlignmentEnum(VerticalAlignment poiVerticalAlignmentEnum) {
this.poiVerticalAlignmentEnum = poiVerticalAlignmentEnum;
}
}

20
src/main/java/com/alibaba/excel/metadata/data/DataFormatData.java

@ -1,5 +1,7 @@
package com.alibaba.excel.metadata.data; package com.alibaba.excel.metadata.data;
import com.alibaba.excel.util.StringUtils;
import lombok.Data; import lombok.Data;
/** /**
@ -19,6 +21,24 @@ public class DataFormatData {
*/ */
private String format; private String format;
/**
* The source is not empty merge the data to the target.
*
* @param source source
* @param target target
*/
public static void merge(DataFormatData source, DataFormatData target) {
if (source == null || target == null) {
return;
}
if (source.getIndex() != null) {
target.setIndex(source.getIndex());
}
if (StringUtils.isNotBlank(source.getFormat())) {
target.setFormat(source.getFormat());
}
}
@Override @Override
public DataFormatData clone() { public DataFormatData clone() {
DataFormatData dataFormatData = new DataFormatData(); DataFormatData dataFormatData = new DataFormatData();

11
src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java

@ -116,4 +116,15 @@ public class WriteCellData<T> extends CellData<T> {
imageDataList.add(imageData); imageDataList.add(imageData);
} }
/**
* Return a style, if is empty, create a new
*
* @return not null.
*/
public WriteCellStyle getOrCreateStyle() {
if (this.writeCellStyle == null) {
this.writeCellStyle = new WriteCellStyle();
}
return this.writeCellStyle;
}
} }

23
src/main/java/com/alibaba/excel/metadata/property/DateTimeFormatProperty.java

@ -1,12 +1,16 @@
package com.alibaba.excel.metadata.property; package com.alibaba.excel.metadata.property;
import com.alibaba.excel.annotation.format.DateTimeFormat; import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.util.BooleanUtils;
import lombok.Data;
/** /**
* Configuration from annotations * Configuration from annotations
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Data
public class DateTimeFormatProperty { public class DateTimeFormatProperty {
private String format; private String format;
private Boolean use1904windowing; private Boolean use1904windowing;
@ -20,22 +24,7 @@ public class DateTimeFormatProperty {
if (dateTimeFormat == null) { if (dateTimeFormat == null) {
return null; return null;
} }
return new DateTimeFormatProperty(dateTimeFormat.value(), dateTimeFormat.use1904windowing()); return new DateTimeFormatProperty(dateTimeFormat.value(),
} BooleanUtils.isTrue(dateTimeFormat.use1904windowing().getBooleanValue()));
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public Boolean getUse1904windowing() {
return use1904windowing;
}
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
} }
} }

140
src/main/java/com/alibaba/excel/metadata/property/FontProperty.java

@ -1,18 +1,21 @@
package com.alibaba.excel.metadata.property; package com.alibaba.excel.metadata.property;
import com.alibaba.excel.annotation.write.style.ContentFontStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.util.StringUtils;
import lombok.Data;
import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import com.alibaba.excel.annotation.write.style.ContentFontStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
/** /**
* Configuration from annotations * Configuration from annotations
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Data
public class FontProperty { public class FontProperty {
/** /**
* The name for the font (i.e. Arial) * The name for the font (i.e. Arial)
@ -77,15 +80,27 @@ public class FontProperty {
return null; return null;
} }
FontProperty styleProperty = new FontProperty(); FontProperty styleProperty = new FontProperty();
styleProperty.setFontName(headFontStyle.fontName()); if (StringUtils.isNotBlank(headFontStyle.fontName())) {
styleProperty.setFontHeightInPoints(headFontStyle.fontHeightInPoints()); styleProperty.setFontName(headFontStyle.fontName());
styleProperty.setItalic(headFontStyle.italic()); }
styleProperty.setStrikeout(headFontStyle.strikeout()); if (headFontStyle.fontHeightInPoints() >= 0) {
styleProperty.setColor(headFontStyle.color()); styleProperty.setFontHeightInPoints(headFontStyle.fontHeightInPoints());
styleProperty.setTypeOffset(headFontStyle.typeOffset()); }
styleProperty.setUnderline(headFontStyle.underline()); styleProperty.setItalic(headFontStyle.italic().getBooleanValue());
styleProperty.setCharset(headFontStyle.charset()); styleProperty.setStrikeout(headFontStyle.strikeout().getBooleanValue());
styleProperty.setBold(headFontStyle.bold()); if (headFontStyle.color() >= 0) {
styleProperty.setColor(headFontStyle.color());
}
if (headFontStyle.typeOffset() >= 0) {
styleProperty.setTypeOffset(headFontStyle.typeOffset());
}
if (headFontStyle.underline() >= 0) {
styleProperty.setUnderline(headFontStyle.underline());
}
if (headFontStyle.charset() >= 0) {
styleProperty.setCharset(headFontStyle.charset());
}
styleProperty.setBold(headFontStyle.bold().getBooleanValue());
return styleProperty; return styleProperty;
} }
@ -94,87 +109,28 @@ public class FontProperty {
return null; return null;
} }
FontProperty styleProperty = new FontProperty(); FontProperty styleProperty = new FontProperty();
styleProperty.setFontName(contentFontStyle.fontName()); if (StringUtils.isNotBlank(contentFontStyle.fontName())) {
styleProperty.setFontHeightInPoints(contentFontStyle.fontHeightInPoints()); styleProperty.setFontName(contentFontStyle.fontName());
styleProperty.setItalic(contentFontStyle.italic()); }
styleProperty.setStrikeout(contentFontStyle.strikeout()); if (contentFontStyle.fontHeightInPoints() >= 0) {
styleProperty.setColor(contentFontStyle.color()); styleProperty.setFontHeightInPoints(contentFontStyle.fontHeightInPoints());
styleProperty.setTypeOffset(contentFontStyle.typeOffset()); }
styleProperty.setUnderline(contentFontStyle.underline()); styleProperty.setItalic(contentFontStyle.italic().getBooleanValue());
styleProperty.setCharset(contentFontStyle.charset()); styleProperty.setStrikeout(contentFontStyle.strikeout().getBooleanValue());
styleProperty.setBold(contentFontStyle.bold()); if (contentFontStyle.color() >= 0) {
styleProperty.setColor(contentFontStyle.color());
}
if (contentFontStyle.typeOffset() >= 0) {
styleProperty.setTypeOffset(contentFontStyle.typeOffset());
}
if (contentFontStyle.underline() >= 0) {
styleProperty.setUnderline(contentFontStyle.underline());
}
if (contentFontStyle.charset() >= 0) {
styleProperty.setCharset(contentFontStyle.charset());
}
styleProperty.setBold(contentFontStyle.bold().getBooleanValue());
return styleProperty; return styleProperty;
} }
public String getFontName() {
return fontName;
}
public void setFontName(String fontName) {
this.fontName = fontName;
}
public Short getFontHeightInPoints() {
return fontHeightInPoints;
}
public void setFontHeightInPoints(Short fontHeightInPoints) {
this.fontHeightInPoints = fontHeightInPoints;
}
public Boolean getItalic() {
return italic;
}
public void setItalic(Boolean italic) {
this.italic = italic;
}
public Boolean getStrikeout() {
return strikeout;
}
public void setStrikeout(Boolean strikeout) {
this.strikeout = strikeout;
}
public Short getColor() {
return color;
}
public void setColor(Short color) {
this.color = color;
}
public Short getTypeOffset() {
return typeOffset;
}
public void setTypeOffset(Short typeOffset) {
this.typeOffset = typeOffset;
}
public Byte getUnderline() {
return underline;
}
public void setUnderline(Byte underline) {
this.underline = underline;
}
public Integer getCharset() {
return charset;
}
public void setCharset(Integer charset) {
this.charset = charset;
}
public Boolean getBold() {
return bold;
}
public void setBold(Boolean bold) {
this.bold = bold;
}
} }

128
src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java

@ -143,29 +143,47 @@ public class StyleProperty {
return null; return null;
} }
StyleProperty styleProperty = new StyleProperty(); StyleProperty styleProperty = new StyleProperty();
DataFormatData dataFormatData = new DataFormatData(); if (headStyle.dataFormat() >= 0) {
dataFormatData.setIndex(headStyle.dataFormat()); DataFormatData dataFormatData = new DataFormatData();
styleProperty.setDataFormatData(dataFormatData); dataFormatData.setIndex(headStyle.dataFormat());
styleProperty.setHidden(headStyle.hidden()); styleProperty.setDataFormatData(dataFormatData);
styleProperty.setLocked(headStyle.locked()); }
styleProperty.setQuotePrefix(headStyle.quotePrefix()); styleProperty.setHidden(headStyle.hidden().getBooleanValue());
styleProperty.setHorizontalAlignment(headStyle.horizontalAlignment()); styleProperty.setLocked(headStyle.locked().getBooleanValue());
styleProperty.setWrapped(headStyle.wrapped()); styleProperty.setQuotePrefix(headStyle.quotePrefix().getBooleanValue());
styleProperty.setVerticalAlignment(headStyle.verticalAlignment()); styleProperty.setHorizontalAlignment(headStyle.horizontalAlignment().getPoiHorizontalAlignment());
styleProperty.setRotation(headStyle.rotation()); styleProperty.setWrapped(headStyle.wrapped().getBooleanValue());
styleProperty.setIndent(headStyle.indent()); styleProperty.setVerticalAlignment(headStyle.verticalAlignment().getPoiVerticalAlignmentEnum());
styleProperty.setBorderLeft(headStyle.borderLeft()); if (headStyle.rotation() >= 0) {
styleProperty.setBorderRight(headStyle.borderRight()); styleProperty.setRotation(headStyle.rotation());
styleProperty.setBorderTop(headStyle.borderTop()); }
styleProperty.setBorderBottom(headStyle.borderBottom()); if (headStyle.indent() >= 0) {
styleProperty.setLeftBorderColor(headStyle.leftBorderColor()); styleProperty.setIndent(headStyle.indent());
styleProperty.setRightBorderColor(headStyle.rightBorderColor()); }
styleProperty.setTopBorderColor(headStyle.topBorderColor()); styleProperty.setBorderLeft(headStyle.borderLeft().getPoiBorderStyle());
styleProperty.setBottomBorderColor(headStyle.bottomBorderColor()); styleProperty.setBorderRight(headStyle.borderRight().getPoiBorderStyle());
styleProperty.setFillPatternType(headStyle.fillPatternType()); styleProperty.setBorderTop(headStyle.borderTop().getPoiBorderStyle());
styleProperty.setFillBackgroundColor(headStyle.fillBackgroundColor()); styleProperty.setBorderBottom(headStyle.borderBottom().getPoiBorderStyle());
styleProperty.setFillForegroundColor(headStyle.fillForegroundColor()); if (headStyle.leftBorderColor() >= 0) {
styleProperty.setShrinkToFit(headStyle.shrinkToFit()); styleProperty.setLeftBorderColor(headStyle.leftBorderColor());
}
if (headStyle.rightBorderColor() >= 0) {
styleProperty.setRightBorderColor(headStyle.rightBorderColor());
}
if (headStyle.topBorderColor() >= 0) {
styleProperty.setTopBorderColor(headStyle.topBorderColor());
}
if (headStyle.bottomBorderColor() >= 0) {
styleProperty.setBottomBorderColor(headStyle.bottomBorderColor());
}
styleProperty.setFillPatternType(headStyle.fillPatternType().getPoiFillPatternType());
if (headStyle.fillBackgroundColor() >= 0) {
styleProperty.setFillBackgroundColor(headStyle.fillBackgroundColor());
}
if (headStyle.fillForegroundColor() >= 0) {
styleProperty.setFillForegroundColor(headStyle.fillForegroundColor());
}
styleProperty.setShrinkToFit(headStyle.shrinkToFit().getBooleanValue());
return styleProperty; return styleProperty;
} }
@ -174,29 +192,47 @@ public class StyleProperty {
return null; return null;
} }
StyleProperty styleProperty = new StyleProperty(); StyleProperty styleProperty = new StyleProperty();
DataFormatData dataFormatData = new DataFormatData(); if (contentStyle.dataFormat() >= 0) {
dataFormatData.setIndex(contentStyle.dataFormat()); DataFormatData dataFormatData = new DataFormatData();
styleProperty.setDataFormatData(dataFormatData); dataFormatData.setIndex(contentStyle.dataFormat());
styleProperty.setHidden(contentStyle.hidden()); styleProperty.setDataFormatData(dataFormatData);
styleProperty.setLocked(contentStyle.locked()); }
styleProperty.setQuotePrefix(contentStyle.quotePrefix()); styleProperty.setHidden(contentStyle.hidden().getBooleanValue());
styleProperty.setHorizontalAlignment(contentStyle.horizontalAlignment()); styleProperty.setLocked(contentStyle.locked().getBooleanValue());
styleProperty.setWrapped(contentStyle.wrapped()); styleProperty.setQuotePrefix(contentStyle.quotePrefix().getBooleanValue());
styleProperty.setVerticalAlignment(contentStyle.verticalAlignment()); styleProperty.setHorizontalAlignment(contentStyle.horizontalAlignment().getPoiHorizontalAlignment());
styleProperty.setRotation(contentStyle.rotation()); styleProperty.setWrapped(contentStyle.wrapped().getBooleanValue());
styleProperty.setIndent(contentStyle.indent()); styleProperty.setVerticalAlignment(contentStyle.verticalAlignment().getPoiVerticalAlignmentEnum());
styleProperty.setBorderLeft(contentStyle.borderLeft()); if (contentStyle.rotation() >= 0) {
styleProperty.setBorderRight(contentStyle.borderRight()); styleProperty.setRotation(contentStyle.rotation());
styleProperty.setBorderTop(contentStyle.borderTop()); }
styleProperty.setBorderBottom(contentStyle.borderBottom()); if (contentStyle.indent() >= 0) {
styleProperty.setLeftBorderColor(contentStyle.leftBorderColor()); styleProperty.setIndent(contentStyle.indent());
styleProperty.setRightBorderColor(contentStyle.rightBorderColor()); }
styleProperty.setTopBorderColor(contentStyle.topBorderColor()); styleProperty.setBorderLeft(contentStyle.borderLeft().getPoiBorderStyle());
styleProperty.setBottomBorderColor(contentStyle.bottomBorderColor()); styleProperty.setBorderRight(contentStyle.borderRight().getPoiBorderStyle());
styleProperty.setFillPatternType(contentStyle.fillPatternType()); styleProperty.setBorderTop(contentStyle.borderTop().getPoiBorderStyle());
styleProperty.setFillBackgroundColor(contentStyle.fillBackgroundColor()); styleProperty.setBorderBottom(contentStyle.borderBottom().getPoiBorderStyle());
styleProperty.setFillForegroundColor(contentStyle.fillForegroundColor()); if (contentStyle.leftBorderColor() >= 0) {
styleProperty.setShrinkToFit(contentStyle.shrinkToFit()); styleProperty.setLeftBorderColor(contentStyle.leftBorderColor());
}
if (contentStyle.rightBorderColor() >= 0) {
styleProperty.setRightBorderColor(contentStyle.rightBorderColor());
}
if (contentStyle.topBorderColor() >= 0) {
styleProperty.setTopBorderColor(contentStyle.topBorderColor());
}
if (contentStyle.bottomBorderColor() >= 0) {
styleProperty.setBottomBorderColor(contentStyle.bottomBorderColor());
}
styleProperty.setFillPatternType(contentStyle.fillPatternType().getPoiFillPatternType());
if (contentStyle.fillBackgroundColor() >= 0) {
styleProperty.setFillBackgroundColor(contentStyle.fillBackgroundColor());
}
if (contentStyle.fillForegroundColor() >= 0) {
styleProperty.setFillForegroundColor(contentStyle.fillForegroundColor());
}
styleProperty.setShrinkToFit(contentStyle.shrinkToFit().getBooleanValue());
return styleProperty; return styleProperty;
} }
} }

13
src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java

@ -16,6 +16,7 @@ import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext; import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext; import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
@ -123,7 +124,7 @@ public class WriteHandlerUtils {
} }
CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, null, columnIndex, relativeRowIndex, writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, null, columnIndex, relativeRowIndex,
head, null, isHead); head, null, null, isHead);
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).beforeCellCreate(context); ((CellWriteHandler)writeHandler).beforeCellCreate(context);
@ -140,7 +141,7 @@ public class WriteHandlerUtils {
} }
CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell,
cell.getColumnIndex(), relativeRowIndex, head, null, isHead); cell.getColumnIndex(), relativeRowIndex, head, null, null, isHead);
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellCreate(context); ((CellWriteHandler)writeHandler).afterCellCreate(context);
@ -159,7 +160,7 @@ public class WriteHandlerUtils {
List<WriteCellData<?>> cellDataList = cellData == null ? null : ListUtils.newArrayList(cellData); List<WriteCellData<?>> cellDataList = cellData == null ? null : ListUtils.newArrayList(cellData);
CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell,
cell.getColumnIndex(), relativeRowIndex, head, cellDataList, isHead); cell.getColumnIndex(), relativeRowIndex, head, cellDataList, cellData, isHead);
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellDataConverted(context); ((CellWriteHandler)writeHandler).afterCellDataConverted(context);
@ -181,9 +182,13 @@ public class WriteHandlerUtils {
if (handlerList == null || handlerList.isEmpty()) { if (handlerList == null || handlerList.isEmpty()) {
return; return;
} }
WriteCellData<?> cellData = null;
if (CollectionUtils.isNotEmpty(cellDataList)) {
cellData = cellDataList.get(0);
}
CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(),
writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell,
cell.getColumnIndex(), relativeRowIndex, head, cellDataList, isHead); cell.getColumnIndex(), relativeRowIndex, head, cellDataList, cellData, isHead);
for (WriteHandler writeHandler : handlerList) { for (WriteHandler writeHandler : handlerList) {
if (writeHandler instanceof CellWriteHandler) { if (writeHandler instanceof CellWriteHandler) {
((CellWriteHandler)writeHandler).afterCellDispose(context); ((CellWriteHandler)writeHandler).afterCellDispose(context);

28
src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java

@ -6,15 +6,7 @@ import java.util.List;
import com.alibaba.excel.write.handler.impl.DefaultRowWriteHandler; import com.alibaba.excel.write.handler.impl.DefaultRowWriteHandler;
import com.alibaba.excel.write.handler.impl.DimensionWorkbookWriteHandler; import com.alibaba.excel.write.handler.impl.DimensionWorkbookWriteHandler;
import com.alibaba.excel.write.handler.impl.FillStyleCellWriteHandler; import com.alibaba.excel.write.handler.impl.FillStyleCellWriteHandler;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.style.DefaultStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/** /**
* Load default handler * Load default handler
@ -39,23 +31,7 @@ public class DefaultWriteHandlerLoader {
public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) { public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) {
List<WriteHandler> handlerList = new ArrayList<>(); List<WriteHandler> handlerList = new ArrayList<>();
if (useDefaultStyle) { if (useDefaultStyle) {
WriteCellStyle headWriteCellStyle = new WriteCellStyle(); handlerList.add(new DefaultStyle());
headWriteCellStyle.setWrapped(true);
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headWriteCellStyle.setLocked(true);
headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
headWriteCellStyle.setBorderTop(BorderStyle.THIN);
headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
headWriteCellStyle.setBorderRight(BorderStyle.THIN);
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontName("宋体");
headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<>()));
} }
handlerList.addAll(DEFAULT_WRITE_HANDLER_LIST); handlerList.addAll(DEFAULT_WRITE_HANDLER_LIST);
return handlerList; return handlerList;

7
src/main/java/com/alibaba/excel/write/handler/context/CellWriteHandlerContext.java

@ -62,6 +62,13 @@ public class CellWriteHandlerContext {
* Nullable.It is null in the case of add header.There may be several when fill the data. * Nullable.It is null in the case of add header.There may be several when fill the data.
*/ */
private List<WriteCellData<?>> cellDataList; private List<WriteCellData<?>> cellDataList;
/**
* Nullable.
* It is null in the case of add header.
* In the case of write there must be not null.
* firstCellData == cellDataList.get(0)
*/
private WriteCellData<?> firstCellData;
/** /**
* Nullable.It is null in the case of fill data. * Nullable.It is null in the case of fill data.
*/ */

199
src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java

@ -139,74 +139,207 @@ public class WriteCellStyle {
*/ */
private Boolean shrinkToFit; private Boolean shrinkToFit;
/**
* The source is not empty merge the data to the target.
*
* @param source source
* @param target target
*/
public static void merge(WriteCellStyle source, WriteCellStyle target) {
if (source == null || target == null) {
return;
}
if (source.getDataFormatData() != null) {
if (target.getDataFormatData() == null) {
target.setDataFormatData(source.getDataFormatData());
} else {
DataFormatData.merge(source.getDataFormatData(), target.getDataFormatData());
}
}
if (source.getWriteFont() != null) {
if (target.getWriteFont() == null) {
target.setWriteFont(source.getWriteFont());
} else {
WriteFont.merge(source.getWriteFont(), target.getWriteFont());
}
}
if (source.getHidden() != null) {
target.setHidden(source.getHidden());
}
if (source.getLocked() != null) {
target.setLocked(source.getLocked());
}
if (source.getQuotePrefix() != null) {
target.setQuotePrefix(source.getQuotePrefix());
}
if (source.getHorizontalAlignment() != null) {
target.setHorizontalAlignment(source.getHorizontalAlignment());
}
if (source.getWrapped() != null) {
target.setWrapped(source.getWrapped());
}
if (source.getVerticalAlignment() != null) {
target.setVerticalAlignment(source.getVerticalAlignment());
}
if (source.getRotation() != null) {
target.setRotation(source.getRotation());
}
if (source.getIndent() != null) {
target.setIndent(source.getIndent());
}
if (source.getBorderLeft() != null) {
target.setBorderLeft(source.getBorderLeft());
}
if (source.getBorderRight() != null) {
target.setBorderRight(source.getBorderRight());
}
if (source.getBorderTop() != null) {
target.setBorderTop(source.getBorderTop());
}
if (source.getBorderBottom() != null) {
target.setBorderBottom(source.getBorderBottom());
}
if (source.getLeftBorderColor() != null) {
target.setLeftBorderColor(source.getLeftBorderColor());
}
if (source.getRightBorderColor() != null) {
target.setRightBorderColor(source.getRightBorderColor());
}
if (source.getTopBorderColor() != null) {
target.setTopBorderColor(source.getTopBorderColor());
}
if (source.getBottomBorderColor() != null) {
target.setBottomBorderColor(source.getBottomBorderColor());
}
if (source.getFillPatternType() != null) {
target.setFillPatternType(source.getFillPatternType());
}
if (source.getFillBackgroundColor() != null) {
target.setFillBackgroundColor(source.getFillBackgroundColor());
}
if (source.getFillForegroundColor() != null) {
target.setFillForegroundColor(source.getFillForegroundColor());
}
if (source.getShrinkToFit() != null) {
target.setShrinkToFit(source.getShrinkToFit());
}
}
/**
* The source is not empty merge the data to the target.
*
* @param styleProperty styleProperty
* @param fontProperty fontProperty
*/
public static WriteCellStyle build(StyleProperty styleProperty, FontProperty fontProperty) { public static WriteCellStyle build(StyleProperty styleProperty, FontProperty fontProperty) {
if (styleProperty == null && fontProperty == null) { if (styleProperty == null && fontProperty == null) {
return null; return null;
} }
WriteCellStyle writeCellStyle = new WriteCellStyle(); WriteCellStyle writeCellStyle = new WriteCellStyle();
if (styleProperty != null) { if (styleProperty != null) {
writeCellStyle.setDataFormatData(styleProperty.getDataFormatData()); if (styleProperty.getDataFormatData() != null) {
writeCellStyle.setHidden(styleProperty.getHidden()); if (writeCellStyle.getDataFormatData() == null) {
writeCellStyle.setLocked(styleProperty.getLocked()); writeCellStyle.setDataFormatData(styleProperty.getDataFormatData());
writeCellStyle.setQuotePrefix(styleProperty.getQuotePrefix()); } else {
writeCellStyle.setHorizontalAlignment(styleProperty.getHorizontalAlignment()); DataFormatData.merge(styleProperty.getDataFormatData(), writeCellStyle.getDataFormatData());
writeCellStyle.setWrapped(styleProperty.getWrapped()); }
writeCellStyle.setVerticalAlignment(styleProperty.getVerticalAlignment()); }
if (styleProperty.getRotation() >= 0) { if (styleProperty.getHidden() != null) {
writeCellStyle.setHidden(styleProperty.getHidden());
}
if (styleProperty.getLocked() != null) {
writeCellStyle.setLocked(styleProperty.getLocked());
}
if (styleProperty.getQuotePrefix() != null) {
writeCellStyle.setQuotePrefix(styleProperty.getQuotePrefix());
}
if (styleProperty.getHorizontalAlignment() != null) {
writeCellStyle.setHorizontalAlignment(styleProperty.getHorizontalAlignment());
}
if (styleProperty.getWrapped() != null) {
writeCellStyle.setWrapped(styleProperty.getWrapped());
}
if (styleProperty.getVerticalAlignment() != null) {
writeCellStyle.setVerticalAlignment(styleProperty.getVerticalAlignment());
}
if (styleProperty.getRotation() != null) {
writeCellStyle.setRotation(styleProperty.getRotation()); writeCellStyle.setRotation(styleProperty.getRotation());
} }
if (styleProperty.getIndent() >= 0) { if (styleProperty.getIndent() != null) {
writeCellStyle.setIndent(styleProperty.getIndent()); writeCellStyle.setIndent(styleProperty.getIndent());
} }
writeCellStyle.setBorderLeft(styleProperty.getBorderLeft()); if (styleProperty.getBorderLeft() != null) {
writeCellStyle.setBorderRight(styleProperty.getBorderRight()); writeCellStyle.setBorderLeft(styleProperty.getBorderLeft());
writeCellStyle.setBorderTop(styleProperty.getBorderTop()); }
writeCellStyle.setBorderBottom(styleProperty.getBorderBottom()); if (styleProperty.getBorderRight() != null) {
if (styleProperty.getLeftBorderColor() >= 0) { writeCellStyle.setBorderRight(styleProperty.getBorderRight());
}
if (styleProperty.getBorderTop() != null) {
writeCellStyle.setBorderTop(styleProperty.getBorderTop());
}
if (styleProperty.getBorderBottom() != null) {
writeCellStyle.setBorderBottom(styleProperty.getBorderBottom());
}
if (styleProperty.getLeftBorderColor() != null) {
writeCellStyle.setLeftBorderColor(styleProperty.getLeftBorderColor()); writeCellStyle.setLeftBorderColor(styleProperty.getLeftBorderColor());
} }
if (styleProperty.getRightBorderColor() >= 0) { if (styleProperty.getRightBorderColor() != null) {
writeCellStyle.setRightBorderColor(styleProperty.getRightBorderColor()); writeCellStyle.setRightBorderColor(styleProperty.getRightBorderColor());
} }
if (styleProperty.getTopBorderColor() >= 0) { if (styleProperty.getTopBorderColor() != null) {
writeCellStyle.setTopBorderColor(styleProperty.getTopBorderColor()); writeCellStyle.setTopBorderColor(styleProperty.getTopBorderColor());
} }
if (styleProperty.getBottomBorderColor() >= 0) { if (styleProperty.getBottomBorderColor() != null) {
writeCellStyle.setBottomBorderColor(styleProperty.getBottomBorderColor()); writeCellStyle.setBottomBorderColor(styleProperty.getBottomBorderColor());
} }
writeCellStyle.setFillPatternType(styleProperty.getFillPatternType()); if (styleProperty.getFillPatternType() != null) {
if (styleProperty.getFillBackgroundColor() >= 0) { writeCellStyle.setFillPatternType(styleProperty.getFillPatternType());
}
if (styleProperty.getFillBackgroundColor() != null) {
writeCellStyle.setFillBackgroundColor(styleProperty.getFillBackgroundColor()); writeCellStyle.setFillBackgroundColor(styleProperty.getFillBackgroundColor());
} }
if (styleProperty.getFillForegroundColor() >= 0) { if (styleProperty.getFillForegroundColor() != null) {
writeCellStyle.setFillForegroundColor(styleProperty.getFillForegroundColor()); writeCellStyle.setFillForegroundColor(styleProperty.getFillForegroundColor());
} }
writeCellStyle.setShrinkToFit(styleProperty.getShrinkToFit()); if (styleProperty.getShrinkToFit() != null) {
writeCellStyle.setShrinkToFit(styleProperty.getShrinkToFit());
}
} }
if (fontProperty != null) { if (fontProperty != null) {
WriteFont writeFont = new WriteFont(); if (writeCellStyle.getWriteFont() == null) {
writeCellStyle.setWriteFont(writeFont); writeCellStyle.setWriteFont(new WriteFont());
if (!StringUtils.isEmpty(fontProperty.getFontName())) { }
WriteFont writeFont = writeCellStyle.getWriteFont();
if (StringUtils.isNotBlank(fontProperty.getFontName())) {
writeFont.setFontName(fontProperty.getFontName()); writeFont.setFontName(fontProperty.getFontName());
} }
writeFont.setFontHeightInPoints(fontProperty.getFontHeightInPoints()); if (fontProperty.getFontHeightInPoints() != null) {
writeFont.setItalic(fontProperty.getItalic()); writeFont.setFontHeightInPoints(fontProperty.getFontHeightInPoints());
writeFont.setStrikeout(fontProperty.getStrikeout()); }
if (fontProperty.getColor() >= 0) { if (fontProperty.getItalic() != null) {
writeFont.setItalic(fontProperty.getItalic());
}
if (fontProperty.getStrikeout() != null) {
writeFont.setStrikeout(fontProperty.getStrikeout());
}
if (fontProperty.getColor() != null) {
writeFont.setColor(fontProperty.getColor()); writeFont.setColor(fontProperty.getColor());
} }
if (fontProperty.getTypeOffset() >= 0) { if (fontProperty.getTypeOffset() != null) {
writeFont.setTypeOffset(fontProperty.getTypeOffset()); writeFont.setTypeOffset(fontProperty.getTypeOffset());
} }
if (fontProperty.getUnderline() >= 0) { if (fontProperty.getUnderline() != null) {
writeFont.setUnderline(fontProperty.getUnderline()); writeFont.setUnderline(fontProperty.getUnderline());
} }
if (fontProperty.getCharset() >= 0) { if (fontProperty.getCharset() != null) {
writeFont.setCharset(fontProperty.getCharset()); writeFont.setCharset(fontProperty.getCharset());
} }
writeFont.setBold(fontProperty.getBold()); if (fontProperty.getBold() != null) {
writeFont.setBold(fontProperty.getBold());
}
} }
return writeCellStyle; return writeCellStyle;
} }
} }

41
src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java

@ -1,5 +1,7 @@
package com.alibaba.excel.write.metadata.style; package com.alibaba.excel.write.metadata.style;
import com.alibaba.excel.util.StringUtils;
import lombok.Data; import lombok.Data;
import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFPalette;
@ -70,4 +72,43 @@ public class WriteFont {
* Bold * Bold
*/ */
private Boolean bold; private Boolean bold;
/**
* The source is not empty merge the data to the target.
*
* @param source source
* @param target target
*/
public static void merge(WriteFont source, WriteFont target) {
if (source == null || target == null) {
return;
}
if (StringUtils.isNotBlank(source.getFontName())) {
target.setFontName(source.getFontName());
}
if (source.getFontHeightInPoints() != null) {
target.setFontHeightInPoints(source.getFontHeightInPoints());
}
if (source.getItalic() != null) {
target.setItalic(source.getItalic());
}
if (source.getStrikeout() != null) {
target.setStrikeout(source.getStrikeout());
}
if (source.getColor() != null) {
target.setColor(source.getColor());
}
if (source.getTypeOffset() != null) {
target.setTypeOffset(source.getTypeOffset());
}
if (source.getUnderline() != null) {
target.setUnderline(source.getUnderline());
}
if (source.getCharset() != null) {
target.setCharset(source.getCharset());
}
if (source.getBold() != null) {
target.setBold(source.getBold());
}
}
} }

15
src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java

@ -1,14 +1,10 @@
package com.alibaba.excel.write.style; package com.alibaba.excel.write.style;
import java.util.List;
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import org.apache.commons.collections4.CollectionUtils;
/** /**
* Use the same style for the column * Use the same style for the column
* *
@ -21,8 +17,8 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
if (stopProcessing(context)) { if (stopProcessing(context)) {
return; return;
} }
WriteCellData<?> cellData = context.getCellDataList().get(0); WriteCellData<?> cellData = context.getFirstCellData();
cellData.setWriteCellStyle(headCellStyle(context.getHeadData())); WriteCellStyle.merge(headCellStyle(context.getHeadData()), cellData.getOrCreateStyle());
} }
@Override @Override
@ -30,8 +26,8 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
if (stopProcessing(context)) { if (stopProcessing(context)) {
return; return;
} }
WriteCellData<?> cellData = context.getCellDataList().get(0); WriteCellData<?> cellData = context.getFirstCellData();
cellData.setWriteCellStyle(contentCellStyle(context)); WriteCellStyle.merge(contentCellStyle(context), cellData.getOrCreateStyle());
} }
/** /**
@ -65,8 +61,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
} }
protected boolean stopProcessing(CellWriteHandlerContext context) { protected boolean stopProcessing(CellWriteHandlerContext context) {
List<WriteCellData<?>> cellDataList = context.getCellDataList(); if (context.getFirstCellData() == null) {
if (CollectionUtils.isEmpty(cellDataList) || cellDataList.size() > 1) {
return true; return true;
} }
return context.getHeadData() == null; return context.getHeadData() == null;

46
src/main/java/com/alibaba/excel/write/style/DefaultStyle.java

@ -0,0 +1,46 @@
package com.alibaba.excel.write.style;
import com.alibaba.excel.constant.OrderConstant;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* The default styles
*
* @author Jiaju Zhuang
*/
public class DefaultStyle extends HorizontalCellStyleStrategy {
@Override
public int order() {
return OrderConstant.DEFINE_STYLE - 1;
}
public DefaultStyle() {
super();
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setWrapped(true);
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headWriteCellStyle.setLocked(true);
headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
headWriteCellStyle.setBorderTop(BorderStyle.THIN);
headWriteCellStyle.setBorderBottom(BorderStyle.THIN);
headWriteCellStyle.setBorderLeft(BorderStyle.THIN);
headWriteCellStyle.setBorderRight(BorderStyle.THIN);
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontName("宋体");
headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont);
setHeadWriteCellStyle(headWriteCellStyle);
}
}

21
src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java

@ -7,6 +7,7 @@ import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
/** /**
@ -14,11 +15,15 @@ import org.apache.commons.collections4.CollectionUtils;
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Data
public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
private WriteCellStyle headWriteCellStyle; private WriteCellStyle headWriteCellStyle;
private List<WriteCellStyle> contentWriteCellStyleList; private List<WriteCellStyle> contentWriteCellStyleList;
public HorizontalCellStyleStrategy() {
}
public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle,
List<WriteCellStyle> contentWriteCellStyleList) { List<WriteCellStyle> contentWriteCellStyleList) {
this.headWriteCellStyle = headWriteCellStyle; this.headWriteCellStyle = headWriteCellStyle;
@ -37,8 +42,8 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
if (stopProcessing(context) || headWriteCellStyle == null) { if (stopProcessing(context) || headWriteCellStyle == null) {
return; return;
} }
WriteCellData<?> cellData = context.getCellDataList().get(0); WriteCellData<?> cellData = context.getFirstCellData();
cellData.setWriteCellStyle(headWriteCellStyle); WriteCellStyle.merge(headWriteCellStyle, cellData.getOrCreateStyle());
} }
@Override @Override
@ -46,18 +51,18 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy {
if (stopProcessing(context) || CollectionUtils.isEmpty(contentWriteCellStyleList)) { if (stopProcessing(context) || CollectionUtils.isEmpty(contentWriteCellStyleList)) {
return; return;
} }
WriteCellData<?> cellData = context.getCellDataList().get(0); WriteCellData<?> cellData = context.getFirstCellData();
if (context.getRelativeRowIndex() == null || context.getRelativeRowIndex() <= 0) { if (context.getRelativeRowIndex() == null || context.getRelativeRowIndex() <= 0) {
cellData.setWriteCellStyle(contentWriteCellStyleList.get(0)); WriteCellStyle.merge(contentWriteCellStyleList.get(0), cellData.getOrCreateStyle());
} else { } else {
cellData.setWriteCellStyle( WriteCellStyle.merge(
contentWriteCellStyleList.get(context.getRelativeRowIndex() % contentWriteCellStyleList.size())); contentWriteCellStyleList.get(context.getRelativeRowIndex() % contentWriteCellStyleList.size()),
cellData.getOrCreateStyle());
} }
} }
protected boolean stopProcessing(CellWriteHandlerContext context) { protected boolean stopProcessing(CellWriteHandlerContext context) {
List<WriteCellData<?>> cellDataList = context.getCellDataList(); return context.getFirstCellData() == null;
return CollectionUtils.isEmpty(cellDataList) || cellDataList.size() > 1;
} }
} }

19
src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java

@ -1,29 +1,28 @@
package com.alibaba.easyexcel.test.demo.write; package com.alibaba.easyexcel.test.demo.write;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import com.alibaba.excel.write.handler.AbstractRowWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
/** /**
* 自定义拦截器.新增注释,第一行头加批注 * 自定义拦截器.新增注释,第一行头加批注
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Slf4j
public class CommentWriteHandler implements RowWriteHandler { public class CommentWriteHandler implements RowWriteHandler {
@Override @Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, public void afterRowDispose(RowWriteHandlerContext context) {
Integer relativeRowIndex, Boolean isHead) { if (BooleanUtils.isTrue(context.getHead())) {
if (isHead) { Sheet sheet = context.getWriteSheetHolder().getSheet();
Sheet sheet = writeSheetHolder.getSheet();
Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch(); Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
// 在第一行 第二列创建一个批注 // 在第一行 第二列创建一个批注
Comment comment = Comment comment =

24
src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java

@ -1,36 +1,30 @@
package com.alibaba.easyexcel.test.demo.write; package com.alibaba.easyexcel.test.demo.write;
import java.util.List; import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Hyperlink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* 自定义拦截器对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel * 自定义拦截器对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Slf4j
public class CustomCellWriteHandler implements CellWriteHandler { public class CustomCellWriteHandler implements CellWriteHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class);
@Override @Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, public void afterCellDispose(CellWriteHandlerContext context) {
List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { Cell cell = context.getCell();
// 这里可以对cell进行任何操作 // 这里可以对cell进行任何操作
LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex()); log.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex());
if (isHead && cell.getColumnIndex() == 0) { if (BooleanUtils.isTrue(context.getHead()) && cell.getColumnIndex() == 0) {
CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper(); CreationHelper createHelper = context.getWriteSheetHolder().getSheet().getWorkbook().getCreationHelper();
Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL); Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
hyperlink.setAddress("https://github.com/alibaba/easyexcel"); hyperlink.setAddress("https://github.com/alibaba/easyexcel");
cell.setHyperlink(hyperlink); cell.setHyperlink(hyperlink);

26
src/test/java/com/alibaba/easyexcel/test/demo/write/CustomSheetWriteHandler.java

@ -1,39 +1,31 @@
package com.alibaba.easyexcel.test.demo.write; package com.alibaba.easyexcel.test.demo.write;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint; import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper; import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/** /**
* 自定义拦截器.对第一列第一行和第二行的数据新增下拉框显示 测试1 测试2 * 自定义拦截器.对第一列第一行和第二行的数据新增下拉框显示 测试1 测试2
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Slf4j
public class CustomSheetWriteHandler implements SheetWriteHandler { public class CustomSheetWriteHandler implements SheetWriteHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomSheetWriteHandler.class);
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override @Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { public void afterSheetCreate(SheetWriteHandlerContext context) {
LOGGER.info("第{}个Sheet写入成功。", writeSheetHolder.getSheetNo()); log.info("第{}个Sheet写入成功。", context.getWriteSheetHolder().getSheetNo());
// 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行 // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0); CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"}); DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList); DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
writeSheetHolder.getSheet().addValidationData(dataValidation); context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
} }
} }

11
src/test/java/com/alibaba/easyexcel/test/demo/write/DemoStyleData.java

@ -2,13 +2,12 @@ package com.alibaba.easyexcel.test.demo.write;
import java.util.Date; import java.util.Date;
import org.apache.poi.ss.usermodel.FillPatternType;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ContentFontStyle; import com.alibaba.excel.annotation.write.style.ContentFontStyle;
import com.alibaba.excel.annotation.write.style.ContentStyle; import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle; import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadStyle; import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import lombok.Data; import lombok.Data;
@ -19,20 +18,20 @@ import lombok.Data;
**/ **/
@Data @Data
// 头背景设置成红色 IndexedColors.RED.getIndex() // 头背景设置成红色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 10) @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)
// 头字体设置成20 // 头字体设置成20
@HeadFontStyle(fontHeightInPoints = 20) @HeadFontStyle(fontHeightInPoints = 20)
// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex() // 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 17) @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)
// 内容字体设置成20 // 内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 20) @ContentFontStyle(fontHeightInPoints = 20)
public class DemoStyleData { public class DemoStyleData {
// 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex() // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14) @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)
// 字符串的头字体设置成20 // 字符串的头字体设置成20
@HeadFontStyle(fontHeightInPoints = 30) @HeadFontStyle(fontHeightInPoints = 30)
// 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex() // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
@ContentStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 40) @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
// 字符串的内容字体设置成20 // 字符串的内容字体设置成20
@ContentFontStyle(fontHeightInPoints = 30) @ContentFontStyle(fontHeightInPoints = 30)
@ExcelProperty("字符串标题") @ExcelProperty("字符串标题")

96
src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

@ -27,7 +27,10 @@ import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.ImageData.ImageType; import com.alibaba.excel.metadata.data.ImageData.ImageType;
import com.alibaba.excel.metadata.data.RichTextStringData; import com.alibaba.excel.metadata.data.RichTextStringData;
import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
@ -36,8 +39,11 @@ import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -110,7 +116,7 @@ public class WriteTest {
// 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。 // 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。
// 根据用户传入字段 假设我们要忽略 date // 根据用户传入字段 假设我们要忽略 date
Set<String> excludeColumnFiledNames = new HashSet<String>(); Set<String> excludeColumnFiledNames = new HashSet<>();
excludeColumnFiledNames.add("date"); excludeColumnFiledNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板") EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
@ -118,7 +124,7 @@ public class WriteTest {
fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
// 根据用户传入字段 假设我们只要导出 date // 根据用户传入字段 假设我们只要导出 date
Set<String> includeColumnFiledNames = new HashSet<String>(); Set<String> includeColumnFiledNames = new HashSet<>();
includeColumnFiledNames.add("date"); includeColumnFiledNames.add("date");
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板") EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
@ -337,7 +343,7 @@ public class WriteTest {
* 2. 直接写即可 * 2. 直接写即可
*/ */
@Test @Test
public void writeCellDataWrite() throws Exception { public void writeCellDataWrite() {
String fileName = TestFileUtil.getPath() + "writeCellDataWrite" + System.currentTimeMillis() + ".xlsx"; String fileName = TestFileUtil.getPath() + "writeCellDataWrite" + System.currentTimeMillis() + ".xlsx";
WriteCellDemoData writeCellDemoData = new WriteCellDemoData(); WriteCellDemoData writeCellDemoData = new WriteCellDemoData();
@ -446,6 +452,9 @@ public class WriteTest {
*/ */
@Test @Test
public void handlerStyleWrite() { public void handlerStyleWrite() {
// 方法1 使用已有的策略 推荐
// HorizontalCellStyleStrategy 每一行的样式都一样 或者隔行一样
// AbstractVerticalCellStyleStrategy 每一列的样式都一样 需要自己回调每一页
String fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx"; String fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
// 头的策略 // 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle(); WriteCellStyle headWriteCellStyle = new WriteCellStyle();
@ -469,7 +478,70 @@ public class WriteTest {
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板") EasyExcel.write(fileName, DemoData.class)
.registerWriteHandler(horizontalCellStyleStrategy)
.sheet("模板")
.doWrite(data());
// 方法2: 使用easyexcel的方式完全自己写 不太推荐 尽量使用已有策略
// @since 3.0.0-beta2
fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
EasyExcel.write(fileName, DemoData.class)
.registerWriteHandler(new CellWriteHandler() {
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
// 当前事件会在 数据设置到poi的cell里面才会回调
// 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
if (BooleanUtils.isNotTrue(context.getHead())) {
// 第一个单元格
// 只要不是头 一定会有数据 当然fill的情况 可能要context.getCellDataList() ,这个需要看模板,因为一个单元格会有多个 WriteCellData
WriteCellData<?> cellData = context.getFirstCellData();
// 这里需要去cellData 获取样式
// 很重要的一个原因是 WriteCellStyle 和 dataFormatData绑定的 简单的说 比如你加了 DateTimeFormat
// ,已经将writeCellStyle里面的dataFormatData 改了 如果你自己new了一个WriteCellStyle,可能注解的样式就失效了
// 然后 getOrCreateStyle 用于返回一个样式,如果为空,则创建一个后返回
WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 这样样式就设置好了 后面有个FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到 cell里面去 所以可以不用管了
}
}
}).sheet("模板")
.doWrite(data());
// 方法3: 使用poi的样式完全自己写 不推荐
// @since 3.0.0-beta2
// 坑1:style里面有dataformat 用来格式化数据的 所以自己设置可能导致格式化注解不生效
// 坑2:不要一直去创建style 记得缓存起来 最多创建6W个就挂了
fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
EasyExcel.write(fileName, DemoData.class)
.registerWriteHandler(new CellWriteHandler() {
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
// 当前事件会在 数据设置到poi的cell里面才会回调
// 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
if (BooleanUtils.isNotTrue(context.getHead())) {
Cell cell = context.getCell();
// 拿到poi的workbook
Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
// 不同单元格尽量传同一个 cellStyle
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(cellStyle);
// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确
// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
// cell里面去 会导致自己设置的不一样
context.getFirstCellData().setWriteCellStyle(null);
}
}
}).sheet("模板")
.doWrite(data()); .doWrite(data());
} }
@ -642,7 +714,7 @@ public class WriteTest {
} }
private List<LongestMatchColumnWidthData> dataLong() { private List<LongestMatchColumnWidthData> dataLong() {
List<LongestMatchColumnWidthData> list = new ArrayList<LongestMatchColumnWidthData>(); List<LongestMatchColumnWidthData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
LongestMatchColumnWidthData data = new LongestMatchColumnWidthData(); LongestMatchColumnWidthData data = new LongestMatchColumnWidthData();
data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i); data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i);
@ -654,12 +726,12 @@ public class WriteTest {
} }
private List<List<String>> variableTitleHead() { private List<List<String>> variableTitleHead() {
List<List<String>> list = new ArrayList<List<String>>(); List<List<String>> list = new ArrayList<>();
List<String> head0 = new ArrayList<String>(); List<String> head0 = new ArrayList<>();
head0.add("string" + System.currentTimeMillis()); head0.add("string" + System.currentTimeMillis());
List<String> head1 = new ArrayList<String>(); List<String> head1 = new ArrayList<>();
head1.add("number" + System.currentTimeMillis()); head1.add("number" + System.currentTimeMillis());
List<String> head2 = new ArrayList<String>(); List<String> head2 = new ArrayList<>();
head2.add("date" + System.currentTimeMillis()); head2.add("date" + System.currentTimeMillis());
list.add(head0); list.add(head0);
list.add(head1); list.add(head1);
@ -682,9 +754,9 @@ public class WriteTest {
} }
private List<List<Object>> dataList() { private List<List<Object>> dataList() {
List<List<Object>> list = new ArrayList<List<Object>>(); List<List<Object>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
List<Object> data = new ArrayList<Object>(); List<Object> data = new ArrayList<>();
data.add("字符串" + i); data.add("字符串" + i);
data.add(new Date()); data.add(new Date());
data.add(0.56); data.add(0.56);
@ -694,7 +766,7 @@ public class WriteTest {
} }
private List<DemoData> data() { private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>(); List<DemoData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
DemoData data = new DemoData(); DemoData data = new DemoData();
data.setString("字符串" + i); data.setString("字符串" + i);

190
src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java

@ -1,22 +1,21 @@
package com.alibaba.easyexcel.test.temp; package com.alibaba.easyexcel.test.temp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.demo.write.IndexData;
import com.alibaba.easyexcel.test.temp.data.DataType;
import com.alibaba.easyexcel.test.temp.data.HeadType;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.poi.ss.usermodel.Cell;
import lombok.Data; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -33,76 +32,102 @@ public class WriteV33Test {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteV33Test.class); private static final Logger LOGGER = LoggerFactory.getLogger(WriteV33Test.class);
@Test @Test
public void test() throws Exception { public void handlerStyleWrite() {
// 方法2 如果写到不同的sheet 同一个对象 // 方法1 使用已有的策略 推荐
String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; // HorizontalCellStyleStrategy 每一行的样式都一样 或者隔行一样
OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(2, 2, 0, 1); // AbstractVerticalCellStyleStrategy 每一列的样式都一样 需要自己回调每一页
String fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 指定文件 //// 头的策略
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler( //WriteCellStyle headWriteCellStyle = new WriteCellStyle();
onceAbsoluteMergeStrategy).build(); //// 背景设置为红色
WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "模板1").build(); //headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "模板2").build(); //WriteFont headWriteFont = new WriteFont();
WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "模板3").build(); //headWriteFont.setFontHeightInPoints((short)20);
excelWriter.write(data(2), writeSheet2); //headWriteCellStyle.setWriteFont(headWriteFont);
excelWriter.write(data(3), writeSheet3); //// 内容的策略
excelWriter.write(data(1), writeSheet1); //WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
excelWriter.write(data(3), writeSheet3); //// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
excelWriter.write(data(1), writeSheet1); //contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
/// 千万别忘记finish 会帮忙关闭流 //// 背景绿色
excelWriter.finish(); //contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
//WriteFont contentWriteFont = new WriteFont();
//// 字体大小
//contentWriteFont.setFontHeightInPoints((short)20);
//contentWriteCellStyle.setWriteFont(contentWriteFont);
//// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
//HorizontalCellStyleStrategy horizontalCellStyleStrategy =
// new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
//
//// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
//EasyExcel.write(fileName, DemoData.class)
// .registerWriteHandler(horizontalCellStyleStrategy)
// .sheet("模板")
// .doWrite(data());
//
// 方法2: 使用easyexcel的方式完全自己写 不太推荐 尽量使用已有策略
//fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
//EasyExcel.write(fileName, DemoData.class)
// .registerWriteHandler(new CellWriteHandler() {
// @Override
// public void afterCellDispose(CellWriteHandlerContext context) {
// // 当前事件会在 数据设置到poi的cell里面才会回调
// // 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
// if (BooleanUtils.isNotTrue(context.getHead())) {
// // 第一个单元格
// // 只要不是头 一定会有数据 当然fill的情况 可能要context.getCellDataList() ,这个需要看模板,因为一个单元格会有多个 WriteCellData
// WriteCellData<?> cellData = context.getFirstCellData();
// // 这里需要去cellData 获取样式
// // 很重要的一个原因是 WriteCellStyle 和 dataFormatData绑定的 简单的说 比如你加了 DateTimeFormat
// // ,已经将writeCellStyle里面的dataFormatData 改了 如果你自己new了一个WriteCellStyle,可能注解的样式就失效了
// // 然后 getOrCreateStyle 用于返回一个样式,如果为空,则创建一个后返回
// WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
// writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
// // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
// writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
//
// // 这样样式就设置好了 后面有个FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到 cell里面去 所以可以不用管了
// }
// }
// }).sheet("模板")
// .doWrite(data());
// 方法3: 使用poi的样式完全自己写 不推荐
// 坑1:style里面有dataformat 用来格式化数据的 所以自己设置可能导致格式化注解不生效
// 坑2:不要一直去创建style 记得缓存起来 最多创建6W个就挂了
fileName = TestFileUtil.getPath() + "handlerStyleWrite" + System.currentTimeMillis() + ".xlsx";
EasyExcel.write(fileName, DemoData.class)
.registerWriteHandler(new CellWriteHandler() {
@Override
public void afterCellDispose(CellWriteHandlerContext context) {
// 当前事件会在 数据设置到poi的cell里面才会回调
// 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not true
if (BooleanUtils.isNotTrue(context.getHead())) {
Cell cell = context.getCell();
// 拿到poi的workbook
Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式
// 不同单元格尽量传同一个 cellStyle
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cell.setCellStyle(cellStyle);
// 由于这里没有指定datafrmat 所以格式化出来的数据需要
// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到
// cell里面去 会导致自己设置的不一样
context.getFirstCellData().setWriteCellStyle(null);
}
}
}).sheet("模板")
.doWrite(data());
} }
private List<DemoData> data(int no) { private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>(); List<DemoData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
DemoData data = new DemoData(); DemoData data = new DemoData();
data.setString("字符串" + no + "---" + i);
list.add(data);
}
return list;
}
@Test
public void test33() throws Exception {
List<DataType> data = getData();
String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = null;
excelWriter = EasyExcel.write(fileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet(1, "test")
.head(HeadType.class)
.build();
excelWriter.write(data, writeSheet);
excelWriter.finish();
}
private List<DataType> getData() {
DataType vo = new DataType();
vo.setId(738);
vo.setFirstRemark("1222");
vo.setSecRemark("22222");
return Collections.singletonList(vo);
}
@Test
public void indexWrite() {
String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx";
Man man = new Man();
man.setAddr("武汉");
man.setName("张三");
ExcelWriter excelWriter = EasyExcel.write(fileName, Humen.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("test").build();
excelWriter.write(Collections.singletonList(man), writeSheet);
// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
private List<IndexData> indexData() {
List<IndexData> list = new ArrayList<IndexData>();
for (int i = 0; i < 10; i++) {
IndexData data = new IndexData();
data.setString("字符串" + i); data.setString("字符串" + i);
data.setDate(new Date()); data.setDate(new Date());
data.setDoubleData(0.56); data.setDoubleData(0.56);
@ -111,17 +136,4 @@ public class WriteV33Test {
return list; return list;
} }
@Data
static class Humen{
@ExcelProperty("名字")
private String name;
}
@Data
static
class Man extends Humen{
@ExcelProperty("地址")
private String addr;
}
} }

5
src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java

@ -2,18 +2,17 @@ package com.alibaba.easyexcel.test.temp.simple;
import java.util.Date; import java.util.Date;
import org.apache.poi.ss.usermodel.FillPatternType;
import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.HeadStyle; import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import lombok.Data; import lombok.Data;
@Data @Data
public class DemoData1 { public class DemoData1 {
@ExcelProperty("字符串标题") @ExcelProperty("字符串标题")
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 42) @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 42)
private String string; private String string;
@ExcelProperty("日期标题") @ExcelProperty("日期标题")
private Date date; private Date date;

5
src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java

@ -2,18 +2,17 @@ package com.alibaba.easyexcel.test.temp.simple;
import java.util.Date; import java.util.Date;
import org.apache.poi.ss.usermodel.FillPatternType;
import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.HeadStyle; import com.alibaba.excel.annotation.write.style.HeadStyle;
import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
import lombok.Data; import lombok.Data;
@Data @Data
public class DemoData2 { public class DemoData2 {
@ExcelProperty("字符串标题") @ExcelProperty("字符串标题")
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 42) @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 42)
private String string; private String string;
@ExcelProperty("日期标题") @ExcelProperty("日期标题")
private Date date; private Date date;

5
update.md

@ -1,3 +1,7 @@
# 3.0.0-beta2
* 优化写入样式的
# 3.0.0-beta1 # 3.0.0-beta1
* 升级jdk8 不再支持jdk6 jdk7 * 升级jdk8 不再支持jdk6 jdk7
@ -33,6 +37,7 @@
* 新增部分jdk8特性 * 新增部分jdk8特性
# 2.2.11 # 2.2.11
* 修复有些xlsx解析失败的bug [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595) * 修复有些xlsx解析失败的bug [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595)
# 2.2.10 # 2.2.10

Loading…
Cancel
Save