Browse Source

* 提升合并策略效率

* 兼容部分比较特殊的excel
pull/1159/head
Jiaju Zhuang 5 years ago
parent
commit
71b9c53b6d
  1. 2
      src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java
  2. 2
      src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java
  3. 9
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java
  4. 5
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java
  5. 2
      src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
  6. 41
      src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java
  7. 89
      src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java
  8. 31
      src/main/java/com/alibaba/excel/annotation/write/style/ContentLoopMerge.java
  9. 159
      src/main/java/com/alibaba/excel/annotation/write/style/ContentStyle.java
  10. 89
      src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java
  11. 159
      src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java
  12. 45
      src/main/java/com/alibaba/excel/annotation/write/style/OnceAbsoluteMerge.java
  13. 43
      src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java
  14. 14
      src/main/java/com/alibaba/excel/metadata/CellExtra.java
  15. 30
      src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java
  16. 31
      src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java
  17. 21
      src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java
  18. 26
      src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java
  19. 52
      src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java
  20. 31
      src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java
  21. 50
      src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
  22. 4
      update.md

2
src/main/java/com/alibaba/excel/analysis/v03/handlers/HyperlinkRecordHandler.java

@ -23,7 +23,7 @@ public class HyperlinkRecordHandler extends AbstractXlsRecordHandler implements
public void processRecord(XlsReadContext xlsReadContext, Record record) {
HyperlinkRecord hr = (HyperlinkRecord)record;
CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, hr.getAddress(), hr.getFirstRow(),
hr.getFirstColumn(), hr.getLastRow(), hr.getLastColumn());
hr.getLastRow(), hr.getFirstColumn(), hr.getLastColumn());
xlsReadContext.xlsReadSheetHolder().setCellExtra(cellExtra);
xlsReadContext.analysisEventProcessor().extra(xlsReadContext);
}

2
src/main/java/com/alibaba/excel/analysis/v03/handlers/MergeCellsRecordHandler.java

@ -27,7 +27,7 @@ public class MergeCellsRecordHandler extends AbstractXlsRecordHandler implements
for (int i = 0; i < mcr.getNumAreas(); i++) {
CellRangeAddress cellRangeAddress = mcr.getAreaAt(i);
CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.MERGE, null, cellRangeAddress.getFirstRow(),
cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastRow(), cellRangeAddress.getLastColumn());
cellRangeAddress.getLastRow(), cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn());
xlsReadContext.xlsReadSheetHolder().setCellExtra(cellExtra);
xlsReadContext.analysisEventProcessor().extra(xlsReadContext);
}

9
src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java

