diff --git a/quickstart.md b/quickstart.md index ffb1f4b..c9fdd7d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -21,7 +21,7 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/demo/read/ReadTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java) * [最简单的读](#simpleRead) * [指定列的下标或者列名](#indexOrNameRead) -* [读多个sheet](#repeatedRead) +* [读多个或者全部sheet](#repeatedRead) * [日期、数字或者自定义格式转换](#converterRead) * [多行头](#complexHeaderRead) * [同步的返回](#synchronousRead) @@ -180,7 +180,7 @@ public class IndexOrNameData { ##### 代码 ```java /** - * 读多个sheet,这里注意一个sheet不能读取多次,多次读取需要重新读取文件 + * 读多个或者全部sheet,这里注意一个sheet不能读取多次,多次读取需要重新读取文件 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

@@ -190,24 +190,21 @@ public class IndexOrNameData { */ @Test public void repeatedRead() { - // 方法1 如果 sheet1 sheet2 都是同一数据 监听器和头 都写到最外层 String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; - ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build(); - ReadSheet readSheet1 = EasyExcel.readSheet(0).build(); - ReadSheet readSheet2 = EasyExcel.readSheet(1).build(); - excelReader.read(readSheet1); - excelReader.read(readSheet2); - // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的 - excelReader.finish(); + // 读取全部sheet + // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写 + EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll(); - // 方法2 如果 sheet1 sheet2 数据不一致的话 + // 读取部分sheet fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; - excelReader = EasyExcel.read(fileName).build(); + ExcelReader excelReader = EasyExcel.read(fileName).build(); // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener - readSheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); - readSheet2 = EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); - excelReader.read(readSheet1); - excelReader.read(readSheet2); + 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(); } @@ -518,6 +515,11 @@ public class DemoData { private Date date; @ExcelProperty("数字标题") private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; } ``` ##### 代码 diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java index 808ee56..46f2587 100644 --- a/src/main/java/com/alibaba/excel/ExcelReader.java +++ b/src/main/java/com/alibaba/excel/ExcelReader.java @@ -2,6 +2,7 @@ package com.alibaba.excel; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.slf4j.Logger; @@ -147,27 +148,41 @@ public class ExcelReader { /** * Parse all sheet content by default + * + * @deprecated lease use {@link #readAll()} */ + @Deprecated public void read() { - ExcelReadExecutor excelReadExecutor = excelAnalyser.excelExecutor(); - if (excelReadExecutor.sheetList().isEmpty()) { - LOGGER.warn("Excel doesn't have any sheets."); - return; - } - for (ReadSheet readSheet : excelReadExecutor.sheetList()) { - read(readSheet); - } + readAll(); + } + + /*** + * Parse all sheet content by default + */ + public void readAll() { + checkFinished(); + excelAnalyser.analysis(null, Boolean.TRUE); } /** - * Parse the specified sheet,SheetNo start from 1 + * Parse the specified sheet,SheetNo start from 0 * * @param readSheet * Read sheet */ - public ExcelReader read(ReadSheet readSheet) { + public ExcelReader read(ReadSheet... readSheet) { + return read(Arrays.asList(readSheet)); + } + + /** + * Read multiple sheets. + * + * @param readSheetList + * @return + */ + public ExcelReader read(List readSheetList) { checkFinished(); - excelAnalyser.analysis(readSheet); + excelAnalyser.analysis(readSheetList, Boolean.FALSE); return this; } diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 4800f84..65a99fe 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -138,17 +138,7 @@ public class ExcelWriter { * @return this current writer */ public ExcelWriter write(List data, WriteSheet writeSheet) { - return write(data, writeSheet, (WriteTable)null); - } - - - public ExcelWriter write(List data, WriteSheet writeSheet, String password) { - return write(data, writeSheet, null, password); - } - - private ExcelWriter write(List data, WriteSheet writeSheet, WriteTable writeTable, String password) { - excelBuilder.addContent(data, writeSheet, writeTable, password); - return this; + return write(data, writeSheet, null); } /** diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java index 6d014bb..83de6ac 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java @@ -1,5 +1,7 @@ package com.alibaba.excel.analysis; +import java.util.List; + import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.metadata.ReadSheet; @@ -10,12 +12,14 @@ import com.alibaba.excel.read.metadata.ReadSheet; */ public interface ExcelAnalyser { /** - * parse one sheet + * parse the sheet * - * @param readSheet - * sheet to read + * @param readSheetList + * Which sheets you need to read. + * @param readAll + * The readSheetList parameter is ignored, and all sheets are read. */ - void analysis(ReadSheet readSheet); + void analysis(List readSheetList, Boolean readAll); /** * Complete the entire read file.Release the cache and close stream diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index a924b21..3b4754d 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -1,8 +1,13 @@ package com.alibaba.excel.analysis; +import java.io.FileInputStream; import java.io.InputStream; +import java.util.List; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.IOUtils; @@ -19,7 +24,9 @@ import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.FileUtils; +import com.alibaba.excel.util.StringUtils; /** * @author jipengfei @@ -64,7 +71,8 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { InputStream decryptedStream = null; try { decryptedStream = - DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), null); + DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(), + analysisContext.readWorkbookHolder().getPassword()); excelReadExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream); return; } finally { @@ -74,6 +82,9 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { poifsFileSystem.close(); } } + if (analysisContext.readWorkbookHolder().getPassword() != null) { + Biff8EncryptionKey.setCurrentUserPassword(analysisContext.readWorkbookHolder().getPassword()); + } excelReadExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem); break; case XLSX: @@ -84,17 +95,24 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { } @Override - public void analysis(ReadSheet readSheet) { + public void analysis(List readSheetList, Boolean readAll) { try { - analysisContext.currentSheet(excelReadExecutor, readSheet); + if (!readAll && CollectionUtils.isEmpty(readSheetList)) { + throw new IllegalArgumentException("Specify at least one read sheet."); + } try { - excelReadExecutor.execute(); + excelReadExecutor.execute(readSheetList, readAll); } catch (ExcelAnalysisStopException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Custom stop!"); } } - analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext); + // The last sheet is read + if (excelReadExecutor instanceof XlsSaxAnalyser) { + if (analysisContext.readSheetHolder() != null) { + analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext); + } + } } catch (RuntimeException e) { finish(); throw e; @@ -110,6 +128,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { return; } ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder(); + try { if (readWorkbookHolder.getReadCache() != null) { readWorkbookHolder.getReadCache().destroy(); @@ -146,6 +165,16 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { } catch (Throwable t) { throwCanNotCloseIo(t); } + + clearEncrypt03(); + } + + private void clearEncrypt03() { + if (StringUtils.isEmpty(analysisContext.readWorkbookHolder().getPassword()) + || !ExcelTypeEnum.XLS.equals(analysisContext.readWorkbookHolder().getExcelType())) { + return; + } + Biff8EncryptionKey.setCurrentUserPassword(null); } private void throwCanNotCloseIo(Throwable t) { diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java b/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java index 515eeb9..10ced98 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelReadExecutor.java @@ -19,8 +19,12 @@ public interface ExcelReadExecutor { List sheetList(); /** - * Read sheet + * Read the sheet. + * + * @param readSheetList + * Which sheets you need to read. + * @param readAll + * The readSheetList parameter is ignored, and all sheets are read. */ - void execute(); - + void execute(List readSheetList, Boolean readAll); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java index 62d5517..6f8e716 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsListSheetListener.java @@ -10,7 +10,6 @@ import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; import org.apache.poi.hssf.eventusermodel.HSSFListener; import org.apache.poi.hssf.eventusermodel.HSSFRequest; import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener; -import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -27,13 +26,14 @@ import com.alibaba.excel.read.metadata.ReadSheet; public class XlsListSheetListener implements HSSFListener { private POIFSFileSystem poifsFileSystem; private List sheetList; - private XlsRecordHandler bofRecordHandler; + private BofRecordHandler bofRecordHandler; public XlsListSheetListener(AnalysisContext analysisContext, POIFSFileSystem poifsFileSystem) { this.poifsFileSystem = poifsFileSystem; sheetList = new ArrayList(); - bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false); + bofRecordHandler = new BofRecordHandler(analysisContext, sheetList, false, false); bofRecordHandler.init(); + bofRecordHandler.init(null, true); } @Override 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 129b74e..21977a4 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -60,6 +60,8 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(XlsSaxAnalyser.class); private POIFSFileSystem poifsFileSystem; + private Boolean readAll; + private List readSheetList; private int lastRowNumber; private int lastColumnNumber; /** @@ -91,7 +93,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { } @Override - public void execute() { + public void execute(List readSheetList, Boolean readAll) { + this.readAll = readAll; + this.readSheetList = readSheetList; MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this); formatListener = new FormatTrackingHSSFListener(listener); workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener); @@ -195,9 +199,9 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { // The table has been counted and there are no duplicate statistics if (sheets == null) { sheets = new ArrayList(); - recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false)); + recordHandlers.add(new BofRecordHandler(analysisContext, sheets, false, true)); } else { - recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true)); + recordHandlers.add(new BofRecordHandler(analysisContext, sheets, true, true)); } recordHandlers.add(new FormulaRecordHandler(stubWorkbook, formatListener)); recordHandlers.add(new LabelRecordHandler()); @@ -211,6 +215,10 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { for (XlsRecordHandler x : recordHandlers) { x.init(); + if (x instanceof BofRecordHandler) { + BofRecordHandler bofRecordHandler = (BofRecordHandler)x; + bofRecordHandler.init(readSheetList, readAll); + } } } } 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 d6a93a5..3a86294 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 @@ -10,6 +10,7 @@ import org.apache.poi.hssf.record.Record; import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.util.SheetUtils; /** * Record handler @@ -21,13 +22,18 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { private BoundSheetRecord[] orderedBsrs; private int sheetIndex; private List sheets; + private Boolean readAll; + private List readSheetList; private AnalysisContext context; private boolean alreadyInit; + private boolean needInitSheet; - public BofRecordHandler(AnalysisContext context, List sheets, boolean alreadyInit) { + public BofRecordHandler(AnalysisContext context, List sheets, boolean alreadyInit, + boolean needInitSheet) { this.context = context; this.sheets = sheets; this.alreadyInit = alreadyInit; + this.needInitSheet = needInitSheet; } @Override @@ -45,15 +51,34 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { if (orderedBsrs == null) { orderedBsrs = BoundSheetRecord.orderByBofPosition(boundSheetRecords); } + String sheetName = orderedBsrs[sheetIndex].getSheetname(); + // Find the currently read sheet + ReadSheet readSheet = null; if (!alreadyInit) { - ReadSheet readSheet = new ReadSheet(sheetIndex, orderedBsrs[sheetIndex].getSheetname()); + readSheet = new ReadSheet(sheetIndex, sheetName); sheets.add(readSheet); } - if (context.readSheetHolder() != null) { - if (sheetIndex == context.readSheetHolder().getSheetNo()) { + if (needInitSheet) { + if (readSheet == null) { + for (ReadSheet sheet : sheets) { + if (sheet.getSheetNo() == sheetIndex) { + readSheet = sheet; + break; + } + } + } + assert readSheet != null : "Can't find the sheet."; + context.readWorkbookHolder().setIgnoreRecord03(Boolean.TRUE); + // Copy the parameter to the current sheet + readSheet = SheetUtils.match(readSheet, readSheetList, readAll, + context.readWorkbookHolder().getGlobalConfiguration()); + if (readSheet != null) { + if (readSheet.getSheetNo() != 0) { + // Prompt for the end of the previous form read + context.readSheetHolder().notifyAfterAllAnalysed(context); + } + context.currentSheet(readSheet); context.readWorkbookHolder().setIgnoreRecord03(Boolean.FALSE); - } else { - context.readWorkbookHolder().setIgnoreRecord03(Boolean.TRUE); } } sheetIndex++; @@ -71,6 +96,11 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { } } + public void init(List readSheetList, Boolean readAll) { + this.readSheetList = readSheetList; + this.readAll = readAll; + } + @Override public int getOrder() { return 0; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java index 7a34e6c..dd468b4 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -15,6 +15,7 @@ import javax.xml.parsers.SAXParserFactory; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFRelation; @@ -33,6 +34,8 @@ import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.FileUtils; +import com.alibaba.excel.util.SheetUtils; +import com.alibaba.excel.util.StringUtils; /** * @@ -172,9 +175,16 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { } @Override - public void execute() { - parseXmlSource(sheetMap.get(analysisContext.readSheetHolder().getSheetNo()), - new XlsxRowHandler(analysisContext, stylesTable)); + public void execute(List readSheetList, Boolean readAll) { + for (ReadSheet readSheet : sheetList) { + readSheet = SheetUtils.match(readSheet, readSheetList, readAll, + analysisContext.readWorkbookHolder().getGlobalConfiguration()); + if (readSheet != null) { + analysisContext.currentSheet(readSheet); + parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(analysisContext, stylesTable)); + // The last sheet is read + analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext); + } + } } - } diff --git a/src/main/java/com/alibaba/excel/annotation/ExcelIgnoreUnannotated.java b/src/main/java/com/alibaba/excel/annotation/ExcelIgnoreUnannotated.java new file mode 100644 index 0000000..1475ad3 --- /dev/null +++ b/src/main/java/com/alibaba/excel/annotation/ExcelIgnoreUnannotated.java @@ -0,0 +1,18 @@ +package com.alibaba.excel.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Ignore all unannotated fields. + * + * @author Jiaju Zhuang + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ExcelIgnoreUnannotated { +} diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContext.java b/src/main/java/com/alibaba/excel/context/AnalysisContext.java index 5c918f2..f44c2b3 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContext.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContext.java @@ -22,12 +22,10 @@ public interface AnalysisContext { /** * Select the current table * - * @param excelReadExecutor - * Excel file Executor * @param readSheet * sheet to read */ - void currentSheet(ExcelReadExecutor excelReadExecutor, ReadSheet readSheet); + void currentSheet(ReadSheet readSheet); /** * All information about the workbook you are currently working on diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index 999aa50..e5ded50 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -5,8 +5,6 @@ import java.io.InputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.analysis.ExcelReadExecutor; -import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.read.metadata.ReadSheet; @@ -16,7 +14,6 @@ import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.util.StringUtils; /** * @@ -53,13 +50,9 @@ public class AnalysisContextImpl implements AnalysisContext { } @Override - public void currentSheet(ExcelReadExecutor excelReadExecutor, ReadSheet readSheet) { - if (readSheet == null) { - throw new IllegalArgumentException("Sheet argument cannot be null."); - } + public void currentSheet(ReadSheet readSheet) { readSheetHolder = new ReadSheetHolder(readSheet, readWorkbookHolder); currentReadHolder = readSheetHolder; - selectSheet(excelReadExecutor); if (readWorkbookHolder.getHasReadSheet().contains(readSheetHolder.getSheetNo())) { throw new ExcelAnalysisException("Cannot read sheet repeatedly."); } @@ -69,54 +62,6 @@ public class AnalysisContextImpl implements AnalysisContext { } } - private void selectSheet(ExcelReadExecutor excelReadExecutor) { - if (excelReadExecutor instanceof XlsxSaxAnalyser) { - selectSheet07(excelReadExecutor); - } else { - selectSheet03(); - } - } - - private void selectSheet03() { - if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) { - return; - } - if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) { - LOGGER.warn("Excel 2003 does not support matching sheets by name, defaults to the first one."); - } - readSheetHolder.setSheetNo(0); - } - - private void selectSheet07(ExcelReadExecutor excelReadExecutor) { - if (readSheetHolder.getSheetNo() != null && readSheetHolder.getSheetNo() >= 0) { - for (ReadSheet readSheetExcel : excelReadExecutor.sheetList()) { - if (readSheetExcel.getSheetNo().equals(readSheetHolder.getSheetNo())) { - readSheetHolder.setSheetName(readSheetExcel.getSheetName()); - return; - } - } - throw new ExcelAnalysisException("Can not find sheet:" + readSheetHolder.getSheetNo()); - } - if (!StringUtils.isEmpty(readSheetHolder.getSheetName())) { - for (ReadSheet readSheetExcel : excelReadExecutor.sheetList()) { - String sheetName = readSheetExcel.getSheetName(); - if (sheetName == null) { - continue; - } - if (readSheetHolder.globalConfiguration().getAutoTrim()) { - sheetName = sheetName.trim(); - } - if (sheetName.equals(readSheetHolder.getSheetName())) { - readSheetHolder.setSheetNo(readSheetExcel.getSheetNo()); - return; - } - } - } - ReadSheet readSheetExcel = excelReadExecutor.sheetList().get(0); - readSheetHolder.setSheetNo(readSheetExcel.getSheetNo()); - readSheetHolder.setSheetName(readSheetExcel.getSheetName()); - } - @Override public ReadWorkbookHolder readWorkbookHolder() { return readWorkbookHolder; diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java index a5e6d58..c6e85c9 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContext.java +++ b/src/main/java/com/alibaba/excel/context/WriteContext.java @@ -69,18 +69,6 @@ public interface WriteContext { */ void finish(); - /** - * isEncrypt - * @return - */ - boolean isEncrypt(); - - /** - * setPassword - * @param password - * @return - */ - void setPassword(String password); /** * Current sheet diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 8972424..ffacd52 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -1,15 +1,27 @@ package com.alibaba.excel.context; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.StringUtils; + +import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.InputStream; import java.io.OutputStream; +import java.security.GeneralSecurityException; import java.util.Map; +import java.util.UUID; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.EncryptionMode; import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.DocumentOutputStream; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -120,7 +132,6 @@ public class WriteContextImpl implements WriteContext { WriteHandlerUtils.beforeSheetCreate(this); // Initialization current sheet initSheet(writeType); - WriteHandlerUtils.afterSheetCreate(this); } private void initCurrentSheetHolder(WriteSheet writeSheet) { @@ -147,6 +158,7 @@ public class WriteContextImpl implements WriteContext { writeSheetHolder.setCachedSheet(currentSheet); } writeSheetHolder.setSheet(currentSheet); + WriteHandlerUtils.afterSheetCreate(this); if (WriteTypeEnum.ADD.equals(writeType)) { // Initialization head initHead(writeSheetHolder.excelWriteHeadProperty()); @@ -249,18 +261,23 @@ public class WriteContextImpl implements WriteContext { if (writeWorkbookHolder == null) { return; } - try { - writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); - if (isEncrypt()){ - LOGGER.debug("start encrypt"); - encrypt(writeWorkbookHolder); - LOGGER.debug("finish encrypt"); - } - writeWorkbookHolder.getWorkbook().close(); + boolean isOutputStreamEncrypt = false; + try { + isOutputStreamEncrypt = doOutputStreamEncrypt07(); } catch (Throwable t) { throwCanNotCloseIo(t); } + + if (!isOutputStreamEncrypt) { + try { + writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); + writeWorkbookHolder.getWorkbook().close(); + } catch (Throwable t) { + throwCanNotCloseIo(t); + } + } + try { Workbook workbook = writeWorkbookHolder.getWorkbook(); if (workbook instanceof SXSSFWorkbook) { @@ -269,6 +286,7 @@ public class WriteContextImpl implements WriteContext { } catch (Throwable t) { throwCanNotCloseIo(t); } + try { if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) { writeWorkbookHolder.getOutputStream().close(); @@ -276,6 +294,15 @@ public class WriteContextImpl implements WriteContext { } catch (Throwable t) { throwCanNotCloseIo(t); } + + if (!isOutputStreamEncrypt) { + try { + doFileEncrypt07(); + } catch (Throwable t) { + throwCanNotCloseIo(t); + } + } + try { if (writeWorkbookHolder.getTempTemplateInputStream() != null) { writeWorkbookHolder.getTempTemplateInputStream().close(); @@ -283,21 +310,14 @@ public class WriteContextImpl implements WriteContext { } catch (Throwable t) { throwCanNotCloseIo(t); } + + clearEncrypt03(); + if (LOGGER.isDebugEnabled()) { LOGGER.debug("Finished write."); } } - @Override - public boolean isEncrypt() { - return !StringUtils.isEmpty(writeWorkbookHolder.getPassword()); - } - - @Override - public void setPassword(String password) { - writeWorkbookHolder.setPassword(password); - } - private void throwCanNotCloseIo(Throwable t) { throw new ExcelGenerateException("Can not close IO", t); } @@ -322,28 +342,94 @@ public class WriteContextImpl implements WriteContext { return writeWorkbookHolder.getWorkbook(); } + private void clearEncrypt03() { + if (StringUtils.isEmpty(writeWorkbookHolder.getPassword()) + || !ExcelTypeEnum.XLS.equals(writeWorkbookHolder.getExcelType())) { + return; + } + Biff8EncryptionKey.setCurrentUserPassword(null); + } + /** - * do encrypt - * @param writeWorkbookHolder + * To encrypt */ - private void encrypt(WriteWorkbookHolder writeWorkbookHolder){ + private boolean doOutputStreamEncrypt07() throws Exception { + if (StringUtils.isEmpty(writeWorkbookHolder.getPassword()) + || !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) { + return false; + } + if (writeWorkbookHolder.getFile() != null) { + return false; + } + File tempXlsx = FileUtils.createTmpFile(UUID.randomUUID().toString() + ".xlsx"); + FileOutputStream tempFileOutputStream = new FileOutputStream(tempXlsx); try { - POIFSFileSystem fs = new POIFSFileSystem(); - EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard); - - Encryptor enc = info.getEncryptor(); - enc.confirmPassword(writeWorkbookHolder.getPassword()); - - OPCPackage opc = OPCPackage.open(writeWorkbookHolder.getFile(), PackageAccess.READ_WRITE); - OutputStream os = enc.getDataStream(fs); - opc.save(os); - opc.close(); - //write the encrypted file back to the stream - FileOutputStream fos = new FileOutputStream(writeWorkbookHolder.getFile()); - fs.writeFilesystem(fos); - fos.close(); - } catch (Exception e) { - e.printStackTrace(); + writeWorkbookHolder.getWorkbook().write(tempFileOutputStream); + } finally { + try { + writeWorkbookHolder.getWorkbook().close(); + tempFileOutputStream.close(); + } catch (Exception e) { + if (!tempXlsx.delete()) { + throw new ExcelGenerateException("Can not delete temp File!"); + } + throw e; + } + } + POIFSFileSystem fileSystem = null; + try { + fileSystem = openFileSystemAndEncrypt(tempXlsx); + fileSystem.writeFilesystem(writeWorkbookHolder.getOutputStream()); + } finally { + if (fileSystem != null) { + fileSystem.close(); + } + if (!tempXlsx.delete()) { + throw new ExcelGenerateException("Can not delete temp File!"); + } + } + return true; + } + + /** + * To encrypt + */ + private void doFileEncrypt07() throws Exception { + if (StringUtils.isEmpty(writeWorkbookHolder.getPassword()) + || !ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) { + return; + } + if (writeWorkbookHolder.getFile() == null) { + return; + } + FileOutputStream fileOutputStream = null; + POIFSFileSystem fileSystem = null; + try { + fileSystem = openFileSystemAndEncrypt(writeWorkbookHolder.getFile()); + fileOutputStream = new FileOutputStream(writeWorkbookHolder.getFile()); + fileSystem.writeFilesystem(fileOutputStream); + } finally { + if (fileOutputStream != null) { + fileOutputStream.close(); + } + if (fileSystem != null) { + fileSystem.close(); + } + } + } + + private POIFSFileSystem openFileSystemAndEncrypt(File file) throws Exception { + POIFSFileSystem fileSystem = new POIFSFileSystem(); + Encryptor encryptor = new EncryptionInfo(EncryptionMode.standard).getEncryptor(); + encryptor.confirmPassword(writeWorkbookHolder.getPassword()); + OPCPackage opcPackage = null; + try { + opcPackage = OPCPackage.open(file, PackageAccess.READ_WRITE); + OutputStream outputStream = encryptor.getDataStream(fileSystem); + opcPackage.save(outputStream); + } finally { + opcPackage.close(); } + return fileSystem; } } diff --git a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java b/src/main/java/com/alibaba/excel/metadata/BasicParameter.java index 89d7851..40bffe6 100644 --- a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java +++ b/src/main/java/com/alibaba/excel/metadata/BasicParameter.java @@ -74,4 +74,5 @@ public class BasicParameter { public void setUse1904windowing(Boolean use1904windowing) { this.use1904windowing = use1904windowing; } + } 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 4bffce6..6921161 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -13,9 +13,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; import com.alibaba.excel.annotation.format.NumberFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.converters.AutoConverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.HeadKindEnum; @@ -120,6 +122,8 @@ public class ExcelHeadProperty { tempClass = tempClass.getSuperclass(); } + ExcelIgnoreUnannotated excelIgnoreUnannotated = + (ExcelIgnoreUnannotated)headClazz.getAnnotation(ExcelIgnoreUnannotated.class); // Screening of field List defaultFieldList = new ArrayList(); Map customFiledMap = new TreeMap(); @@ -130,7 +134,9 @@ public class ExcelHeadProperty { continue; } ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); - if (excelProperty == null && convertAllFiled != null && !convertAllFiled) { + boolean noExcelProperty = excelProperty == null + && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null); + if (noExcelProperty) { ignoreMap.put(field.getName(), field); continue; } diff --git a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java index 2b5bcd6..340548b 100644 --- a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java @@ -222,10 +222,28 @@ public class ExcelReaderBuilder { return this; } + /** + * Whether the encryption + * + * @param password + * @return + */ + public ExcelReaderBuilder password(String password) { + readWorkbook.setPassword(password); + return this; + } + public ExcelReader build() { return new ExcelReader(readWorkbook); } + public ExcelReader doReadAll() { + ExcelReader excelReader = build(); + excelReader.readAll(); + excelReader.finish(); + return excelReader; + } + public ExcelReaderSheetBuilder sheet() { return sheet(null, null); } diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java b/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java index f3a3a7b..5b6f8de 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java @@ -42,6 +42,19 @@ public class ReadSheet extends ReadBasicParameter { this.sheetName = sheetName; } + public void copyBasicParameter(ReadSheet other) { + if (other == null) { + return; + } + this.setHeadRowNumber(other.getHeadRowNumber()); + this.setCustomReadListenerList(other.getCustomReadListenerList()); + this.setHead(other.getHead()); + this.setClazz(other.getClazz()); + this.setCustomConverterList(other.getCustomConverterList()); + this.setAutoTrim(other.getAutoTrim()); + this.setUse1904windowing(other.getUse1904windowing()); + } + @Override public String toString() { return "ReadSheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString(); diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java index b21cdb8..3a873da 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java @@ -59,6 +59,10 @@ public class ReadWorkbook extends ReadBasicParameter { * Select the cache.Default use {@link com.alibaba.excel.cache.selector.SimpleReadCacheSelector} */ private ReadCacheSelector readCacheSelector; + /** + * Whether the encryption + */ + private String password; /** * The default is all excel objects.Default is true. *

@@ -164,4 +168,12 @@ public class ReadWorkbook extends ReadBasicParameter { public void setReadCacheSelector(ReadCacheSelector readCacheSelector) { this.readCacheSelector = readCacheSelector; } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java index 3fd8839..a94afb3 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java @@ -8,8 +8,6 @@ import java.util.Set; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.cache.selector.EternalReadCacheSelector; @@ -28,7 +26,6 @@ import com.alibaba.excel.support.ExcelTypeEnum; * @author Jiaju Zhuang */ public class ReadWorkbookHolder extends AbstractReadHolder { - private static final Logger LOGGER = LoggerFactory.getLogger(ReadWorkbookHolder.class); /** * current param @@ -82,7 +79,10 @@ public class ReadWorkbookHolder extends AbstractReadHolder { * Temporary files when reading excel */ private File tempFile; - + /** + * Whether the encryption + */ + private String password; /** * The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a * field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. @@ -174,6 +174,7 @@ public class ReadWorkbookHolder extends AbstractReadHolder { } this.hasReadSheet = new HashSet(); this.ignoreRecord03 = Boolean.FALSE; + this.password = readWorkbook.getPassword(); } public ReadWorkbook getReadWorkbook() { @@ -312,6 +313,14 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.ignoreRecord03 = ignoreRecord03; } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + @Override public HolderEnum holderType() { return HolderEnum.WORKBOOK; diff --git a/src/main/java/com/alibaba/excel/util/FileUtils.java b/src/main/java/com/alibaba/excel/util/FileUtils.java index 9738b50..34e6853 100644 --- a/src/main/java/com/alibaba/excel/util/FileUtils.java +++ b/src/main/java/com/alibaba/excel/util/FileUtils.java @@ -157,6 +157,15 @@ public class FileUtils { return directory; } + public static File createTmpFile(String fileName) { + String tmpDir = System.getProperty(JAVA_IO_TMPDIR); + if (tmpDir == null) { + throw new RuntimeException( + "Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!"); + } + return new File(tmpDir, fileName); + } + /** * * @param directory diff --git a/src/main/java/com/alibaba/excel/util/SheetUtils.java b/src/main/java/com/alibaba/excel/util/SheetUtils.java new file mode 100644 index 0000000..66a1c48 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/SheetUtils.java @@ -0,0 +1,67 @@ +package com.alibaba.excel.util; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.read.metadata.ReadSheet; + +/** + * Sheet utils + * + * @author Jiaju Zhuang + */ +public class SheetUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(SheetUtils.class); + + private SheetUtils() {} + + /** + * Match the parameters to the actual sheet + * + * @param readSheet + * actual sheet + * @param parameterReadSheetList + * parameters + * @param readAll + * @return + */ + public static ReadSheet match(ReadSheet readSheet, List parameterReadSheetList, Boolean readAll, + GlobalConfiguration globalConfiguration) { + if (readAll) { + return readSheet; + } + for (ReadSheet parameterReadSheet : parameterReadSheetList) { + if (parameterReadSheet == null) { + continue; + } + if (parameterReadSheet.getSheetNo() == null && parameterReadSheet.getSheetName() == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("The first is read by default."); + } + parameterReadSheet.setSheetNo(0); + } + boolean match = (parameterReadSheet.getSheetNo() != null + && parameterReadSheet.getSheetNo().equals(readSheet.getSheetNo())); + if (!match) { + String parameterSheetName = parameterReadSheet.getSheetName(); + if (!StringUtils.isEmpty(parameterSheetName)) { + boolean autoTrim = (parameterReadSheet.getAutoTrim() != null && parameterReadSheet.getAutoTrim()) + || (parameterReadSheet.getAutoTrim() == null && globalConfiguration.getAutoTrim()); + if (autoTrim) { + parameterSheetName = parameterSheetName.trim(); + } + match = parameterSheetName.equals(readSheet.getSheetName()); + } + } + if (match) { + readSheet.copyBasicParameter(parameterReadSheet); + return readSheet; + } + } + return null; + } + +} diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index 949c3da..2f39e1c 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -1,10 +1,16 @@ package com.alibaba.excel.util; +import java.io.File; import java.io.IOException; +import java.io.OutputStream; -import org.apache.poi.hssf.usermodel.HSSFFont; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -48,6 +54,10 @@ public class WorkBookUtil { } writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); writeWorkbookHolder.setWorkbook(hssfWorkbook); + if (writeWorkbookHolder.getPassword() != null) { + Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword()); + hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY); + } } public static Sheet createSheet(Workbook workbook, String sheetName) { diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index c1a00c2..fc017fd 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -103,7 +103,6 @@ public class ExcelBuilderImpl implements ExcelBuilder { } context.currentSheet(writeSheet, WriteTypeEnum.ADD); context.currentTable(writeTable); - context.setPassword(password); if (excelWriteAddExecutor == null) { excelWriteAddExecutor = new ExcelWriteAddExecutor(context); } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java index 3faad69..82de038 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java @@ -90,6 +90,19 @@ public class ExcelWriterBuilder { return this; } + /** + * Whether the encryption. + *

+ * WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive. + * + * @param password + * @return + */ + public ExcelWriterBuilder password(String password) { + writeWorkbook.setPassword(password); + return this; + } + /** * The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a * field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java index 95acbbc..26acff5 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java @@ -159,19 +159,6 @@ public class ExcelWriterSheetBuilder { excelWriter.finish(); } - /** - * write with password - * @param data - * @param password - */ - public void doWrite(List data,String password) { - if (excelWriter == null) { - throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); - } - excelWriter.write(data, build(), password); - excelWriter.finish(); - } - public ExcelWriterTableBuilder table() { return table(null); } diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java index 8ea5209..ae6c495 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java @@ -50,6 +50,13 @@ public class WriteWorkbook extends WriteBasicParameter { * Mandatory use 'inputStream' .Default is false */ private Boolean mandatoryUseInputStream; + /** + * Whether the encryption + *

+ * WARRING:Encryption is when the entire file is read into memory, so it is very memory intensive. + * + */ + private String password; /** * The default is all excel objects.Default is true. *

@@ -140,4 +147,12 @@ public class WriteWorkbook extends WriteBasicParameter { public void setWriteHandler(com.alibaba.excel.event.WriteHandler writeHandler) { this.writeHandler = writeHandler; } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } } 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 65559db..d802085 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 @@ -1,15 +1,12 @@ package com.alibaba.excel.write.metadata.holder; -import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -96,9 +93,8 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { * prevent duplicate creation of sheet objects */ private Map hasBeenInitializedSheet; - /** - * password + * Whether the encryption */ private String password; @@ -140,6 +136,7 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream(); } this.hasBeenInitializedSheet = new HashMap(); + this.password = writeWorkbook.getPassword(); } private void copyTemplate() throws IOException { @@ -257,11 +254,6 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.mandatoryUseInputStream = mandatoryUseInputStream; } - @Override - public HolderEnum holderType() { - return HolderEnum.WORKBOOK; - } - public String getPassword() { return password; } @@ -269,4 +261,9 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { public void setPassword(String password) { this.password = password; } + + @Override + public HolderEnum holderType() { + return HolderEnum.WORKBOOK; + } } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptData.java b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptData.java new file mode 100644 index 0000000..19ef8d0 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptData.java @@ -0,0 +1,14 @@ +package com.alibaba.easyexcel.test.core.encrypt; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class EncryptData { + @ExcelProperty("姓名") + private String name; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataListener.java new file mode 100644 index 0000000..0fb603f --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataListener.java @@ -0,0 +1,35 @@ +package com.alibaba.easyexcel.test.core.encrypt; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; + +/** + * @author Jiaju Zhuang + */ +public class EncryptDataListener extends AnalysisEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(EncryptDataListener.class); + List list = new ArrayList(); + + @Override + public void invoke(EncryptData data, AnalysisContext context) { + list.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + Assert.assertEquals(list.size(), 10); + Assert.assertEquals(list.get(0).getName(), "姓名0"); + Assert.assertEquals((int)(context.readSheetHolder().getSheetNo()), 0); + Assert.assertEquals( + context.readSheetHolder().getExcelReadHeadProperty().getHeadMap().get(0).getHeadNameList().get(0), "姓名"); + LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0))); + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java new file mode 100644 index 0000000..7477887 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java @@ -0,0 +1,88 @@ +package com.alibaba.easyexcel.test.core.encrypt; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.alibaba.easyexcel.test.core.simple.SimpleData; +import com.alibaba.easyexcel.test.core.simple.SimpleDataListener; +import com.alibaba.easyexcel.test.core.simple.SimpleDataSheetNameListener; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.FileUtils; + +/** + * + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class EncryptDataTest { + + private static File file07; + private static File file03; + private static File file07OutputStream; + private static File file03OutputStream; + + @BeforeClass + public static void init() { + file07 = TestFileUtil.createNewFile("encrypt07.xlsx"); + file03 = TestFileUtil.createNewFile("encrypt03.xls"); + file07OutputStream = TestFileUtil.createNewFile("encryptOutputStream07.xlsx"); + file03OutputStream = TestFileUtil.createNewFile("encryptOutputStream03.xls"); + } + + @Test + public void t01ReadAndWrite07() { + readAndWrite(file07); + } + + @Test + public void t02ReadAndWrite03() { + readAndWrite(file03); + } + + @Test + public void t01ReadAndWriteStream07() throws Exception { + readAndWriteStream(file07OutputStream, ExcelTypeEnum.XLSX); + } + + @Test + public void t02ReadAndWriteStream03() throws Exception { + readAndWriteStream(file03OutputStream, ExcelTypeEnum.XLSX); + } + + private void readAndWrite(File file) { + EasyExcel.write(file, EncryptData.class).password("123456").sheet().doWrite(data()); + EasyExcel.read(file, EncryptData.class, new EncryptDataListener()).password("123456").sheet().doRead(); + } + + private void readAndWriteStream(File file, ExcelTypeEnum excelType) throws Exception { + FileOutputStream fileOutputStream = new FileOutputStream(file); + EasyExcel.write(fileOutputStream, EncryptData.class).password("123456").excelType(excelType).sheet() + .doWrite(data()); + fileOutputStream.close(); + + FileInputStream fileInputStream = new FileInputStream(file); + EasyExcel.read(fileInputStream, EncryptData.class, new EncryptDataListener()).password("123456").sheet() + .doRead(); + } + + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + SimpleData simpleData = new SimpleData(); + simpleData.setName("姓名" + i); + list.add(simpleData); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java index 579a821..44e2f55 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java @@ -40,6 +40,16 @@ public class MultipleSheetsDataTest { read(file03); } + @Test + public void t03Read07All() { + readAll(file07); + } + + @Test + public void t04Read03All() { + readAll(file03); + } + private void read(File file) { MultipleSheetsListener multipleSheetsListener = new MultipleSheetsListener(); ExcelReader excelReader = EasyExcel.read(file, MultipleSheetsData.class, multipleSheetsListener).build(); @@ -53,4 +63,8 @@ public class MultipleSheetsDataTest { excelReader.finish(); } + private void readAll(File file) { + EasyExcel.read(file, MultipleSheetsData.class, new MultipleSheetsListener()).doReadAll(); + } + } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java index 950f562..f414be2 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsListener.java @@ -27,6 +27,7 @@ public class MultipleSheetsListener extends AnalysisEventListener * 1. 创建excel对应的实体对象 参照{@link DemoData} *

@@ -82,24 +82,21 @@ public class ReadTest { */ @Test public void repeatedRead() { - // 方法1 如果 sheet1 sheet2 都是同一数据 监听器和头 都写到最外层 String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; - ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build(); - ReadSheet readSheet1 = EasyExcel.readSheet(0).build(); - ReadSheet readSheet2 = EasyExcel.readSheet(1).build(); - excelReader.read(readSheet1); - excelReader.read(readSheet2); - // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的 - excelReader.finish(); + // 读取全部sheet + // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写 + EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll(); - // 方法2 如果 sheet1 sheet2 数据不一致的话 + // 读取部分sheet fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; - excelReader = EasyExcel.read(fileName).build(); + ExcelReader excelReader = EasyExcel.read(fileName).build(); // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener - readSheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); - readSheet2 = EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); - excelReader.read(readSheet1); - excelReader.read(readSheet2); + 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(); } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/DemoData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/DemoData.java index b65fbf0..8a7902b 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/DemoData.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/DemoData.java @@ -2,6 +2,8 @@ package com.alibaba.easyexcel.test.demo.write; import java.util.Date; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -19,4 +21,9 @@ public class DemoData { private Date date; @ExcelProperty("数字标题") private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; } 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 b2a1722..336a199 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 @@ -57,7 +57,7 @@ public class WriteTest { // 这里 需要指定写用哪个class去读 ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); - excelWriter.write(data(), writeSheet,"12345"); + excelWriter.write(data(), writeSheet); // 进行加密 /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/Poi3Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/Poi3Test.java new file mode 100644 index 0000000..2ff3427 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/Poi3Test.java @@ -0,0 +1,73 @@ +package com.alibaba.easyexcel.test.temp.poi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellCopyPolicy; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.streaming.SXSSFRow; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.util.FileUtils; + +/** + * 测试poi + * + * @author Jiaju Zhuang + **/ +@Ignore +public class Poi3Test { + private static final Logger LOGGER = LoggerFactory.getLogger(Poi3Test.class); + + @Test + public void Encryption() throws Exception { + String file = TestFileUtil.getPath() + "large" + File.separator + "large07.xlsx"; + POIFSFileSystem fs = new POIFSFileSystem(); + EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); + Encryptor enc = info.getEncryptor(); + enc.confirmPassword("foobaa"); + OPCPackage opc = OPCPackage.open(new File(file), PackageAccess.READ_WRITE); + OutputStream os = enc.getDataStream(fs); + opc.save(os); + opc.close(); + + // Write out the encrypted version + FileOutputStream fos = new FileOutputStream("D:\\test\\99999999999.xlsx"); + fs.writeFilesystem(fos); + fos.close(); + fs.close(); + + } + + @Test + public void Encryption2() throws Exception { + Biff8EncryptionKey.setCurrentUserPassword("123456"); + POIFSFileSystem fs = new POIFSFileSystem(new File("d:/test/simple03.xls"), true); + HSSFWorkbook hwb = new HSSFWorkbook(fs.getRoot(), true); + Biff8EncryptionKey.setCurrentUserPassword(null); + System.out.println(hwb.getSheetAt(0).getSheetName()); + + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java index 0a19c35..ee7be1e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java @@ -22,6 +22,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; import com.alibaba.excel.util.FileUtils; /** 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 d5a39d6..27bea33 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 @@ -33,7 +33,7 @@ public class Wirte { String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 - EasyExcel.write(fileName).sheet("模板").head(head()).doWrite(data()); + EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); } private List> head() { diff --git a/update.md b/update.md index 04eec04..331dfbe 100644 --- a/update.md +++ b/update.md @@ -2,10 +2,13 @@ * 新增支持导入、导出支持公式 * 新增支持读取单元格类型、写入指定单元格类型 * 支持通过模板填充数据 -* 新增写支持 禁用头样式 autoHeadStyle +* 新增写支持 禁用头样式 `autoHeadStyle` * 用map读取数据 空的单元格也会有个 null的数据 * 转换报错 能获取到对应的行号和列号 * 优化读取全部sheet方案 +* 新增注解`ExcelIgnoreUnannotated` 支持忽略未加`ExcelProperty`注解的字段 +* 支持导出加密 [Issue #361](https://github.com/alibaba/easyexcel/issues/361) +* 支持导入加密 [Issue #295](https://github.com/alibaba/easyexcel/issues/295) # 2.0.5 * 优化07版超大文件读取方案