Browse Source

Merge pull request #1391 from alibaba/developing

Developing
developing
Jiaju Zhuang 4 years ago committed by GitHub
parent
commit
352604664f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      README.md
  2. 6
      pom.xml
  3. 2
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  4. 13
      src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java
  5. 3
      src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
  6. 5
      src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
  7. 21
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  8. 1
      src/main/java/com/alibaba/excel/metadata/AbstractHolder.java
  9. 15
      src/main/java/com/alibaba/excel/metadata/BasicParameter.java
  10. 14
      src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java
  11. 33
      src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
  12. 81
      src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java
  13. 9
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  14. 13
      src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java
  15. 11
      src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java
  16. 12
      src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java
  17. 13
      src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java
  18. 13
      src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java
  19. 1
      src/main/java/com/alibaba/excel/util/NumberUtils.java
  20. 1
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  21. 64
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  22. 56
      src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java
  23. 4
      src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java
  24. 1
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java
  25. 24
      src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java
  26. 3
      src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java
  27. 13
      src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java
  28. 44
      src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java
  29. 136
      src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java
  30. 16
      src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java
  31. 18
      src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
  32. 5
      src/test/java/com/alibaba/easyexcel/test/temp/LockData.java
  33. 6
      src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java
  34. 108
      src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java
  35. 67
      src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java
  36. 91
      src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java
  37. 1
      src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java
  38. 4
      src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java
  39. 14
      update.md

3
README.md

