From fa73c782463acafb2a9f8d2d4ba9deaf675f17ba Mon Sep 17 00:00:00 2001 From: laiyijie <449132062@qq.com> Date: Tue, 19 May 2020 18:48:22 +0800 Subject: [PATCH 01/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=A8=E5=85=AC?= =?UTF-8?q?=E5=BC=8F=E7=9A=84=E8=A1=8C=E6=97=A0=E6=B3=95=E8=A2=AB=E8=AF=BB?= =?UTF-8?q?=E5=8F=96=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/v03/handlers/FormulaRecordHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java index 099b3087..5ac5eeb2 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java +++ b/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; @@ -76,5 +77,6 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig cellMap.put((int)frec.getColumn(), tempCellData); break; } + xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } } From f4a2382a65e5922e4ebe245ba9129ad69ffa0566 Mon Sep 17 00:00:00 2001 From: chi-chi weng <949409306@qq.com> Date: Wed, 20 May 2020 19:17:29 +0800 Subject: [PATCH 02/25] Fastjson has a serious security problem in 1.2.58 Fastjson has a serious security problem in 1.2.58,which will cause RCE https://www.anquanke.com/post/id/199527 https://www.cnblogs.com/tr1ple/p/12348886.html https://github.com/jas502n/fastjson-1.2.58-rce --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 783f1207..471e0f7d 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,7 @@ com.alibaba fastjson - 1.2.58 + 1.2.68 test From 4a2dd0e94b6dfbcb475a0c475c4b4a7661bfa8a5 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 14:48:46 +0800 Subject: [PATCH 03/25] =?UTF-8?q?=E6=92=A4=E9=94=80=E5=88=A0=E9=99=A4`Abst?= =?UTF-8?q?ractMergeStrategy`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../write/merge/AbstractMergeStrategy.java | 56 +++++++++++++++++++ update.md | 4 ++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java diff --git a/pom.xml b/pom.xml index 783f1207..cc83fd25 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba easyexcel - 2.2.3 + 2.2.4 jar easyexcel diff --git a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java new file mode 100644 index 00000000..2a2b7b6d --- /dev/null +++ b/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 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); +} diff --git a/update.md b/update.md index fdb7b140..b0fbc64d 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,7 @@ +# 2.2.4 +* 撤销删除`AbstractMergeStrategy` + + # 2.2.3 * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) * 回退自定义转换器入参为空 From 20454248cf04a3e938596a7e83b2bfc328493c14 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 16:27:03 +0800 Subject: [PATCH 04/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E7=94=A8String=E8=AF=BB=E5=8F=96=E6=95=B0=E5=AD=97=E4=B8=8D?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=A7=91=E5=AD=A6=E8=AE=A1=E6=95=B0=E6=B3=95?= =?UTF-8?q?=20=E9=80=9A=E8=BF=87`useScientificFormat`=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/metadata/AbstractHolder.java | 1 + .../excel/metadata/BasicParameter.java | 15 ++++ .../excel/metadata/GlobalConfiguration.java | 14 ++++ .../metadata/{ => format}/DataFormatter.java | 33 +++++--- .../format/ExcelGeneralNumberFormat.java | 81 +++++++++++++++++++ .../AbstractExcelReaderParameterBuilder.java | 13 +++ .../metadata/holder/AbstractReadHolder.java | 11 +++ .../excel/util/NumberDataFormatterUtils.java | 13 +-- .../metadata/holder/AbstractWriteHolder.java | 4 + .../easyexcel/test/temp/Lock2Test.java | 4 +- update.md | 1 + 11 files changed, 168 insertions(+), 22 deletions(-) rename src/main/java/com/alibaba/excel/metadata/{ => format}/DataFormatter.java (96%) create mode 100644 src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java diff --git a/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java b/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java index 6bfd8252..f7cb1ced 100644 --- a/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java +++ b/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() { diff --git a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java b/src/main/java/com/alibaba/excel/metadata/BasicParameter.java index d00c93a8..5baf5cf5 100644 --- a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java +++ b/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> 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; + } } diff --git a/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java b/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java index 12cc8d31..26f3720f 100644 --- a/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java +++ b/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; + } } diff --git a/src/main/java/com/alibaba/excel/metadata/DataFormatter.java b/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java similarity index 96% rename from src/main/java/com/alibaba/excel/metadata/DataFormatter.java rename to src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java index 7467cd26..0bc70d16 100644 --- a/src/main/java/com/alibaba/excel/metadata/DataFormatter.java +++ b/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; } diff --git a/src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java b/src/main/java/com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java new file mode 100644 index 00000000..cdeb5e85 --- /dev/null +++ b/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 }. + *