@ -1,8 +1,5 @@
package com.alibaba.excel.analysis.v07.handlers;
import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_DATA_FORMAT_TAG;
import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TYPE_TAG;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.xml.sax.Attributes;
@ -24,7 +21,7 @@ public class CellTagHandler extends AbstractXlsxTagHandler {
@Override
public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.POSITION)));
xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R)));
// t="s" ,it's means String
// t="str" ,it's means String,but does not need to be read in the 'sharedStrings.xml'
@ -33,12 +30,12 @@ public class CellTagHandler extends AbstractXlsxTagHandler {
// t="e" ,it's means Error
// t="n" ,it's means Number
// t is null ,it's means Empty or Number
CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(CELL_VALUE_TYPE_TAG));
CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_T));
xlsxReadSheetHolder.setTempCellData(new CellData(type));
xlsxReadSheetHolder.setTempData(new StringBuilder());
// Put in data transformation information
String dateFormatIndex = attributes.getValue(CELL_DATA_FORMAT_TAG);
String dateFormatIndex = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_S);
if (dateFormatIndex != null) {
int dateFormatIndexInteger = Integer.parseInt(dateFormatIndex);
XSSFCellStyle xssfCellStyle =

5
src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java

@ -1,9 +1,8 @@
package com.alibaba.excel.analysis.v07.handlers;
import static com.alibaba.excel.constant.ExcelXmlConstants.DIMENSION_REF;
import org.xml.sax.Attributes;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
/**
@ -15,7 +14,7 @@ public class CountTagHandler extends AbstractXlsxTagHandler {
@Override
public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
String d = attributes.getValue(DIMENSION_REF);
String d = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_REF);
String totalStr = d.substring(d.indexOf(":") + 1, d.length());
String c = totalStr.toUpperCase().replaceAll("[A-Z]", "");
xlsxReadContext.readSheetHolder().setApproximateTotalRowNumber(Integer.parseInt(c));

2
src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java

@ -21,7 +21,7 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
@Override
public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
xlsxReadContext.readRowHolder(
new ReadRowHolder(PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.POSITION)),
new ReadRowHolder(PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R)),
RowTypeEnum.DATA, xlsxReadContext.readSheetHolder().getGlobalConfiguration(), null));
}

41
src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java

@ -24,18 +24,33 @@ import com.alibaba.excel.context.xlsx.XlsxReadContext;
*/
public class XlsxRowHandler extends DefaultHandler {
private XlsxReadContext xlsxReadContext;
private static final Map<String, XlsxTagHandler> XLSX_CELL_HANDLER_MAP = new HashMap<String, XlsxTagHandler>(16);
private static final Map<String, XlsxTagHandler> XLSX_CELL_HANDLER_MAP = new HashMap<String, XlsxTagHandler>(32);
static {
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, new CellFormulaTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG,
new CellInlineStringValueTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, new CellTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, new CellValueTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION, new CountTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, new HyperlinkTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, new MergeCellTagHandler());
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, new RowTagHandler());
CellFormulaTagHandler cellFormulaTagHandler = new CellFormulaTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, cellFormulaTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_FORMULA_TAG, cellFormulaTagHandler);
CellInlineStringValueTagHandler cellInlineStringValueTagHandler = new CellInlineStringValueTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);
CellTagHandler cellTagHandler = new CellTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, cellTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_TAG, cellTagHandler);
CellValueTagHandler cellValueTagHandler = new CellValueTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, cellValueTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_VALUE_TAG, cellValueTagHandler);
CountTagHandler countTagHandler = new CountTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION_TAG, countTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_DIMENSION_TAG, countTagHandler);
HyperlinkTagHandler hyperlinkTagHandler = new HyperlinkTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, hyperlinkTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_HYPERLINK_TAG, hyperlinkTagHandler);
MergeCellTagHandler mergeCellTagHandler = new MergeCellTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, mergeCellTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_MERGE_CELL_TAG, mergeCellTagHandler);
RowTagHandler rowTagHandler = new RowTagHandler();
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, rowTagHandler);
XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_ROW_TAG, rowTagHandler);
}
public XlsxRowHandler(XlsxReadContext xlsxReadContext) {
@ -45,7 +60,7 @@ public class XlsxRowHandler extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);
if (handler == null) {
if (handler == null || !handler.support(xlsxReadContext)) {
return;
}
xlsxReadContext.xlsxReadSheetHolder().getTagDeque().push(name);
@ -59,7 +74,7 @@ public class XlsxRowHandler extends DefaultHandler {
return;
}
XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(currentTag);
if (handler == null) {
if (handler == null || !handler.support(xlsxReadContext)) {
return;
}
handler.characters(xlsxReadContext, ch, start, length);
@ -68,7 +83,7 @@ public class XlsxRowHandler extends DefaultHandler {
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
XlsxTagHandler handler = XLSX_CELL_HANDLER_MAP.get(name);
if (handler == null) {
if (handler == null || !handler.support(xlsxReadContext)) {
return;
}
handler.endElement(xlsxReadContext, name);

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

@ -0,0 +1,89 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
/**
* Custom content styles.
*
* @author Jiaju Zhuang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ContentFontStyle {
/**
* The name for the font (i.e. Arial)
*/
String fontName();
/**
* Height in the familiar unit of measure - points
*/
short fontHeightInPoints() default -1;
/**
* Whether to use italics or not
*/
boolean italic() default false;
/**
* Whether to use a strikeout horizontal line through the text or not
*/
boolean strikeout() default false;
/**
* The color for the font
*
* @see Font#COLOR_NORMAL
* @see Font#COLOR_RED
* @see HSSFPalette#getColor(short)
* @see IndexedColors
*/
short color() default -1;
/**
* Set normal,super or subscript.
*
* @see Font#SS_NONE
* @see Font#SS_SUPER
* @see Font#SS_SUB
*/
short typeOffset() default -1;
/**
* set type of text underlining to use
*
* @see Font#U_NONE
* @see Font#U_SINGLE
* @see Font#U_DOUBLE
* @see Font#U_SINGLE_ACCOUNTING
* @see Font#U_DOUBLE_ACCOUNTING
*/
byte underline() default -1;
/**
* Set character-set to use.
*
* @see FontCharset
* @see Font#ANSI_CHARSET
* @see Font#DEFAULT_CHARSET
* @see Font#SYMBOL_CHARSET
*/
int charset() default -1;
/**
* Bold
*/
boolean bold() default false;
}

31
src/main/java/com/alibaba/excel/annotation/write/style/ContentLoopMerge.java

@ -0,0 +1,31 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The regions of the loop merge
*
* @author Jiaju Zhuang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ContentLoopMerge {
/**
* Each row
*
* @return
*/
int eachRow() default -1;
/**
* Extend column
*
* @return
*/
int columnExtend() default 1;
}

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

@ -0,0 +1,159 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.BuiltinFormats;
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.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* Custom content styles
*
* @author Jiaju Zhuang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ContentStyle {
/**
* Set the data format (must be a valid format). Built in formats are defined at {@link BuiltinFormats}.
*/
short dataFormat();
/**
* Set the cell's using this style to be hidden
*/
boolean hidden();
/**
* Set the cell's using this style to be locked
*/
boolean locked();
/**
* 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
* {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel
*/
boolean quotePrefix();
/**
* Set the type of horizontal alignment for the cell
*/
HorizontalAlignment horizontalAlignment();
/**
* 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
*
*/
boolean wrapped();
/**
* Set the type of vertical alignment for the cell
*/
VerticalAlignment verticalAlignment();
/**
* Set the degree of rotation for the text in the cell.
*
* Note: HSSF uses values from -90 to 90 degrees, whereas XSSF uses values from 0 to 180 degrees. The
* implementations of this method will map between these two value-ranges accordingly, however the corresponding
* getter is returning values in the range mandated by the current type of Excel file-format that this CellStyle is
* applied to.
*/
short rotation();
/**
* Set the number of spaces to indent the text in the cell
*/
short indent();
/**
* Set the type of border to use for the left border of the cell
*/
BorderStyle borderLeft();
/**
* Set the type of border to use for the right border of the cell
*/
BorderStyle borderRight();
/**
* Set the type of border to use for the top border of the cell
*/
BorderStyle borderTop();
/**
* Set the type of border to use for the bottom border of the cell
*/
BorderStyle borderBottom();
/**
* Set the color to use for the left border
*
* @see IndexedColors
*/
short leftBorderColor();
/**
* Set the color to use for the right border
*
* @see IndexedColors
*
*/
short rightBorderColor();
/**
* Set the color to use for the top border
*
* @see IndexedColors
*
*/
short topBorderColor();
/**
* Set the color to use for the bottom border
*
* @see IndexedColors
*
*/
short bottomBorderColor();
/**
* Setting to one fills the cell with the foreground color... No idea about other values
*
* @see FillPatternType#SOLID_FOREGROUND
*/
FillPatternType fillPatternType();
/**
* Set the background fill color.
*
* @see IndexedColors
*
*/
short fillBackgroundColor();
/**
* Set the foreground fill color <i>Note: Ensure Foreground color is set prior to background color.</i>
*
* @see IndexedColors
*
*/
short fillForegroundColor();
/**
* Controls if the Cell should be auto-sized to shrink to fit if the text is too long
*/
boolean shrinkToFit();
}

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

@ -0,0 +1,89 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
/**
* Custom header styles.
*
* @author Jiaju Zhuang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface HeadFontStyle {
/**
* The name for the font (i.e. Arial)
*/
String fontName();
/**
* Height in the familiar unit of measure - points
*/
short fontHeightInPoints() default -1;
/**
* Whether to use italics or not
*/
boolean italic() default false;
/**
* Whether to use a strikeout horizontal line through the text or not
*/
boolean strikeout() default false;
/**
* The color for the font
*
* @see Font#COLOR_NORMAL
* @see Font#COLOR_RED
* @see HSSFPalette#getColor(short)
* @see IndexedColors
*/
short color() default -1;
/**
* Set normal,super or subscript.
*
* @see Font#SS_NONE
* @see Font#SS_SUPER
* @see Font#SS_SUB
*/
short typeOffset() default -1;
/**
* set type of text underlining to use
*
* @see Font#U_NONE
* @see Font#U_SINGLE
* @see Font#U_DOUBLE
* @see Font#U_SINGLE_ACCOUNTING
* @see Font#U_DOUBLE_ACCOUNTING
*/
byte underline() default -1;
/**
* Set character-set to use.
*
* @see FontCharset
* @see Font#ANSI_CHARSET
* @see Font#DEFAULT_CHARSET
* @see Font#SYMBOL_CHARSET
*/
int charset() default -1;
/**
* Bold
*/
boolean bold() default false;
}

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

@ -0,0 +1,159 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.BuiltinFormats;
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.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* Custom header styles
*
* @author Jiaju Zhuang
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface HeadStyle {
/**
* Set the data format (must be a valid format). Built in formats are defined at {@link BuiltinFormats}.
*/
short dataFormat() default -1;
/**
* Set the cell's using this style to be hidden
*/
boolean hidden() default false;
/**
* Set the cell's using this style to be locked
*/
boolean locked() default false;
/**
* 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
* {@link IgnoredErrorType}) like prefixing the cell value with a ' in Excel
*/
boolean quotePrefix() default false;
/**
* Set the type of horizontal alignment for the cell
*/
HorizontalAlignment horizontalAlignment();
/**
* 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
*
*/
boolean wrapped() default false;
/**
* Set the type of vertical alignment for the cell
*/
VerticalAlignment verticalAlignment();
/**
* Set the degree of rotation for the text in the cell.
*
* Note: HSSF uses values from -90 to 90 degrees, whereas XSSF uses values from 0 to 180 degrees. The
* implementations of this method will map between these two value-ranges accordingly, however the corresponding
* getter is returning values in the range mandated by the current type of Excel file-format that this CellStyle is
* applied to.
*/
short rotation() default -1;
/**
* Set the number of spaces to indent the text in the cell
*/
short indent() default -1;
/**
* Set the type of border to use for the left border of the cell
*/
BorderStyle borderLeft();
/**
* Set the type of border to use for the right border of the cell
*/
BorderStyle borderRight();
/**
* Set the type of border to use for the top border of the cell
*/
BorderStyle borderTop();
/**
* Set the type of border to use for the bottom border of the cell
*/
BorderStyle borderBottom();
/**
* Set the color to use for the left border
*
* @see IndexedColors
*/
short leftBorderColor() default -1;
/**
* Set the color to use for the right border
*
* @see IndexedColors
*
*/
short rightBorderColor() default -1;
/**
* Set the color to use for the top border
*
* @see IndexedColors
*
*/
short topBorderColor() default -1;
/**
* Set the color to use for the bottom border
*
* @see IndexedColors
*
*/
short bottomBorderColor() default -1;
/**
* Setting to one fills the cell with the foreground color... No idea about other values
*
* @see FillPatternType#SOLID_FOREGROUND
*/
FillPatternType fillPatternType();
/**
* Set the background fill color.
*
* @see IndexedColors
*
*/
short fillBackgroundColor() default -1;
/**
* Set the foreground fill color <i>Note: Ensure Foreground color is set prior to background color.</i>
*
* @see IndexedColors
*
*/
short fillForegroundColor() default -1;
/**
* Controls if the Cell should be auto-sized to shrink to fit if the text is too long
*/
boolean shrinkToFit() default false;
}

45
src/main/java/com/alibaba/excel/annotation/write/style/OnceAbsoluteMerge.java

@ -0,0 +1,45 @@
package com.alibaba.excel.annotation.write.style;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Merge the cells once
*
* @author Jiaju Zhuang
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface OnceAbsoluteMerge {
/**
* First row
*
* @return
*/
int firstRowIndex() default -1;
/**
* Last row
*
* @return
*/
int lastRowIndex() default -1;
/**
* First column
*
* @return
*/
int firstColumnIndex() default -1;
/**
* Last row
*
* @return
*/
int lastColumnIndex() default -1;
}

43
src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java

@ -4,37 +4,54 @@ package com.alibaba.excel.constant;
* @author jipengfei
*/
public class ExcelXmlConstants {
public static final String DIMENSION = "dimension";
public static final String DIMENSION_REF = "ref";
public static final String POSITION = "r";
public static final String DIMENSION_TAG = "dimension";
public static final String ROW_TAG = "row";
public static final String CELL_TAG = "c";
public static final String CELL_VALUE_TYPE_TAG = "t";
/**
* Number formatted label
*/
public static final String CELL_DATA_FORMAT_TAG = "s";
public static final String CELL_FORMULA_TAG = "f";
public static final String CELL_VALUE_TAG = "v";
/**
* When the data is "inlineStr" his tag is "t"
*/
public static final String CELL_INLINE_STRING_VALUE_TAG = "t";
public static final String CELL_TAG = "c";
public static final String MERGE_CELL_TAG = "mergeCell";
public static final String HYPERLINK_TAG = "hyperlink";
public static final String X_DIMENSION_TAG = "x:dimension";
public static final String X_ROW_TAG = "x:row";
public static final String X_CELL_FORMULA_TAG = "x:f";
public static final String X_CELL_VALUE_TAG = "x:v";
/**
* Cell range split
* When the data is "inlineStr" his tag is "t"
*/
public static final String CELL_RANGE_SPLIT = ":";
public static final String X_CELL_INLINE_STRING_VALUE_TAG = "x:t";
public static final String X_CELL_TAG = "x:c";
public static final String X_MERGE_CELL_TAG = "x:mergeCell";
public static final String X_HYPERLINK_TAG = "x:hyperlink";
/**
* s attribute
*/
public static final String ATTRIBUTE_S = "s";
/**
* ref attribute
*/
public static final String ATTRIBUTE_REF = "ref";
/**
* r attribute
*/
public static final String ATTRIBUTE_R = "r";
/**
* t attribute
*/
public static final String ATTRIBUTE_T = "t";
/**
* location attribute
*/
public static final String ATTRIBUTE_LOCATION = "location";
/**
* Cell range split
*/
public static final String CELL_RANGE_SPLIT = ":";
}

14
src/main/java/com/alibaba/excel/metadata/CellExtra.java

@ -23,14 +23,14 @@ public class CellExtra extends AbstractCell {
* First row index,if this object is an interval
*/
private Integer firstRowIndex;
/**
* First column index,if this object is an interval
*/
private Integer firstColumnIndex;
/**
* Last row index,if this object is an interval
*/
private Integer lastRowIndex;
/**
* First column index,if this object is an interval
*/
private Integer firstColumnIndex;
/**
* Last column index,if this object is an interval
*/
@ -55,11 +55,11 @@ public class CellExtra extends AbstractCell {
}
public CellExtra(CellExtraTypeEnum type, String text, Integer rowIndex, Integer columnIndex) {
this(type, text, rowIndex, columnIndex, rowIndex, columnIndex);
this(type, text, rowIndex, rowIndex, columnIndex, columnIndex);
}
public CellExtra(CellExtraTypeEnum type, String text, Integer firstRowIndex, Integer firstColumnIndex,
Integer lastRowIndex, Integer lastColumnIndex) {
public CellExtra(CellExtraTypeEnum type, String text, Integer firstRowIndex, Integer lastRowIndex,
Integer firstColumnIndex, Integer lastColumnIndex) {
super();
setRowIndex(firstRowIndex);
setColumnIndex(firstColumnIndex);

30
src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java → src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java

@ -1,23 +1,22 @@
package com.alibaba.excel.write.merge;
package com.alibaba.excel.write.handler;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
/**
* Merge strategy
* Abstract cell write handler
*
* @author Jiaju Zhuang
*/
public abstract class AbstractMergeStrategy implements CellWriteHandler {
**/
public abstract class AbstractCellWriteHandler implements CellWriteHandler {
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
@ -26,24 +25,13 @@ public abstract class AbstractMergeStrategy implements CellWriteHandler {
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {}
Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}
merge(writeSheetHolder.getSheet(), cell, head, relativeRowIndex);
}
/**
* merge
*
* @param sheet
* @param cell
* @param head
* @param relativeRowIndex
*/
protected abstract void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex);
}
}

31
src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java

@ -0,0 +1,31 @@
package com.alibaba.excel.write.handler;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
/**
* Abstract row write handler
*
* @author Jiaju Zhuang
**/
public abstract class AbstractRowWriteHandler implements RowWriteHandler {
@Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
}
}

21
src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java

@ -0,0 +1,21 @@
package com.alibaba.excel.write.handler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/**
* Abstract sheet write handler
*
* @author Jiaju Zhuang
**/
public abstract class AbstractSheetWriteHandler implements SheetWriteHandler {
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
}
}

26
src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java

@ -0,0 +1,26 @@
package com.alibaba.excel.write.handler;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/**
* Abstract workbook write handler
*
* @author Jiaju Zhuang
**/
public abstract class AbstractWorkbookWriteHandler implements WorkbookWriteHandler {
@Override
public void beforeWorkbookCreate() {
}
@Override
public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {
}
@Override
public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
}
}