@ -4,7 +4,8 @@ EasyExcel
[![Maven central](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/easyexcel)
[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
[QQ群: 662022184](//shang.qq.com/wpa/qunwpa?idkey=53d9d821b0833e3c14670f007488a61e300f00ff4f1b81fd950590d90dd80f80)
[QQ1群(已满): 662022184](https://jq.qq.com/?_wv=1027&k=1T21jJxh)
[QQ2群: 1097936804](https://jq.qq.com/?_wv=1027&k=j5zEy6Xl)
[钉钉1群(已满): 21960511](https://qr.dingtalk.com/action/joingroup?code=v1,k1,cchz6k12ci9B08NNqhNRFGXocNVHrZtW0kaOtTKg/Rk=&_dt_no_comment=1&origin=11)
[钉钉2群: 32796397](https://qr.dingtalk.com/action/joingroup?code=v1,k1,jyU9GtEuNU5S0QTyklqYcYJ8qDZtUuTPMM7uPZTS8Hs=&_dt_no_comment=1&origin=11)

6
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
<version>2.2.4</version>
<packaging>jar</packaging>
<name>easyexcel</name>
@ -97,7 +97,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
<version>1.2.68</version>
<scope>test</scope>
</dependency>
<dependency>
@ -162,6 +162,8 @@
<exclude>com/alibaba/excel/event/AnalysisEventListener.java</exclude>
<exclude>com/alibaba/excel/metadata/DataFormatter.java</exclude>
<exclude>com/alibaba/excel/util/DateUtils.java</exclude>
<exclude>com/alibaba/excel/metadata/format/DataFormatter.java</exclude>
<exclude>com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java</exclude>
</excludes>
</configuration>
<executions>

2
src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java

@ -147,7 +147,7 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
return;
}
boolean ignoreRecord = (handler instanceof IgnorableXlsRecordHandler)
&& xlsReadContext.xlsReadSheetHolder() != null && xlsReadContext.xlsReadSheetHolder().getIgnoreRecord();
&& xlsReadContext.xlsReadSheetHolder() != null && xlsReadContext.xlsReadWorkbookHolder().getIgnoreRecord();
if (ignoreRecord) {
// No need to read the current sheet
return;

13
src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java

@ -22,10 +22,11 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
BOFRecord br = (BOFRecord)record;
BOFRecord br = (BOFRecord) record;
XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder();
if (br.getType() == BOFRecord.TYPE_WORKBOOK) {
xlsReadWorkbookHolder.setReadSheetIndex(null);
xlsReadWorkbookHolder.setIgnoreRecord(Boolean.FALSE);
return;
}
if (br.getType() != BOFRecord.TYPE_WORKSHEET) {
@ -38,15 +39,15 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
readSheetIndex = 0;
xlsReadWorkbookHolder.setReadSheetIndex(readSheetIndex);
}
ReadSheet readSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
assert readSheet != null : "Can't find the sheet.";
ReadSheet actualReadSheet = xlsReadWorkbookHolder.getActualSheetDataList().get(readSheetIndex);
assert actualReadSheet != null : "Can't find the sheet.";
// Copy the parameter to the current sheet
readSheet = SheetUtils.match(readSheet, xlsReadContext);
ReadSheet readSheet = SheetUtils.match(actualReadSheet, xlsReadContext);
if (readSheet != null) {
xlsReadContext.currentSheet(readSheet);
xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.FALSE);
xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.FALSE);
} else {
xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE);
xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.TRUE);
}
// Go read the next one
xlsReadWorkbookHolder.setReadSheetIndex(xlsReadWorkbookHolder.getReadSheetIndex() + 1);

3
src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java

@ -3,6 +3,7 @@ package com.alibaba.excel.analysis.v03.handlers;
import java.math.BigDecimal;
import java.util.Map;
import com.alibaba.excel.enums.RowTypeEnum;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
@ -14,6 +15,7 @@ import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.metadata.CellData;
@ -43,6 +45,7 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
}
tempCellData.setFormula(Boolean.TRUE);
tempCellData.setFormulaValue(formulaValue);
xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA);
switch (cellType) {
case STRING:
// Formula result is a string

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

@ -10,6 +10,7 @@ import com.alibaba.excel.enums.RowTypeEnum;
import com.alibaba.excel.metadata.Cell;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.PositionUtils;
/**
@ -39,7 +40,9 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
@Override
public void endElement(XlsxReadContext xlsxReadContext, String name) {
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), RowTypeEnum.DATA,
RowTypeEnum rowType =
CollectionUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,
xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null);

21
src/main/java/com/alibaba/excel/context/WriteContextImpl.java

@ -112,7 +112,6 @@ public class WriteContextImpl implements WriteContext {
return;
}
initCurrentSheetHolder(writeSheet);
// Workbook handler need to supplementary execution
@ -125,8 +124,12 @@ public class WriteContextImpl implements WriteContext {
private boolean selectSheetFromCache(WriteSheet writeSheet) {
writeSheetHolder = null;
if (writeSheet.getSheetNo() != null) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(writeSheet.getSheetNo());
Integer sheetNo = writeSheet.getSheetNo();
if (sheetNo == null && StringUtils.isEmpty(writeSheet.getSheetName())) {
sheetNo = 0;
}
if (sheetNo != null) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(sheetNo);
}
if (writeSheetHolder == null && !StringUtils.isEmpty(writeSheet.getSheetName())) {
writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetNameMap().get(writeSheet.getSheetName());
@ -160,9 +163,15 @@ public class WriteContextImpl implements WriteContext {
Sheet currentSheet;
try {
if (writeSheetHolder.getSheetNo() != null) {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
// When the add default sort order of appearance
if (WriteTypeEnum.ADD.equals(writeType) && writeWorkbookHolder.getTempTemplateInputStream() == null) {
currentSheet = createSheet();
} else {
currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo());
writeSheetHolder
.setCachedSheet(
writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo()));
}
} else {
// sheet name must not null
currentSheet = writeWorkbookHolder.getWorkbook().getSheet(writeSheetHolder.getSheetName());

1
src/main/java/com/alibaba/excel/metadata/AbstractHolder.java

@ -68,6 +68,7 @@ public abstract class AbstractHolder implements ConfigurationHolder {
} else {
globalConfiguration.setLocale(basicParameter.getLocale());
}
}
public Boolean getNewInitialization() {

15
src/main/java/com/alibaba/excel/metadata/BasicParameter.java

@ -41,6 +41,13 @@ public class BasicParameter {
*/
private Locale locale;
/**
* Whether to use scientific Format.
*
* default is false
*/
private Boolean useScientificFormat;
public List<List<String>> getHead() {
return head;
}
@ -88,4 +95,12 @@ public class BasicParameter {
public void setLocale(Locale locale) {
this.locale = locale;
}
public Boolean getUseScientificFormat() {
return useScientificFormat;
}
public void setUseScientificFormat(Boolean useScientificFormat) {
this.useScientificFormat = useScientificFormat;
}
}

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

@ -25,6 +25,12 @@ public class GlobalConfiguration {
* used when formatting dates and numbers.
*/
private Locale locale;
/**
* Whether to use scientific Format.
*
* default is false
*/
private Boolean useScientificFormat;
public Boolean getUse1904windowing() {
return use1904windowing;
@ -49,4 +55,12 @@ public class GlobalConfiguration {
public void setLocale(Locale locale) {
this.locale = locale;
}
public Boolean getUseScientificFormat() {
return useScientificFormat;
}
public void setUseScientificFormat(Boolean useScientificFormat) {
this.useScientificFormat = useScientificFormat;
}
}

33
src/main/java/com/alibaba/excel/metadata/DataFormatter.java → src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java

@ -15,7 +15,7 @@
* can be found in svn at location root/projects/3rd-party/src
* ====================================================================
*/
package com.alibaba.excel.metadata;
package com.alibaba.excel.metadata.format;
import java.math.BigDecimal;
import java.math.RoundingMode;
@ -35,12 +35,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ExcelGeneralNumberFormat;
import org.apache.poi.ss.usermodel.ExcelStyleDateFormatter;
import org.apache.poi.ss.usermodel.FractionFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.util.DateUtils;
/**
@ -138,21 +138,32 @@ public class DataFormatter {
* @return
*/
private Boolean use1904windowing;
/**
* Creates a formatter using the {@link Locale#getDefault() default locale}.
* Whether to use scientific Format.
*
* default is false
*/
public DataFormatter() {
this(null, null);
}
private Boolean useScientificFormat;
/**
* Creates a formatter using the given locale.
*
*/
public DataFormatter(Locale locale, Boolean use1904windowing) {
this.use1904windowing = use1904windowing != null ? use1904windowing : Boolean.FALSE;
this.locale = locale != null ? locale : Locale.getDefault();
public DataFormatter(GlobalConfiguration globalConfiguration) {
if (globalConfiguration == null) {
this.use1904windowing = Boolean.FALSE;
this.locale = Locale.getDefault();
this.useScientificFormat = Boolean.FALSE;
} else {
this.use1904windowing =
globalConfiguration.getUse1904windowing() != null ? globalConfiguration.getUse1904windowing()
: Boolean.FALSE;
this.locale =
globalConfiguration.getLocale() != null ? globalConfiguration.getLocale() : Locale.getDefault();
this.useScientificFormat =
globalConfiguration.getUseScientificFormat() != null ? globalConfiguration.getUseScientificFormat()
: Boolean.FALSE;
}
this.dateSymbols = DateFormatSymbols.getInstance(this.locale);
this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale);
}
@ -532,7 +543,7 @@ public class DataFormatter {
return defaultNumFormat;
// otherwise use general format
}
defaultNumFormat = new ExcelGeneralNumberFormat(locale);
defaultNumFormat = new ExcelGeneralNumberFormat(locale, useScientificFormat);
return defaultNumFormat;
}

81
src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java

@ -0,0 +1,81 @@
package com.alibaba.excel.metadata.format;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Locale;
import org.apache.poi.ss.usermodel.DataFormatter;
/**
* Written with reference to {@link org.apache.poi.ss.usermodel.ExcelGeneralNumberFormat }.
* <p>
* Supported Do not use scientific notation.
*
* @author JiaJu Zhuang
**/
public class ExcelGeneralNumberFormat extends Format {
private static final long serialVersionUID = 1L;
private static final MathContext TO_10_SF = new MathContext(10, RoundingMode.HALF_UP);
private final DecimalFormatSymbols decimalSymbols;
private final DecimalFormat integerFormat;
private final DecimalFormat decimalFormat;
private final DecimalFormat scientificFormat;
public ExcelGeneralNumberFormat(final Locale locale, final boolean useScientificFormat) {
decimalSymbols = DecimalFormatSymbols.getInstance(locale);
// Supported Do not use scientific notation.
if (useScientificFormat) {
scientificFormat = new DecimalFormat("0.#####E0", decimalSymbols);
} else {
scientificFormat = new DecimalFormat("#", decimalSymbols);
}
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(scientificFormat);
integerFormat = new DecimalFormat("#", decimalSymbols);
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(integerFormat);
decimalFormat = new DecimalFormat("#.##########", decimalSymbols);
DataFormatter.setExcelStyleRoundingMode(decimalFormat);
}
@Override
public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) {
final double value;
if (number instanceof Number) {
value = ((Number) number).doubleValue();
if (Double.isInfinite(value) || Double.isNaN(value)) {
return integerFormat.format(number, toAppendTo, pos);
}
} else {
// testBug54786 gets here with a date, so retain previous behaviour
return integerFormat.format(number, toAppendTo, pos);
}
final double abs = Math.abs(value);
if (abs >= 1E11 || (abs <= 1E-10 && abs > 0)) {
return scientificFormat.format(number, toAppendTo, pos);
} else if (Math.floor(value) == value || abs >= 1E10) {
// integer, or integer portion uses all 11 allowed digits
return integerFormat.format(number, toAppendTo, pos);
}
// Non-integers of non-scientific magnitude are formatted as "up to 11
// numeric characters, with the decimal point counting as a numeric
// character". We know there is a decimal point, so limit to 10 digits.
// https://support.microsoft.com/en-us/kb/65903
final double rounded = new BigDecimal(value).round(TO_10_SF).doubleValue();
return decimalFormat.format(rounded, toAppendTo, pos);
}
@Override
public Object parseObject(String source, ParsePosition pos) {
throw new UnsupportedOperationException();
}
}

9
src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java

@ -73,7 +73,7 @@ public class ExcelHeadProperty {
int headIndex = 0;
for (int i = 0; i < head.size(); i++) {
if (holder instanceof AbstractWriteHolder) {
if (((AbstractWriteHolder)holder).ignore(null, i)) {
if (((AbstractWriteHolder) holder).ignore(null, i)) {
continue;
}
}
@ -130,9 +130,8 @@ public class ExcelHeadProperty {
index++;
}
}
if (!initOneColumnProperty(holder, index, field, Boolean.FALSE)) {
index++;
}
initOneColumnProperty(holder, index, field, Boolean.FALSE);
index++;
}
for (Map.Entry<Integer, Field> entry : customFiledMap.entrySet()) {
initOneColumnProperty(holder, entry.getKey(), entry.getValue(), Boolean.TRUE);
@ -151,7 +150,7 @@ public class ExcelHeadProperty {
*/
private boolean initOneColumnProperty(Holder holder, int index, Field field, Boolean forceIndex) {
if (holder instanceof AbstractWriteHolder) {
if (((AbstractWriteHolder)holder).ignore(field.getName(), index)) {
if (((AbstractWriteHolder) holder).ignore(field.getName(), index)) {
return true;
}
}

13
src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java

@ -31,6 +31,19 @@ public abstract class AbstractExcelReaderParameterBuilder<T extends AbstractExce
return self();
}
/**
* Whether to use scientific Format.
*
* default is false
*
* @param useScientificFormat
* @return
*/
public T useScientificFormat(Boolean useScientificFormat) {
parameter().setUseScientificFormat(useScientificFormat);
return self();
}
/**
* Custom type listener run after default
*

11
src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java

@ -56,6 +56,17 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
getGlobalConfiguration().setUse1904windowing(readBasicParameter.getUse1904windowing());
}
if (readBasicParameter.getUseScientificFormat() == null) {
if (parentAbstractReadHolder == null) {
getGlobalConfiguration().setUseScientificFormat(Boolean.FALSE);
} else {
getGlobalConfiguration()
.setUseScientificFormat(parentAbstractReadHolder.getGlobalConfiguration().getUseScientificFormat());
}
} else {
getGlobalConfiguration().setUseScientificFormat(readBasicParameter.getUseScientificFormat());
}
// Initialization property
this.excelReadHeadProperty = new ExcelReadHeadProperty(this, getClazz(), getHead(), convertAllFiled);
if (readBasicParameter.getHeadRowNumber() == null) {

12
src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java

@ -18,10 +18,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
* Row type.Temporary storage, last set in <code>ReadRowHolder</code>.
*/
private RowTypeEnum tempRowType;
/**
* Ignore record.
*/
private Boolean ignoreRecord;
/**
* Temp object index.
*/
@ -33,7 +29,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
public XlsReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) {
super(readSheet, readWorkbookHolder);
ignoreRecord = Boolean.FALSE;
tempRowType = RowTypeEnum.EMPTY;
objectCacheMap = new HashMap<Integer, String>(16);
}
@ -46,13 +41,6 @@ public class XlsReadSheetHolder extends ReadSheetHolder {
this.tempRowType = tempRowType;
}
public Boolean getIgnoreRecord() {
return ignoreRecord;
}
public void setIgnoreRecord(Boolean ignoreRecord) {
this.ignoreRecord = ignoreRecord;
}
public Integer getTempObjectIndex() {
return tempObjectIndex;

13
src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java

@ -42,6 +42,10 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
* Sheet Index
*/
private Integer readSheetIndex;
/**
* Ignore record.
*/
private Boolean ignoreRecord;
public XlsReadWorkbookHolder(ReadWorkbook readWorkbook) {
super(readWorkbook);
@ -51,6 +55,7 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
if (getGlobalConfiguration().getUse1904windowing() == null) {
getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
}
ignoreRecord = Boolean.FALSE;
}
public POIFSFileSystem getPoifsFileSystem() {
@ -100,4 +105,12 @@ public class XlsReadWorkbookHolder extends ReadWorkbookHolder {
public void setReadSheetIndex(Integer readSheetIndex) {
this.readSheetIndex = readSheetIndex;
}
public Boolean getIgnoreRecord() {
return ignoreRecord;
}
public void setIgnoreRecord(Boolean ignoreRecord) {
this.ignoreRecord = ignoreRecord;
}
}

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

@ -1,6 +1,6 @@
package com.alibaba.excel.util;
import com.alibaba.excel.metadata.DataFormatter;
import com.alibaba.excel.metadata.format.DataFormatter;
import com.alibaba.excel.metadata.GlobalConfiguration;
/**
@ -9,6 +9,7 @@ import com.alibaba.excel.metadata.GlobalConfiguration;
* @author Jiaju Zhuang
**/
public class NumberDataFormatterUtils {
/**
* Cache DataFormatter.
*/
@ -18,8 +19,7 @@ public class NumberDataFormatterUtils {
* Format number data.
*
* @param data
* @param dataFormat
* Not null.
* @param dataFormat Not null.
* @param dataFormatString
* @param globalConfiguration
* @return
@ -28,12 +28,7 @@ public class NumberDataFormatterUtils {
GlobalConfiguration globalConfiguration) {
DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get();
if (dataFormatter == null) {
if (globalConfiguration != null) {
dataFormatter =
new DataFormatter(globalConfiguration.getLocale(), globalConfiguration.getUse1904windowing());
} else {
dataFormatter = new DataFormatter();
}
dataFormatter = new DataFormatter(globalConfiguration);
DATA_FORMATTER_THREAD_LOCAL.set(dataFormatter);
}
return dataFormatter.format(data, dataFormat, dataFormatString);

1
src/main/java/com/alibaba/excel/util/NumberUtils.java

@ -167,6 +167,7 @@ public class NumberUtils {
RoundingMode roundingMode = contentProperty.getNumberFormatProperty().getRoundingMode();
DecimalFormat decimalFormat = new DecimalFormat(format);
decimalFormat.setRoundingMode(roundingMode);
decimalFormat.setParseBigDecimal(true);
return decimalFormat.parse(string);
}
}

1
src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java

@ -156,6 +156,7 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName)
|| ignoreMap.containsKey(filedName) || writeContext.currentWriteHolder().ignore(filedName, cellIndex);
if (uselessData) {
cellIndex++;
continue;
}
Object value = beanMap.get(filedName);

64
src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java

@ -295,28 +295,9 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
default:
throw new ExcelGenerateException("The wrong direction.");
}
Row row = sheet.getRow(lastRowIndex);
if (row == null) {
row = cachedSheet.getRow(lastRowIndex);
if (row == null) {
WriteHandlerUtils.beforeRowCreate(writeContext, lastRowIndex, null, Boolean.FALSE);
if (fillConfig.getForceNewRow()) {
row = cachedSheet.createRow(lastRowIndex);
} else {
row = sheet.createRow(lastRowIndex);
}
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE);
} else {
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
}
}
Cell cell = row.getCell(lastColumnIndex);
if (cell == null) {
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, lastColumnIndex, null, Boolean.FALSE);
cell = row.createCell(lastColumnIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, null, Boolean.FALSE);
}
Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell);
Cell cell = createCellIfNecessary(row,lastColumnIndex);
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag);
if (collectionFieldStyleMap == null) {
@ -334,6 +315,45 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
return cell;
}
private Cell createCellIfNecessary(Row row, Integer lastColumnIndex) {
Cell cell = row.getCell(lastColumnIndex);
if (cell != null) {
return cell;
}
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, lastColumnIndex, null, Boolean.FALSE);
cell = row.createCell(lastColumnIndex);
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, null, Boolean.FALSE);
return cell;
}
private Row createRowIfNecessary(Sheet sheet, Sheet cachedSheet, Integer lastRowIndex, FillConfig fillConfig,
AnalysisCell analysisCell, boolean isOriginalCell) {
Row row = sheet.getRow(lastRowIndex);
if (row != null) {
return row;
}
row = cachedSheet.getRow(lastRowIndex);
if (row == null) {
WriteHandlerUtils.beforeRowCreate(writeContext, lastRowIndex, null, Boolean.FALSE);
if (fillConfig.getForceNewRow()) {
row = cachedSheet.createRow(lastRowIndex);
} else {
// The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside.
// Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh.getLastRowNum() + "] that is already written to disk.
try {
row = sheet.createRow(lastRowIndex);
} catch (IllegalArgumentException ignore) {
row = cachedSheet.createRow(lastRowIndex);
}
}
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE);
} else {
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
}
return row;
}
private void checkRowHeight(AnalysisCell analysisCell, FillConfig fillConfig, boolean isOriginalCell, Row row) {
if (!analysisCell.getFirstRow() || !WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection())) {
return;

56
src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java

@ -0,0 +1,56 @@
package com.alibaba.excel.write.merge;
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
*
* @author Jiaju Zhuang
*/
public abstract class AbstractMergeStrategy implements CellWriteHandler {
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder,
WriteTableHolder writeTableHolder, CellData cellData, Cell cell, 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);
}