+ * 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(); + } + +} diff --git a/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java b/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java index 4e5e3702..29d676cb 100644 --- a/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java @@ -31,6 +31,19 @@ public abstract class AbstractExcelReaderParameterBuilder list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync(); + List list = EasyExcel.read(file).useScientificFormat(false).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); diff --git a/update.md b/update.md index b0fbc64d..a43d3fe7 100644 --- a/update.md +++ b/update.md @@ -1,5 +1,6 @@ # 2.2.4 * 撤销删除`AbstractMergeStrategy` +* 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 # 2.2.3 From 737de9553f6ea2e9b6abadf1d8fc591c31e3b79e Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 16:39:57 +0800 Subject: [PATCH 05/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D07=E7=89=88=E4=BB=85?= =?UTF-8?q?=E6=9C=89=E6=A0=B7=E5=BC=8F=E7=9A=84=E7=A9=BA=E8=A1=8C=20?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=8D=E5=BF=BD=E7=95=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alibaba/excel/analysis/v07/handlers/RowTagHandler.java | 5 ++++- src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java | 4 ++-- update.md | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java index 329b2245..877c6a5f 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java +++ b/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); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 7a2c9d67..2771e580 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -32,9 +32,9 @@ public class Lock2Test { @Test public void test() throws Exception { - File file = TestFileUtil.readUserHomeFile("test/test.xlsx"); + File file = TestFileUtil.readUserHomeFile("test/test2style.xls"); - List list = EasyExcel.read(file).useScientificFormat(false).sheet().headRowNumber(0).doReadSync(); + List list = EasyExcel.read(file).ignoreEmptyRow(true).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); diff --git a/update.md b/update.md index a43d3fe7..51136072 100644 --- a/update.md +++ b/update.md @@ -1,7 +1,7 @@ # 2.2.4 * 撤销删除`AbstractMergeStrategy` * 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 - +* 修复07版仅有样式的空行 默认不忽略的bug # 2.2.3 * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) From 852f0ecacb7552430d40fc0b1c457e561cde4e4d Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 17:23:41 +0800 Subject: [PATCH 06/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA`shee?= =?UTF-8?q?t`=E4=B8=8D=E6=8C=89=E7=85=A7=E9=A1=BA=E5=BA=8F=E5=86=99?= =?UTF-8?q?=E5=85=A5=20=E4=BC=9A=E9=94=99=E8=AF=AF=E7=9A=84bug=20#1332?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/context/WriteContextImpl.java | 19 ++++-- .../metadata/holder/WriteWorkbookHolder.java | 1 + .../easyexcel/test/temp/Lock2Test.java | 2 +- .../easyexcel/test/temp/WriteV33Test.java | 64 +++++++++++++++++++ update.md | 3 + 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 0af631ca..cec99f56 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/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,7 +124,11 @@ public class WriteContextImpl implements WriteContext { private boolean selectSheetFromCache(WriteSheet writeSheet) { writeSheetHolder = null; - if (writeSheet.getSheetNo() != null) { + Integer sheetNo = null; + if (writeSheet.getSheetNo() == null && StringUtils.isEmpty(writeSheet.getSheetName())) { + sheetNo = 0; + } + if (sheetNo != null) { writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(writeSheet.getSheetNo()); } if (writeSheetHolder == null && !StringUtils.isEmpty(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())); + int realSheetNo = writeSheetHolder.getSheetNo(); + // When the add default sort order of appearance + if (WriteTypeEnum.ADD.equals(writeType)) { + currentSheet = createSheet(); + } else { + currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(realSheetNo); + writeSheetHolder + .setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(realSheetNo)); + } } else { // sheet name must not null currentSheet = writeWorkbookHolder.getWorkbook().getSheet(writeSheetHolder.getSheetName()); diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java index be557ebd..8c84f1dc 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java +++ b/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; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 2771e580..88d665ac 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -32,7 +32,7 @@ public class Lock2Test { @Test public void test() throws Exception { - File file = TestFileUtil.readUserHomeFile("test/test2style.xls"); + File file = TestFileUtil.readUserHomeFile("test/test.xlsx"); List list = EasyExcel.read(file).ignoreEmptyRow(true).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java new file mode 100644 index 00000000..ca4f3ba6 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java @@ -0,0 +1,64 @@ +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.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"; + // 这里 指定文件 + ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).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 data(int no) { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + DemoData data = new DemoData(); + data.setString("字符串" + no + "---" + i); + list.add(data); + } + return list; + } + +} diff --git a/update.md b/update.md index 51136072..c27358e6 100644 --- a/update.md +++ b/update.md @@ -2,6 +2,9 @@ * 撤销删除`AbstractMergeStrategy` * 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 * 修复07版仅有样式的空行 默认不忽略的bug +* 写入`sheet`不设置`index`和`name`默认不为0的问题 +* 修复多个`sheet`不按照顺序写入 会错误的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332) + # 2.2.3 * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) From 39b023997a6e1b46013a3230d7b0c056e5a34b7a Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 17:24:00 +0800 Subject: [PATCH 07/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA`shee?= =?UTF-8?q?t`=E4=B8=8D=E6=8C=89=E7=85=A7=E9=A1=BA=E5=BA=8F=E5=86=99?= =?UTF-8?q?=E5=85=A5=20=E4=BC=9A=E9=94=99=E8=AF=AF=E7=9A=84bug=20#1332?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.md b/update.md index c27358e6..6a0083aa 100644 --- a/update.md +++ b/update.md @@ -3,7 +3,7 @@ * 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 * 修复07版仅有样式的空行 默认不忽略的bug * 写入`sheet`不设置`index`和`name`默认不为0的问题 -* 修复多个`sheet`不按照顺序写入 会错误的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332) +* 修复多个`sheet`不按照顺序写入 会乱序的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332) # 2.2.3 From 39ed3a6738a52f512f97594482a031977c87b60b Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 17:25:26 +0800 Subject: [PATCH 08/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA`shee?= =?UTF-8?q?t`=E4=B8=8D=E6=8C=89=E7=85=A7=E9=A1=BA=E5=BA=8F=E5=86=99?= =?UTF-8?q?=E5=85=A5=20=E4=BC=9A=E4=B9=B1=E5=BA=8F=E7=9A=84bug=20#1332?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alibaba/excel/context/WriteContextImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index cec99f56..86ecc208 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -163,14 +163,14 @@ public class WriteContextImpl implements WriteContext { Sheet currentSheet; try { if (writeSheetHolder.getSheetNo() != null) { - int realSheetNo = writeSheetHolder.getSheetNo(); // When the add default sort order of appearance if (WriteTypeEnum.ADD.equals(writeType)) { currentSheet = createSheet(); } else { - currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(realSheetNo); + currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo()); writeSheetHolder - .setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheetAt(realSheetNo)); + .setCachedSheet( + writeWorkbookHolder.getCachedWorkbook().getSheetAt(writeSheetHolder.getSheetNo())); } } else { // sheet name must not null From 2c45fa0b13c85b16500e14e677af862ae1804fe8 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Fri, 22 May 2020 17:59:25 +0800 Subject: [PATCH 09/25] =?UTF-8?q?=E5=86=99=E5=85=A5`sheet`=E4=B8=8D?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE`index`=E5=92=8C`name`=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E4=B8=BA0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/context/WriteContextImpl.java | 2 +- .../easyexcel/test/temp/WriteLargeTest.java | 108 ++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 86ecc208..22ccabf7 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -129,7 +129,7 @@ public class WriteContextImpl implements WriteContext { sheetNo = 0; } if (sheetNo != null) { - writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(writeSheet.getSheetNo()); + writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap().get(sheetNo); } if (writeSheetHolder == null && !StringUtils.isEmpty(writeSheet.getSheetName())) { writeSheetHolder = writeWorkbookHolder.getHasBeenInitializedSheetNameMap().get(writeSheet.getSheetName()); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java new file mode 100644 index 00000000..008d7629 --- /dev/null +++ b/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 data() { + List list = new ArrayList(); + 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; + } +} From e9b904884ee219898afe513c3e2282efc8a62b2a Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 15:34:54 +0800 Subject: [PATCH 10/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9head=E6=98=AFList?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=86=85=E5=AE=B9=E5=8D=95=E5=85=83=E6=A0=BC?= =?UTF-8?q?=E7=9A=84=E6=A0=B7=E5=BC=8F=E4=B8=8D=E7=94=9F=E6=95=88=20#1339?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../style/AbstractCellStyleStrategy.java | 3 +- .../AbstractVerticalCellStyleStrategy.java | 13 +-- .../easyexcel/test/temp/WriteV34Test.java | 86 +++++++++++++++++++ update.md | 1 + 4 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java index 06a596f1..14ad9ce5 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java +++ b/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 cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - if (isHead == null || head == null) { + if (isHead == null) { return; } if (isHead) { diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java index 09903a00..197c5cf8 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java +++ b/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); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java new file mode 100644 index 00000000..3fd3fbcd --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java @@ -0,0 +1,86 @@ +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).head(head()).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板") + .doWrite(data(1)); + } + + + private List> head() { + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add("字符串" + System.currentTimeMillis()); + List head1 = new ArrayList(); + head1.add("数字" + System.currentTimeMillis()); + List head2 = new ArrayList(); + head2.add("日期" + System.currentTimeMillis()); + list.add(head0); + list.add(head1); + list.add(head2); + return list; + } + + private List data(int no) { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + DemoData data = new DemoData(); + data.setString("字符串" + no + "---" + i); + list.add(data); + } + return list; + } + +} diff --git a/update.md b/update.md index 6a0083aa..573c775d 100644 --- a/update.md +++ b/update.md @@ -4,6 +4,7 @@ * 修复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) # 2.2.3 From 98ec9f8080a7e49a49c6f4d65b757881167f9289 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 15:55:06 +0800 Subject: [PATCH 11/25] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=86=99=E5=85=A5`clas?= =?UTF-8?q?s`=E5=92=8C`list`=E5=90=8C=E6=97=B6=E4=BC=A0=E5=85=A5=20`field`?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E4=B8=8D=E4=B8=80=E8=87=B4=E6=8A=A5=E9=94=99?= =?UTF-8?q?=20#1333?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property/ExcelWriteHeadProperty.java | 20 +++++++++++-------- .../easyexcel/test/temp/WriteV34Test.java | 9 +++++++-- update.md | 1 + 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java b/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java index 8fe03497..68ca4107 100644 --- a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java +++ b/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,24 @@ 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 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); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java index 3fd3fbcd..cf815292 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV34Test.java @@ -54,7 +54,7 @@ public class WriteV34Test { new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 - EasyExcel.write(fileName).head(head()).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板") + EasyExcel.write(fileName,DemoData.class).head(head()).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板") .doWrite(data(1)); } @@ -63,13 +63,18 @@ public class WriteV34Test { List> list = new ArrayList>(); List head0 = new ArrayList(); head0.add("字符串" + System.currentTimeMillis()); + head0.add("再找找"); List head1 = new ArrayList(); head1.add("数字" + System.currentTimeMillis()); List head2 = new ArrayList(); head2.add("日期" + System.currentTimeMillis()); + List head3 = new ArrayList(); + head3.add("日期" + System.currentTimeMillis()); list.add(head0); list.add(head1); - list.add(head2); + list.add(head2); list.add(head3); + + return list; } diff --git a/update.md b/update.md index 573c775d..fd61d994 100644 --- a/update.md +++ b/update.md @@ -5,6 +5,7 @@ * 写入`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) +* 新增写入`class`和`list`同时传入 `field`数量不一致报错 [Issue #1333](https://github.com/alibaba/easyexcel/issues/1333) # 2.2.3 From 0de3e57d6ba1ec883e026d48c9bea1f72c271c24 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 16:14:19 +0800 Subject: [PATCH 12/25] =?UTF-8?q?*=20=E4=BF=AE=E5=A4=8D=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E8=A1=A8=E5=A4=B4=E4=B8=8D=E6=98=AF`index=3D0`=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=20=E5=90=88=E5=B9=B6=E5=BC=82=E5=B8=B8=E7=9A=84bug=20?= =?UTF-8?q?#1322?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/write/property/ExcelWriteHeadProperty.java | 6 ++++-- update.md | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java b/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java index 68ca4107..979a7750 100644 --- a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java +++ b/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java @@ -66,7 +66,8 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty { 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."); + 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); @@ -180,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; diff --git a/update.md b/update.md index fd61d994..05d073a6 100644 --- a/update.md +++ b/update.md @@ -6,6 +6,7 @@ * 修复多个`sheet`不按照顺序写入 会乱序的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332) * 修改head是List时,内容单元格的样式不生效 [Issue #1339](https://github.com/alibaba/easyexcel/issues/1339) * 新增写入`class`和`list`同时传入 `field`数量不一致报错 [Issue #1333](https://github.com/alibaba/easyexcel/issues/1333) +* 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322) # 2.2.3 From 84998e9c458db2baee3f72159c2da712dab66f3d Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 16:14:29 +0800 Subject: [PATCH 13/25] =?UTF-8?q?*=20=E4=BF=AE=E5=A4=8D=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E8=A1=A8=E5=A4=B4=E4=B8=8D=E6=98=AF`index=3D0`=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=20=E5=90=88=E5=B9=B6=E5=BC=82=E5=B8=B8=E7=9A=84bug=20?= =?UTF-8?q?#1322?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.md b/update.md index 05d073a6..6abc9416 100644 --- a/update.md +++ b/update.md @@ -6,7 +6,6 @@ * 修复多个`sheet`不按照顺序写入 会乱序的bug [Issue #1332](https://github.com/alibaba/easyexcel/issues/1332) * 修改head是List时,内容单元格的样式不生效 [Issue #1339](https://github.com/alibaba/easyexcel/issues/1339) * 新增写入`class`和`list`同时传入 `field`数量不一致报错 [Issue #1333](https://github.com/alibaba/easyexcel/issues/1333) -* 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322) # 2.2.3 @@ -15,6 +14,7 @@ # 2.2.2 * 修改`sheet`事件未调用的bug +* 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322) # 2.2.1 * 发布正式版 From 58fdceb2c0891e7f0cea579f73cbc6a4e6389719 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 16:31:20 +0800 Subject: [PATCH 14/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dxls=E4=BB=85=E5=85=AC?= =?UTF-8?q?=E5=BC=8F=E8=A1=8C=20=E4=B8=8D=E8=AF=BB=E5=8F=96=E7=9A=84bug=20?= =?UTF-8?q?#1324?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/v03/handlers/FormulaRecordHandler.java | 2 ++ src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java | 4 ++-- update.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java index 099b3087..777bfb35 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java @@ -14,6 +14,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 +44,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 diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 88d665ac..96a0aad9 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -32,9 +32,9 @@ public class Lock2Test { @Test public void test() throws Exception { - File file = TestFileUtil.readUserHomeFile("test/test.xlsx"); + File file = TestFileUtil.readUserHomeFile("test/test4.xlsx"); - List list = EasyExcel.read(file).ignoreEmptyRow(true).sheet().headRowNumber(0).doReadSync(); + List list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); diff --git a/update.md b/update.md index 6abc9416..92b55a28 100644 --- a/update.md +++ b/update.md @@ -5,7 +5,7 @@ * 写入`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) -* 新增写入`class`和`list`同时传入 `field`数量不一致报错 [Issue #1333](https://github.com/alibaba/easyexcel/issues/1333) +* 修复xls仅公式行 不读取的bug [Issue #1324](https://github.com/alibaba/easyexcel/issues/1324) # 2.2.3 From 927f6b410f6e76f8cd967192676dc6bb75a4a837 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 25 May 2020 17:11:52 +0800 Subject: [PATCH 15/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dxls=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E7=AC=AC2=E9=A1=B5=20`NPE`=20=E7=9A=84bug=20?= =?UTF-8?q?#1280?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/v03/handlers/BofRecordHandler.java | 9 +++++---- .../java/com/alibaba/easyexcel/test/temp/Lock2Test.java | 4 ++-- update.md | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java index 66e3ab76..ee559813 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java @@ -22,7 +22,7 @@ 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); @@ -38,14 +38,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); } else { + xlsReadContext.currentSheet(actualReadSheet); xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE); } // Go read the next one diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 96a0aad9..29aa216a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -32,9 +32,9 @@ public class Lock2Test { @Test public void test() throws Exception { - File file = TestFileUtil.readUserHomeFile("test/test4.xlsx"); + File file = TestFileUtil.readUserHomeFile("test/test6.xls"); - List list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync(); + List list = EasyExcel.read(file).sheet(1).headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); diff --git a/update.md b/update.md index 92b55a28..33584c9b 100644 --- a/update.md +++ b/update.md @@ -6,6 +6,7 @@ * 修复多个`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) # 2.2.3 From fdeb31794078057955e615e62c60639208298307 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 16:24:04 +0800 Subject: [PATCH 16/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C=E6=9C=80=E5=90=8E=E4=B8=80?= =?UTF-8?q?=E8=A1=8C=E4=B8=AD=E9=97=B4=E6=9C=89=E7=A9=BA=E8=A1=8C=E4=BC=9A?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=A4=B1=E8=B4=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/write/executor/ExcelWriteFillExecutor.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index 1a42fde1..383d31f9 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -303,7 +303,13 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (fillConfig.getForceNewRow()) { row = cachedSheet.createRow(lastRowIndex); } else { - row = sheet.createRow(lastRowIndex); + // 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); From 13416ab6b09336b954010dd14196eb9a49f49edb Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 16:24:30 +0800 Subject: [PATCH 17/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C=E6=9C=80=E5=90=8E=E4=B8=80?= =?UTF-8?q?=E8=A1=8C=E4=B8=AD=E9=97=B4=E6=9C=89=E7=A9=BA=E8=A1=8C=E4=BC=9A?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=A4=B1=E8=B4=A5=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.md b/update.md index 33584c9b..6635fa4f 100644 --- a/update.md +++ b/update.md @@ -7,7 +7,7 @@ * 修改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 # 2.2.3 * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) From 9d60fa6745aa18a9ebdbd31112f995cf05454e47 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 16:41:53 +0800 Subject: [PATCH 18/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D`includeColumnIndexes`?= =?UTF-8?q?=E4=B8=8D=E5=8C=85=E5=90=AB=E7=AC=AC=E5=88=97=20=E4=BC=9A?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=AF=BC=E5=87=BA=E6=95=B0=E6=8D=AE=E7=9A=84?= =?UTF-8?q?bug=20#1346?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/metadata/property/ExcelHeadProperty.java | 9 ++++----- .../excel/write/executor/ExcelWriteAddExecutor.java | 1 + update.md | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java index 34109adc..5a035772 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/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 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; } } diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java index d25ee941..728703ef 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/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); diff --git a/update.md b/update.md index 6635fa4f..95140c02 100644 --- a/update.md +++ b/update.md @@ -8,6 +8,7 @@ * 修复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) # 2.2.3 * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) From cf40b873bd77425a4b358dc4f4bd5d3f0b5ddb28 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 17:25:15 +0800 Subject: [PATCH 19/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D`@NumberFormat`?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E8=BD=AC=E6=8D=A2double=E6=97=B6=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E4=BC=9A=E4=B8=A2=E5=A4=B1=E7=B2=BE=E5=BA=A6=20#1306?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alibaba/excel/context/WriteContextImpl.java | 4 ++-- .../java/com/alibaba/excel/util/NumberUtils.java | 1 + .../easyexcel/test/temp/FillTempTest.java | 16 +++++++++++----- .../alibaba/easyexcel/test/temp/Lock2Test.java | 14 ++++++++++++-- .../alibaba/easyexcel/test/temp/LockData.java | 5 ++++- .../easyexcel/test/temp/LockDataListener.java | 6 +++--- .../easyexcel/test/temp/WriteV33Test.java | 5 ++++- .../easyexcel/test/temp/simple/Wirte.java | 1 + .../easyexcel/test/temp/simple/WriteData.java | 4 +++- update.md | 1 + 10 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 22ccabf7..9a07d353 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -124,8 +124,8 @@ public class WriteContextImpl implements WriteContext { private boolean selectSheetFromCache(WriteSheet writeSheet) { writeSheetHolder = null; - Integer sheetNo = null; - if (writeSheet.getSheetNo() == null && StringUtils.isEmpty(writeSheet.getSheetName())) { + Integer sheetNo = writeSheet.getSheetNo(); + if (sheetNo == null && StringUtils.isEmpty(writeSheet.getSheetName())) { sheetNo = 0; } if (sheetNo != null) { diff --git a/src/main/java/com/alibaba/excel/util/NumberUtils.java b/src/main/java/com/alibaba/excel/util/NumberUtils.java index e687fbfc..4257ff44 100644 --- a/src/main/java/com/alibaba/excel/util/NumberUtils.java +++ b/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); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java index 0ed625da..7917e063 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java +++ b/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 map = new HashMap(); map.put("date", "2019年10月9日13:28:28"); map.put("total", 1000); - excelWriter.fill(map, writeSheet); + excelWriter.fill(map, writeSheet0); + excelWriter.finish(); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 29aa216a..0dcef53c 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -28,6 +28,7 @@ import com.alibaba.fastjson.JSON; **/ @Ignore public class Lock2Test { + private static final Logger LOGGER = LoggerFactory.getLogger(Lock2Test.class); @Test @@ -41,6 +42,15 @@ public class Lock2Test { } } + @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 = diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/LockData.java b/src/test/java/com/alibaba/easyexcel/test/temp/LockData.java index 2e1ed7b0..14fa65e3 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/LockData.java +++ b/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; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java index d5891115..64cce8db 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java +++ b/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> { +public class LockDataListener extends AnalysisEventListener { private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class); /** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 5; - List> list = new ArrayList>(); + List list = new ArrayList(); @Override - public void invoke(Map data, AnalysisContext context) { + public void invoke(LockData data, AnalysisContext context) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); list.add(data); if (list.size() >= BATCH_COUNT) { diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java index ca4f3ba6..f8db7f9c 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java @@ -17,6 +17,7 @@ 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; @@ -37,8 +38,10 @@ public class WriteV33Test { 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).build(); + 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(); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java index e31e74b1..ffabd105 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java +++ b/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; diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java index b9de59b9..2b25bb0a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java +++ b/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; } diff --git a/update.md b/update.md index 95140c02..5374449a 100644 --- a/update.md +++ b/update.md @@ -9,6 +9,7 @@ * 修复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) From 11d17024315c526d2fdd97de61e0dfc75dcfb22f Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 18:21:24 +0800 Subject: [PATCH 20/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9demo=20=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=8A=A0=E4=B8=8Afinal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../easyexcel/test/demo/read/ReadTest.java | 44 ++++-- .../easyexcel/test/demo/write/WriteTest.java | 136 +++++++++++------- 2 files changed, 111 insertions(+), 69 deletions(-) diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java index edcf8a0b..ea011b31 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java +++ b/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(); + } + } } /** diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java index 7139fa8f..ee9ce2f6 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java +++ b/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 { + /** * 最简单的写 *