52
src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java

@ -1,58 +1,64 @@
package com.alibaba.excel.write.merge;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.AbstractRowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
/**
* The regions of the loop merge
*
* @author Jiaju Zhuang
*/
public class LoopMergeStrategy extends AbstractMergeStrategy {
public class LoopMergeStrategy extends AbstractRowWriteHandler {
/**
* Each row
*/
private int eachRow;
private int columnCount;
/**
* Extend column
*/
private int columnExtend;
/**
* The number of the current column
*/
private int columnIndex;
public LoopMergeStrategy(int eachRow, int columnIndex) {
this(eachRow, 1, columnIndex);
}
public LoopMergeStrategy(int eachRow, int columnCount, int columnIndex) {
public LoopMergeStrategy(int eachRow, int columnExtend, int columnIndex) {
if (eachRow < 1) {
throw new IllegalArgumentException("EachRows must be greater than 1");
}
if (columnCount < 1) {
throw new IllegalArgumentException("ColumnCount must be greater than 1");
if (columnExtend < 1) {
throw new IllegalArgumentException("ColumnExtend must be greater than 1");
}
if (columnCount == 1 && eachRow == 1) {
throw new IllegalArgumentException("ColumnCount or eachRows must be greater than 1");
if (columnExtend == 1 && eachRow == 1) {
throw new IllegalArgumentException("ColumnExtend or eachRows must be greater than 1");
}
if (columnIndex < 0) {
throw new IllegalArgumentException("ColumnIndex must be greater than 0");
}
this.eachRow = eachRow;
this.columnCount = columnCount;
this.columnExtend = columnExtend;
this.columnIndex = columnIndex;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (relativeRowIndex == null) {
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}
Integer currentColumnIndex;
if (head != null) {
currentColumnIndex = head.getColumnIndex();
} else {
currentColumnIndex = cell.getColumnIndex();
}
if (currentColumnIndex == columnIndex && relativeRowIndex % eachRow == 0) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(cell.getRowIndex(),
cell.getRowIndex() + eachRow - 1, cell.getColumnIndex(), cell.getColumnIndex() + columnCount - 1);
sheet.addMergedRegionUnsafe(cellRangeAddress);
if (relativeRowIndex % eachRow == 0) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(row.getRowNum(), row.getRowNum() + eachRow - 1,
columnIndex, columnIndex + columnExtend - 1);
writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress);
}
}
}

31
src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java

@ -1,21 +1,32 @@
package com.alibaba.excel.write.merge;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.AbstractSheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
/**
* It only merges once when create cell(firstRowIndex,lastRowIndex)
*
* @author Jiaju Zhuang
*/
public class OnceAbsoluteMergeStrategy extends AbstractMergeStrategy {
public class OnceAbsoluteMergeStrategy extends AbstractSheetWriteHandler {
/**
* First row
*/
private int firstRowIndex;
/**
* Last row
*/
private int lastRowIndex;
/**
* First column
*/
private int firstColumnIndex;
/**
* Last row
*/
private int lastColumnIndex;
public OnceAbsoluteMergeStrategy(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex) {
@ -29,11 +40,9 @@ public class OnceAbsoluteMergeStrategy extends AbstractMergeStrategy {
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (cell.getRowIndex() == firstRowIndex && cell.getColumnIndex() == firstColumnIndex) {
CellRangeAddress cellRangeAddress =
new CellRangeAddress(firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex);
sheet.addMergedRegionUnsafe(cellRangeAddress);
}
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
CellRangeAddress cellRangeAddress =
new CellRangeAddress(firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex);
writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress);
}
}

50
src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java

@ -1,15 +1,24 @@
package com.alibaba.easyexcel.test.temp;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.fastjson.JSON;
/**
@ -32,6 +41,47 @@ public class Lock2Test {
}
}
@Test
public void write() throws Exception {
String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".xlsx";
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// 背景设置为红色
headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)20);
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 背景绿色
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());
}
private List<DemoData> data() {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
@Test
public void testc() throws Exception {
LOGGER.info("reslut:{}", JSON.toJSONString(new CellReference("B3")));

4
update.md

@ -7,6 +7,10 @@
* 新增支持读取批注、超链接、合并单元格
* 如果是`RuntimeException`则不再封装对象
* 新增`CellData`可以获取行列号
* 新增样式注解
* 新增合并单元格注解
* 提升合并策略效率
* 兼容部分比较特殊的excel
# 2.1.4

Loading…
Cancel
Save