4
src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java

@ -111,6 +111,10 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
getGlobalConfiguration().setUse1904windowing(writeBasicParameter.getUse1904windowing());
}
if (writeBasicParameter.getUseScientificFormat() != null) {
throw new UnsupportedOperationException("Currently does not support setting useScientificFormat.");
}
if (writeBasicParameter.getNeedHead() == null) {
if (parentAbstractWriteHolder == null) {
this.needHead = Boolean.TRUE;

1
src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java

@ -112,6 +112,7 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
*/
private Boolean writeExcelOnException;
public WriteWorkbookHolder(WriteWorkbook writeWorkbook) {
super(writeWorkbook, null, writeWorkbook.getConvertAllFiled());
this.writeWorkbook = writeWorkbook;

24
src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java

@ -39,6 +39,7 @@ import com.alibaba.excel.metadata.property.StyleProperty;
* @author jipengfei
*/
public class ExcelWriteHeadProperty extends ExcelHeadProperty {
private RowHeightProperty headRowHeightProperty;
private RowHeightProperty contentRowHeightProperty;
private OnceAbsoluteMergeProperty onceAbsoluteMergeProperty;
@ -49,21 +50,25 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty {
return;
}
this.headRowHeightProperty =
RowHeightProperty.build((HeadRowHeight)headClazz.getAnnotation(HeadRowHeight.class));
RowHeightProperty.build((HeadRowHeight) headClazz.getAnnotation(HeadRowHeight.class));
this.contentRowHeightProperty =
RowHeightProperty.build((ContentRowHeight)headClazz.getAnnotation(ContentRowHeight.class));
RowHeightProperty.build((ContentRowHeight) headClazz.getAnnotation(ContentRowHeight.class));
this.onceAbsoluteMergeProperty =
OnceAbsoluteMergeProperty.build((OnceAbsoluteMerge)headClazz.getAnnotation(OnceAbsoluteMerge.class));
OnceAbsoluteMergeProperty.build((OnceAbsoluteMerge) headClazz.getAnnotation(OnceAbsoluteMerge.class));
ColumnWidth parentColumnWidth = (ColumnWidth)headClazz.getAnnotation(ColumnWidth.class);
HeadStyle parentHeadStyle = (HeadStyle)headClazz.getAnnotation(HeadStyle.class);
HeadFontStyle parentHeadFontStyle = (HeadFontStyle)headClazz.getAnnotation(HeadFontStyle.class);
ContentStyle parentContentStyle = (ContentStyle)headClazz.getAnnotation(ContentStyle.class);
ContentFontStyle parentContentFontStyle = (ContentFontStyle)headClazz.getAnnotation(ContentFontStyle.class);
ColumnWidth parentColumnWidth = (ColumnWidth) headClazz.getAnnotation(ColumnWidth.class);
HeadStyle parentHeadStyle = (HeadStyle) headClazz.getAnnotation(HeadStyle.class);
HeadFontStyle parentHeadFontStyle = (HeadFontStyle) headClazz.getAnnotation(HeadFontStyle.class);
ContentStyle parentContentStyle = (ContentStyle) headClazz.getAnnotation(ContentStyle.class);
ContentFontStyle parentContentFontStyle = (ContentFontStyle) headClazz.getAnnotation(ContentFontStyle.class);
for (Map.Entry<Integer, ExcelContentProperty> entry : getContentPropertyMap().entrySet()) {
Integer index = entry.getKey();
ExcelContentProperty excelContentPropertyData = entry.getValue();
if (excelContentPropertyData == null) {
throw new IllegalArgumentException(
"Passing in the class and list the head, the two must be the same size.");
}
Field field = excelContentPropertyData.getField();
Head headData = getHeadMap().get(index);
ColumnWidth columnWidth = field.getAnnotation(ColumnWidth.class);
@ -176,7 +181,8 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty {
if (j == lastRow && i == lastCol) {
continue;
}
cellRangeList.add(new CellRange(j, lastRow, i, lastCol));
cellRangeList
.add(new CellRange(j, lastRow, head.getColumnIndex(), headList.get(lastCol).getColumnIndex()));
}
}
return cellRangeList;

3
src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java

@ -22,6 +22,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
* @author Jiaju Zhuang
*/
public abstract class AbstractCellStyleStrategy implements CellWriteHandler, WorkbookWriteHandler, NotRepeatExecutor {
boolean hasInitialized = false;
@Override
@ -50,7 +51,7 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, Wor
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead == null || head == null) {
if (isHead == null) {
return;
}
if (isHead) {

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

@ -12,7 +12,6 @@ import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
/**
*
* Use the same style for the column
*
* @author Jiaju Zhuang
@ -30,6 +29,9 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
@Override
protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (head == null) {
return;
}
int columnIndex = head.getColumnIndex();
if (headCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = headCellStyleCache.get(columnIndex);
@ -50,6 +52,9 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if (head == null) {
return;
}
int columnIndex = head.getColumnIndex();
if (contentCellStyleCache.containsKey(columnIndex)) {
CellStyle cellStyle = contentCellStyleCache.get(columnIndex);
@ -71,8 +76,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
/**
* Returns the column width corresponding to each column head
*
* @param head
* Nullable
* @param head Nullable
* @return
*/
protected abstract WriteCellStyle headCellStyle(Head head);
@ -80,8 +84,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl
/**
* Returns the column width corresponding to each column head
*
* @param head
* Nullable
* @param head Nullable
* @return
*/
protected abstract WriteCellStyle contentCellStyle(Head head);

44
src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java

@ -27,6 +27,7 @@ import com.alibaba.fastjson.JSON;
*/
@Ignore
public class ReadTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ReadTest.class);
/**
@ -48,11 +49,17 @@ public class ReadTest {
// 写法2:
fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
ExcelReader excelReader = null;
try {
excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
ReadSheet readSheet = EasyExcel.readSheet(0).build();
excelReader.read(readSheet);
} finally {
if (excelReader != null) {
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
}
}
}
/**
@ -90,16 +97,23 @@ public class ReadTest {
// 读取部分sheet
fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
ExcelReader excelReader = EasyExcel.read(fileName).build();
// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
ReadSheet readSheet1 =
EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
ReadSheet readSheet2 =
EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
// 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能
excelReader.read(readSheet1, readSheet2);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
ExcelReader excelReader = null;
try {
excelReader = EasyExcel.read(fileName).build();
// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
ReadSheet readSheet1 =
EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
ReadSheet readSheet2 =
EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
// 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能
excelReader.read(readSheet1, readSheet2);
} finally {
if (excelReader != null) {
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
}
}
}
/**

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

@ -40,6 +40,7 @@ import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy
*/
@Ignore
public class WriteTest {
/**
* 最简单的写
* <p>
@ -58,11 +59,17 @@ public class WriteTest {
// 写法2
fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel.write(fileName, DemoData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
/**
@ -141,48 +148,64 @@ public class WriteTest {
public void repeatedWrite() {
// 方法1 如果写到同一个sheet
String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
for (int i = 0; i < 5; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
ExcelWriter excelWriter = null;
try {
// 这里 需要指定写用哪个class去写
excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
for (int i = 0; i < 5; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
// 方法2 如果写到不同的sheet 同一个对象
fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 指定文件
excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
try {
// 这里 指定文件
excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
// 方法3 如果写到不同的sheet 不同的对象
fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 指定文件
excelWriter = EasyExcel.write(fileName).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
try {
// 这里 指定文件
excelWriter = EasyExcel.write(fileName).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 5; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<DemoData> data = data();
excelWriter.write(data, writeSheet);
}
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
/**
@ -302,7 +325,7 @@ public class WriteTest {
// 背景设置为红色
headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)20);
headWriteFont.setFontHeightInPoints((short) 20);
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
@ -312,7 +335,7 @@ public class WriteTest {
contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short)20);
contentWriteFont.setFontHeightInPoints((short) 20);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
@ -362,18 +385,24 @@ public class WriteTest {
String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx";
// 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();
WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();
// 第一次写入会创建头
excelWriter.write(data(), writeSheet, writeTable0);
// 第二次写如也会创建头,然后在第一次的后面写入数据
excelWriter.write(data(), writeSheet, writeTable1);
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
ExcelWriter excelWriter = null;
try {
EasyExcel.write(fileName, DemoData.class).build();
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.TRUE).build();
WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();
// 第一次写入会创建头
excelWriter.write(data(), writeSheet, writeTable0);
// 第二次写如也会创建头,然后在第一次的后面写入数据
excelWriter.write(data(), writeSheet, writeTable1);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
/**
@ -399,8 +428,7 @@ public class WriteTest {
/**
* 自动列宽(不太精确)
* <p>
* 这个目前不是很好用比如有数字就会导致换行而且长度也不是刚好和实际长度一致 所以需要精确到刚好列宽的慎用 当然也可以自己参照
* {@link LongestMatchColumnWidthStyleStrategy}重新实现.
* 这个目前不是很好用比如有数字就会导致换行而且长度也不是刚好和实际长度一致 所以需要精确到刚好列宽的慎用 当然也可以自己参照 {@link LongestMatchColumnWidthStyleStrategy}重新实现.
* <p>
* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好目前没找到很好的算法 有的话可以推荐下
*

16
src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java

@ -13,6 +13,7 @@ import com.alibaba.easyexcel.test.temp.fill.FillData2;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
/**
@ -33,16 +34,21 @@ public class FillTempTest {
public void complexFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName = "D:\\test\\simple.xlsx";
OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(2, 2, 0, 1);
String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(teamp(), writeSheet);
ExcelWriter excelWriter = EasyExcel.write(fileName).registerWriteHandler(onceAbsoluteMergeStrategy).withTemplate(TestFileUtil.readUserHomeFile("test/simple.xlsx")).build();
WriteSheet writeSheet0 = EasyExcel.writerSheet(0).build();
WriteSheet writeSheet1 = EasyExcel.writerSheet(1).build();
excelWriter.fill(teamp(), writeSheet0);
excelWriter.fill(teamp(), writeSheet1);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
excelWriter.fill(map, writeSheet);
excelWriter.fill(map, writeSheet0);
excelWriter.finish();
}

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

@ -28,19 +28,29 @@ import com.alibaba.fastjson.JSON;
**/
@Ignore
public class Lock2Test {
private static final Logger LOGGER = LoggerFactory.getLogger(Lock2Test.class);
@Test
public void test() throws Exception {
File file = TestFileUtil.readUserHomeFile("test/t3.xls");
File file = TestFileUtil.readUserHomeFile("test/test6.xls");
List<Object> list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync();
List<Object> list = EasyExcel.read(file).sheet(1).headRowNumber(0).doReadSync();
LOGGER.info("数据:{}", list.size());
for (Object data : list) {
LOGGER.info("返回数据:{}", JSON.toJSONString(data));
}
}
@Test
public void test33() throws Exception {
File file = TestFileUtil.readUserHomeFile("test/test6.xlsx");
EasyExcel.read(file, LockData.class, new LockDataListener()).sheet(0).headRowNumber(0)
.doRead();
}
@Test
public void write() throws Exception {
String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".xlsx";
@ -49,7 +59,7 @@ public class Lock2Test {
// 背景设置为红色
headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short)20);
headWriteFont.setFontHeightInPoints((short) 20);
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
@ -59,7 +69,7 @@ public class Lock2Test {
contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short)20);
contentWriteFont.setFontHeightInPoints((short) 20);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
HorizontalCellStyleStrategy horizontalCellStyleStrategy =

5
src/test/java/com/alibaba/easyexcel/test/temp/LockData.java

@ -1,5 +1,7 @@
package com.alibaba.easyexcel.test.temp;
import com.alibaba.excel.annotation.format.NumberFormat;
import lombok.Data;
/**
@ -9,7 +11,8 @@ import lombok.Data;
**/
@Data
public class LockData {
private String string0;
@NumberFormat("#.##%")
private Double string0;
private String string1;
private String string2;
private String string3;

6
src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java

@ -18,16 +18,16 @@ import com.alibaba.fastjson.JSON;
*
* @author Jiaju Zhuang
*/
public class LockDataListener extends AnalysisEventListener<Map<Integer, CellData>> {
public class LockDataListener extends AnalysisEventListener<LockData> {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
/**
* 每隔5条存储数据库实际使用中可以3000条然后清理list 方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<Map<Integer, CellData>> list = new ArrayList<Map<Integer, CellData>>();
List<LockData> list = new ArrayList<LockData>();
@Override
public void invoke(Map<Integer, CellData> data, AnalysisContext context) {
public void invoke(LockData data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
list.add(data);
if (list.size() >= BATCH_COUNT) {

108
src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java

@ -0,0 +1,108 @@
package com.alibaba.easyexcel.test.temp;
import java.util.ArrayList;
import java.util.List;
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;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.easyexcel.test.core.large.LargeData;
import com.alibaba.easyexcel.test.demo.write.DemoData;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
/**
* 临时测试
*
* @author Jiaju Zhuang
**/
@Ignore
public class WriteLargeTest {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteLargeTest.class);
private int i = 0;
@Test
public void test() throws Exception {
// 方法2 如果写到不同的sheet 同一个对象
String fileName = TestFileUtil.getPath() + "large" + 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);
ExcelWriter excelWriter = EasyExcel.write(fileName,LargeData.class).registerWriteHandler(horizontalCellStyleStrategy).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
for (int j = 0; j < 100; j++) {
excelWriter.write(data(), writeSheet);
LOGGER.info("{} fill success.", j);
}
excelWriter.finish();
}
private List<LargeData> data() {
List<LargeData> list = new ArrayList<LargeData>();
int size = i + 5000;
for (; i < size; i++) {
LargeData largeData = new LargeData();
list.add(largeData);
largeData.setStr1("str1-" + i);
largeData.setStr2("str2-" + i);
largeData.setStr3("str3-" + i);
largeData.setStr4("str4-" + i);
largeData.setStr5("str5-" + i);
largeData.setStr6("str6-" + i);
largeData.setStr7("str7-" + i);
largeData.setStr8("str8-" + i);
largeData.setStr9("str9-" + i);
largeData.setStr10("str10-" + i);
largeData.setStr11("str11-" + i);
largeData.setStr12("str12-" + i);
largeData.setStr13("str13-" + i);
largeData.setStr14("str14-" + i);
largeData.setStr15("str15-" + i);
largeData.setStr16("str16-" + i);
largeData.setStr17("str17-" + i);
largeData.setStr18("str18-" + i);
largeData.setStr19("str19-" + i);
largeData.setStr20("str20-" + i);
largeData.setStr21("str21-" + i);
largeData.setStr22("str22-" + i);
largeData.setStr23("str23-" + i);
largeData.setStr24("str24-" + i);
largeData.setStr25("str25-" + i);
}
return list;
}
}

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

@ -0,0 +1,67 @@
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.ExcelWriter;
import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
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;
/**
* 临时测试
*
* @author Jiaju Zhuang
**/
@Ignore
public class WriteV33Test {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteV33Test.class);
@Test
public void test() throws Exception {
// 方法2 如果写到不同的sheet 同一个对象
String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(2, 2, 0, 1);
// 这里 指定文件
ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler(onceAbsoluteMergeStrategy).build();
WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "模板1").build();
WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "模板2").build();
WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "模板3").build();
excelWriter.write(data(2), writeSheet2);
excelWriter.write(data(3), writeSheet3);
excelWriter.write(data(1), writeSheet1);
excelWriter.write(data(3), writeSheet3);
excelWriter.write(data(1), writeSheet1);
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
private List<DemoData> data(int no) {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + no + "---" + i);
list.add(data);
}
return list;
}
}

91
src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java

@ -0,0 +1,91 @@
package com.alibaba.easyexcel.test.temp;
import java.util.ArrayList;
import java.util.List;
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.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
/**
* 临时测试
*
* @author Jiaju Zhuang
**/
@Ignore
public class WriteV34Test {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteV34Test.class);
@Test
public void test() throws Exception {
String fileName = TestFileUtil.getPath() + "handlerStyleWrite" + 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).head(head()).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
.doWrite(data(1));
}
private List<List<String>> head() {
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
head0.add("字符串" + System.currentTimeMillis());
head0.add("再找找");
List<String> head1 = new ArrayList<String>();
head1.add("数字" + System.currentTimeMillis());
List<String> head2 = new ArrayList<String>();
head2.add("日期" + System.currentTimeMillis());
List<String> head3 = new ArrayList<String>();
head3.add("日期" + System.currentTimeMillis());
list.add(head0);
list.add(head1);
list.add(head2); list.add(head3);
return list;
}
private List<DemoData> data(int no) {
List<DemoData> list = new ArrayList<DemoData>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + no + "---" + i);
list.add(data);
}
return list;
}
}

