未验证 提交 35260466 编写于 作者: 庄家钜's avatar 庄家钜 提交者: GitHub

Merge pull request #1391 from alibaba/developing

Developing
......@@ -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)
......
......@@ -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>
......
......@@ -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;
......
......@@ -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,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
......
......@@ -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);
......
......@@ -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());
......
......@@ -68,6 +68,7 @@ public abstract class AbstractHolder implements ConfigurationHolder {
} else {
globalConfiguration.setLocale(basicParameter.getLocale());
}
}
public Boolean getNewInitialization() {
......
......@@ -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;
}
}
......@@ -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;
}
}
......@@ -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;
}
......
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();
}
}
......@@ -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;
}
}
......
......@@ -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
*
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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;
}
}
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);
......
......@@ -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);
}
}
......@@ -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);
......
......@@ -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;
......
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);
}
......@@ -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;
......
......@@ -112,6 +112,7 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
*/
private Boolean writeExcelOnException;
public WriteWorkbookHolder(WriteWorkbook writeWorkbook) {
super(writeWorkbook, null, writeWorkbook.getConvertAllFiled());
this.writeWorkbook = writeWorkbook;
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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();
}
}
}
/**
......
......@@ -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)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。
*
......
......@@ -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();
}
......
......@@ -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 =
......
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;
......
......@@ -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) {
......
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;
}
}
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;
}
}
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;
}
}
......@@ -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;
......
......@@ -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;
}
# 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
* 发布正式版
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册