@@ -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 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 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 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 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 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 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 { /** * 自动列宽(不太精确) *

- * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 - * {@link LongestMatchColumnWidthStyleStrategy}重新实现. + * 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 {@link LongestMatchColumnWidthStyleStrategy}重新实现. *

* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。 * From 5c794ec669ca16ac0f2fc5974885efcd91ffb70d Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 18:36:09 +0800 Subject: [PATCH 21/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dxls=E4=BB=85=E5=85=AC?= =?UTF-8?q?=E5=BC=8F=E8=A1=8C=20=E4=B8=8D=E8=AF=BB=E5=8F=96=E7=9A=84bug=20?= =?UTF-8?q?#1324?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/v03/handlers/FormulaRecordHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java index bc01c95e..f78d4102 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java @@ -79,6 +79,5 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig cellMap.put((int)frec.getColumn(), tempCellData); break; } - xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } } From 897812008d0e806eca26e5f607432e222320adc8 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 18:54:18 +0800 Subject: [PATCH 22/25] =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 + .../executor/ExcelWriteFillExecutor.java | 70 +++++++++++-------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 55f5f6d7..be70e6bf 100644 --- a/pom.xml +++ b/pom.xml @@ -162,6 +162,8 @@ com/alibaba/excel/event/AnalysisEventListener.java com/alibaba/excel/metadata/DataFormatter.java com/alibaba/excel/util/DateUtils.java + com/alibaba/excel/metadata/format/DataFormatter.java + com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index 383d31f9..29a037a6 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -295,34 +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 { - // 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); - } - } - 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 collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag); if (collectionFieldStyleMap == null) { @@ -340,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; From bffb08d97cb49f2b231512570d87d0ecc4471724 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 20:06:36 +0800 Subject: [PATCH 23/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E8=A1=A8=E6=A0=BC=E4=BB=A3=E7=A0=81=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alibaba/excel/analysis/v03/XlsSaxAnalyser.java | 2 +- .../analysis/v03/handlers/BofRecordHandler.java | 6 +++--- .../metadata/holder/xls/XlsReadSheetHolder.java | 12 ------------ .../metadata/holder/xls/XlsReadWorkbookHolder.java | 13 +++++++++++++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index bda4f53d..e1c19be6 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/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; diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java index ee559813..3e6713c4 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java @@ -26,6 +26,7 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder(); if (br.getType() == BOFRecord.TYPE_WORKBOOK) { xlsReadWorkbookHolder.setReadSheetIndex(null); + xlsReadWorkbookHolder.setIgnoreRecord(Boolean.FALSE); return; } if (br.getType() != BOFRecord.TYPE_WORKSHEET) { @@ -44,10 +45,9 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { ReadSheet readSheet = SheetUtils.match(actualReadSheet, xlsReadContext); if (readSheet != null) { xlsReadContext.currentSheet(readSheet); - xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.FALSE); + xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.FALSE); } else { - xlsReadContext.currentSheet(actualReadSheet); - xlsReadContext.xlsReadSheetHolder().setIgnoreRecord(Boolean.TRUE); + xlsReadContext.xlsReadWorkbookHolder().setIgnoreRecord(Boolean.TRUE); } // Go read the next one xlsReadWorkbookHolder.setReadSheetIndex(xlsReadWorkbookHolder.getReadSheetIndex() + 1); diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java index d0171ffc..1d12ab6c 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadSheetHolder.java +++ b/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 ReadRowHolder. */ 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(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; diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java index 70c1c03a..a8c86a75 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/xls/XlsReadWorkbookHolder.java +++ b/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; + } } From 96be4346ca5d4284f561d454926503c89ad8f589 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 20:11:05 +0800 Subject: [PATCH 24/25] =?UTF-8?q?=E6=9C=89=E6=A8=A1=E6=9D=BF=E8=AF=BB?= =?UTF-8?q?=E5=86=99=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/alibaba/excel/context/WriteContextImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 9a07d353..c1f89f02 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -164,7 +164,7 @@ public class WriteContextImpl implements WriteContext { try { if (writeSheetHolder.getSheetNo() != null) { // When the add default sort order of appearance - if (WriteTypeEnum.ADD.equals(writeType)) { + if (WriteTypeEnum.ADD.equals(writeType) && writeWorkbookHolder.getTempTemplateInputStream() == null) { currentSheet = createSheet(); } else { currentSheet = writeWorkbookHolder.getWorkbook().getSheetAt(writeSheetHolder.getSheetNo()); From 4cbdf679d5031b3cc5ee11afc49fe05c4891a959 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 9 Jun 2020 21:06:02 +0800 Subject: [PATCH 25/25] =?UTF-8?q?=E6=96=B0=E5=A2=9EQQ2=E7=BE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f1a12fe..89bae018 100644 --- a/README.md +++ b/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)