1
src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java

@ -126,6 +126,7 @@ public class Wirte {
for (int i = 0; i < 10; i++) {
WriteData data = new WriteData();
data.setF(300.35f);
data.setF1(33f);
list.add(data);
}
return list;

4
src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java

@ -11,6 +11,8 @@ import lombok.Data;
**/
@Data
public class WriteData {
@ContentStyle(locked = true)
// @ContentStyle(locked = true)
private float f;
// @ContentStyle(locked = false)
private float f1;
}

14
update.md

@ -1,9 +1,23 @@
# 2.2.4
* 撤销删除`AbstractMergeStrategy`
* 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改
* 修复07版仅有样式的空行 默认不忽略的bug
* 写入`sheet`不设置`index`和`name`默认不为0的问题
* 修复多个`sheet`不按照顺序写入 会乱序的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332)
* 修改head是List时,内容单元格的样式不生效 [Issue #1339](https://github.com/alibaba/easyexcel/issues/1339)
* 修复xls仅公式行 不读取的bug [Issue #1324](https://github.com/alibaba/easyexcel/issues/1324)
* 修复xls直接读取第2页 `NPE` 的bug [Issue #1280](https://github.com/alibaba/easyexcel/issues/1280)
* 修复填充的时候,最后一行中间有空行会创建失败的bug
* 修复`includeColumnIndexes`不包含第列 会无法导出数据的bug [Issue #1346](https://github.com/alibaba/easyexcel/issues/1346)
* 修复`@NumberFormat`注解转换double时可能会丢失精度 [Issue #1306](https://github.com/alibaba/easyexcel/issues/1306)
# 2.2.3
* 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274)
* 回退自定义转换器入参为空
# 2.2.2
* 修改`sheet`事件未调用的bug
* 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322)
# 2.2.1
* 发布正式版

Loading…
Cancel
Save