From 59acbf0c8deabfa026d76de2e4703f1377b70811 Mon Sep 17 00:00:00 2001 From: "jipengfei.jpf" Date: Thu, 29 Nov 2018 10:24:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=86=99=E5=9B=9E=E8=B0=83?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/alibaba/excel/EasyExcelFactory.java | 20 +++++++ .../java/com/alibaba/excel/ExcelWriter.java | 34 +++++++---- .../alibaba/excel/context/WriteContext.java | 29 ++++++--- .../com/alibaba/excel/event/WriteHandler.java | 35 +++++++++++ .../alibaba/excel/write/ExcelBuilderImpl.java | 23 ++++++-- .../com/alibaba/easyexcel/test/WriteTest.java | 47 +++++++++++++++ .../test/listen/AfterWriteHandlerImpl.java | 59 +++++++++++++++++++ 7 files changed, 225 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/event/WriteHandler.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/listen/AfterWriteHandlerImpl.java diff --git a/src/main/java/com/alibaba/excel/EasyExcelFactory.java b/src/main/java/com/alibaba/excel/EasyExcelFactory.java index fae2fe61..5327dc93 100644 --- a/src/main/java/com/alibaba/excel/EasyExcelFactory.java +++ b/src/main/java/com/alibaba/excel/EasyExcelFactory.java @@ -2,6 +2,7 @@ package com.alibaba.excel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.support.ExcelTypeEnum; @@ -97,4 +98,23 @@ public class EasyExcelFactory { return new ExcelWriter(temp, outputStream, typeEnum, needHead); } + /** + * Get ExcelWriter with a template file + * + * @param temp Append data after a POI file , Can be null(the template POI filesystem that contains the + * Workbook stream) + * @param outputStream the java OutputStream you wish to write the data to + * @param typeEnum 03 or 07 + * @param needHead + * @param handler User-defined callback + * @return new ExcelWriter + */ + public static ExcelWriter getWriterWithTempAndHandler(InputStream temp, + OutputStream outputStream, + ExcelTypeEnum typeEnum, + boolean needHead, + WriteHandler handler) { + return new ExcelWriter(temp, outputStream, typeEnum, needHead, handler); + } + } diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 6d9ebe42..e4061e0e 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -1,5 +1,6 @@ package com.alibaba.excel; +import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; @@ -17,7 +18,7 @@ import java.util.List; * This object can perform the following two functions. *
  *    1. Create a new empty Excel workbook, write the data to the stream after the data is filled.
- *    2. Edit existing Excel, write the original Excel file, or write it to other places.
+ *    2. Edit existing Excel, write the original Excel file, or write it to other places.{@link ExcelWriter(InputStream , OutputStream , ExcelTypeEnum , boolean )}
  * 
* @author jipengfei */ @@ -39,7 +40,7 @@ public class ExcelWriter { /** * @param generateParam - * @since easyexcel 0.0.1 + * @since easyexcel 0.0.1 Use {@link new ExcelWrite(int, int, int) */ @Deprecated public ExcelWriter(GenerateParam generateParam) { @@ -55,7 +56,7 @@ public class ExcelWriter { * @param needHead Do you need to write the header to the file? */ public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) { - excelBuilder = new ExcelBuilderImpl(null, outputStream, typeEnum, needHead); + excelBuilder = new ExcelBuilderImpl(null, outputStream, typeEnum, needHead, null); } /** @@ -65,11 +66,24 @@ public class ExcelWriter { * @param typeEnum 03 or 07 */ public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,Boolean needHead) { - excelBuilder = new ExcelBuilderImpl(templateInputStream,outputStream, typeEnum, needHead); + excelBuilder = new ExcelBuilderImpl(templateInputStream,outputStream, typeEnum, needHead, null); } + /** - * Write data to a sheet + * Create new writer + * @param templateInputStream Append data after a POI file ,Can be null(the template POI filesystem that contains the Workbook stream) + * @param outputStream the java OutputStream you wish to write the data to + * @param typeEnum 03 or 07 + * @param writeHandler User-defined callback + */ + public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum, Boolean needHead, + WriteHandler writeHandler) { + excelBuilder = new ExcelBuilderImpl(templateInputStream,outputStream, typeEnum, needHead,writeHandler); + } + + /** + * Write data(List) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @return this current writer @@ -97,7 +111,7 @@ public class ExcelWriter { /** * - * Write data to a sheet + * Write data(List>) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @return this @@ -108,7 +122,7 @@ public class ExcelWriter { } /** - * Write data to a sheet + * Write data(List>) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @return this @@ -119,7 +133,7 @@ public class ExcelWriter { } /** - * Write data to a sheet + * Write data(List) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @param table Write to this table @@ -131,7 +145,7 @@ public class ExcelWriter { } /** - * Write data to a sheet + * Write data(List>) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @param table Write to this table @@ -156,7 +170,7 @@ public class ExcelWriter { } /** - * Write data to a sheet + * Write data(List>) to a sheet * @param data Data to be written * @param sheet Write to this sheet * @param table Write to this table diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java index c3813798..b1aee592 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContext.java +++ b/src/main/java/com/alibaba/excel/context/WriteContext.java @@ -1,5 +1,6 @@ package com.alibaba.excel.context; +import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.ExcelHeadProperty; import com.alibaba.excel.metadata.Table; @@ -7,10 +8,7 @@ import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.StyleUtil; import com.alibaba.excel.util.WorkBookUtil; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import java.io.IOException; @@ -91,12 +89,20 @@ public class WriteContext { private boolean needHead = Boolean.TRUE; + private WriteHandler afterWriteHandler; + + public WriteHandler getAfterWriteHandler() { + return afterWriteHandler; + } + public WriteContext(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType, - boolean needHead) throws IOException { + boolean needHead, WriteHandler afterWriteHandler) throws IOException { this.needHead = needHead; this.outputStream = out; + this.afterWriteHandler = afterWriteHandler; this.workbook = WorkBookUtil.createWorkBook(templateInputStream, excelType); this.defaultCellStyle = StyleUtil.buildDefaultCellStyle(this.workbook); + } /** @@ -110,6 +116,9 @@ public class WriteContext { this.currentSheet = workbook.getSheetAt(sheet.getSheetNo() - 1); } catch (Exception e) { this.currentSheet = WorkBookUtil.createSheet(workbook, sheet); + if (null != afterWriteHandler) { + this.afterWriteHandler.sheet(sheet.getSheetNo(), currentSheet); + } } buildSheetStyle(currentSheet, sheet.getColumnWidthMap()); /** **/ @@ -154,13 +163,16 @@ public class WriteContext { int startRow = currentSheet.getLastRowNum(); if (startRow > 0) { startRow += 4; - }else { + } else { startRow = currentSheetParam.getStartRow(); } addMergedRegionToCurrentSheet(startRow); int i = startRow; for (; i < this.excelHeadProperty.getRowNum() + startRow; i++) { Row row = WorkBookUtil.createRow(currentSheet, i); + if (null != afterWriteHandler) { + this.afterWriteHandler.row(i, row); + } addOneRowOfHeadDataToExcel(row, this.excelHeadProperty.getHeadByRowNum(i - startRow)); } } @@ -177,7 +189,10 @@ public class WriteContext { private void addOneRowOfHeadDataToExcel(Row row, List headByRowNum) { if (headByRowNum != null && headByRowNum.size() > 0) { for (int i = 0; i < headByRowNum.size(); i++) { - WorkBookUtil.createCell(row, i, getCurrentHeadCellStyle(), headByRowNum.get(i)); + Cell cell = WorkBookUtil.createCell(row, i, getCurrentHeadCellStyle(), headByRowNum.get(i)); + if (null != afterWriteHandler) { + this.afterWriteHandler.cell(i, cell); + } } } } diff --git a/src/main/java/com/alibaba/excel/event/WriteHandler.java b/src/main/java/com/alibaba/excel/event/WriteHandler.java new file mode 100644 index 00000000..408799f6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/event/WriteHandler.java @@ -0,0 +1,35 @@ +package com.alibaba.excel.event; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; + +/** + * + * @author jipengfei + */ +public interface WriteHandler { + + /** + * Custom operation after creating each sheet + * + * @param sheetNo + * @param sheet + */ + void sheet(int sheetNo, Sheet sheet); + + /** + * Custom operation after creating each row + * + * @param rowNum + * @param row + */ + void row(int rowNum, Row row); + + /** + * Custom operation after creating each cell + * @param cellNum + * @param cell + */ + void cell(int cellNum, Cell cell); +} diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index bb362e98..893f31f2 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -1,6 +1,7 @@ package com.alibaba.excel.write; import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.ExcelColumnProperty; @@ -12,6 +13,7 @@ import com.alibaba.excel.util.POITempFile; import com.alibaba.excel.util.TypeUtil; import com.alibaba.excel.util.WorkBookUtil; import net.sf.cglib.beans.BeanMap; +import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.util.CellRangeAddress; @@ -23,6 +25,7 @@ import java.util.List; /** * @author jipengfei + * @date 2017/05/27 */ public class ExcelBuilderImpl implements ExcelBuilder { @@ -31,11 +34,11 @@ public class ExcelBuilderImpl implements ExcelBuilder { public ExcelBuilderImpl(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType, - boolean needHead) { + boolean needHead, WriteHandler writeHandler) { try { //初始化时候创建临时缓存目录,用于规避POI在并发写bug POITempFile.createPOIFilesDirectory(); - context = new WriteContext(templateInputStream, out, excelType, needHead); + context = new WriteContext(templateInputStream, out, excelType, needHead, writeHandler); } catch (Exception e) { throw new RuntimeException(e); } @@ -99,11 +102,14 @@ public class ExcelBuilderImpl implements ExcelBuilder { } for (int i = 0; i < oneRowData.size(); i++) { Object cellValue = oneRowData.get(i); - WorkBookUtil.createCell(row, i, context.getCurrentContentStyle(), cellValue, TypeUtil.isNum(cellValue)); + Cell cell = WorkBookUtil.createCell(row, i, context.getCurrentContentStyle(), cellValue, + TypeUtil.isNum(cellValue)); + if (null != context.getAfterWriteHandler()) { + context.getAfterWriteHandler().cell(i, cell); + } } } - private void addJavaObjectToExcel(Object oneRowData, Row row) { int i = 0; BeanMap beanMap = BeanMap.create(oneRowData); @@ -113,7 +119,11 @@ public class ExcelBuilderImpl implements ExcelBuilder { excelHeadProperty.getFormat()); CellStyle cellStyle = baseRowModel.getStyle(i) != null ? baseRowModel.getStyle(i) : context.getCurrentContentStyle(); - WorkBookUtil.createCell(row, i, cellStyle, cellValue, TypeUtil.isNum(excelHeadProperty.getField())); + Cell cell = WorkBookUtil.createCell(row, i, cellStyle, cellValue, + TypeUtil.isNum(excelHeadProperty.getField())); + if (null != context.getAfterWriteHandler()) { + context.getAfterWriteHandler().cell(i, cell); + } i++; } @@ -121,6 +131,9 @@ public class ExcelBuilderImpl implements ExcelBuilder { private void addOneRowOfDataToExcel(Object oneRowData, int n) { Row row = WorkBookUtil.createRow(context.getCurrentSheet(), n); + if (null != context.getAfterWriteHandler()) { + context.getAfterWriteHandler().row(n, row); + } if (oneRowData instanceof List) { addBasicTypeToExcel((List)oneRowData, row); } else { diff --git a/src/test/java/com/alibaba/easyexcel/test/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/WriteTest.java index cda8ced2..6b481b63 100644 --- a/src/test/java/com/alibaba/easyexcel/test/WriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/WriteTest.java @@ -1,5 +1,6 @@ package com.alibaba.easyexcel.test; +import com.alibaba.easyexcel.test.listen.AfterWriteHandlerImpl; import com.alibaba.easyexcel.test.model.WriteModel; import com.alibaba.easyexcel.test.util.FileUtil; import com.alibaba.excel.EasyExcelFactory; @@ -105,6 +106,52 @@ public class WriteTest { } + @Test + public void writeV2007WithTemplateAndHandler() throws IOException { + InputStream inputStream = FileUtil.getResourcesFileInputStream("temp.xlsx"); + OutputStream out = new FileOutputStream("/Users/jipengfei/2007.xlsx"); + ExcelWriter writer = EasyExcelFactory.getWriterWithTempAndHandler(inputStream,out,ExcelTypeEnum.XLSX,true, + new AfterWriteHandlerImpl()); + //写第一个sheet, sheet1 数据全是List 无模型映射关系 + Sheet sheet1 = new Sheet(1, 3); + sheet1.setSheetName("第一个sheet"); + sheet1.setStartRow(20); + + //设置列宽 设置每列的宽度 + Map columnWidth = new HashMap(); + columnWidth.put(0,10000);columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000); + sheet1.setColumnWidthMap(columnWidth); + sheet1.setHead(createTestListStringHead()); + //or 设置自适应宽度 + //sheet1.setAutoWidth(Boolean.TRUE); + writer.write1(createTestListObject(), sheet1); + + //写第二个sheet sheet2 模型上打有表头的注解,合并单元格 + Sheet sheet2 = new Sheet(2, 3, WriteModel.class, "第二个sheet", null); + sheet2.setTableStyle(createTableStyle()); + sheet2.setStartRow(20); + writer.write(createTestListJavaMode(), sheet2); + + //写第三个sheet包含多个table情况 + Sheet sheet3 = new Sheet(3, 0); + sheet3.setSheetName("第三个sheet"); + sheet3.setStartRow(30); + Table table1 = new Table(1); + table1.setHead(createTestListStringHead()); + writer.write1(createTestListObject(), sheet3, table1); + + //写sheet2 模型上打有表头的注解 + Table table2 = new Table(2); + table2.setTableStyle(createTableStyle()); + table2.setClazz(WriteModel.class); + writer.write(createTestListJavaMode(), sheet3, table2); + + writer.finish(); + out.close(); + + } + + @Test public void writeV2003() throws IOException { diff --git a/src/test/java/com/alibaba/easyexcel/test/listen/AfterWriteHandlerImpl.java b/src/test/java/com/alibaba/easyexcel/test/listen/AfterWriteHandlerImpl.java new file mode 100644 index 00000000..fd7c38fb --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/listen/AfterWriteHandlerImpl.java @@ -0,0 +1,59 @@ +package com.alibaba.easyexcel.test.listen; + +import com.alibaba.excel.event.WriteHandler; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; + +public class AfterWriteHandlerImpl implements WriteHandler { + + // + CellStyle cellStyle; + + @Override + public void sheet(int sheetNo, Sheet sheet) { + Workbook workbook = sheet.getWorkbook(); + //要锁定单元格需先为此表单设置保护密码,设置之后此表单默认为所有单元格锁定,可使用setLocked(false)为指定单元格设置不锁定。 + //设置表单保护密码 + sheet.protectSheet("your password"); + //创建样式 + cellStyle = workbook.createCellStyle(); + //设置是否锁 + cellStyle.setLocked(false); + + } + + @Override + public void row(int rowNum, Row row) { + Workbook workbook = row.getSheet().getWorkbook(); + //设置行高 + row.setHeight((short)20); + } + + @Override + public void cell(int cellNum, Cell cell) { + Workbook workbook = cell.getSheet().getWorkbook(); + Sheet currentSheet = cell.getSheet(); + if (cellNum == 4 && cell.getRowIndex() == 30) { + //设置样式 + //注意:样式最好采用公用样式,样式在创建sheet后创建,如果有多个样式也需要在创建sheet时候创建后面直接使用,不要每个Cell Create 一个样式,不然会导致报错 The maximum number + // of Cell Styles was exceeded. + cell.setCellStyle(cellStyle); + + + + //设置备注 + Drawing draw = currentSheet.createDrawingPatriarch(); + Comment comment = draw.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, 4, 25, 9, 30)); + XSSFRichTextString rtf = new XSSFRichTextString("添加批注内容收到货死的死哦多胡搜idsad是否会杜甫的范德萨发!1111"); + Font commentFormatter = workbook.createFont(); + commentFormatter.setFontName("宋体"); + //设置字体大小 + commentFormatter.setFontHeightInPoints((short)9); + rtf.applyFont(commentFormatter); + comment.setString(rtf); + comment.setAuthor("ceshi"); + cell.setCellComment(comment); + } + } +}