diff --git a/pom.xml b/pom.xml index 84af219..2a06ad6 100644 --- a/pom.xml +++ b/pom.xml @@ -59,12 +59,12 @@ org.apache.poi poi - 3.17 + 4.0.1 org.apache.poi poi-ooxml - 3.17 + 4.0.1 cglib diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 8e1c011..652ab99 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -21,7 +21,7 @@ import com.alibaba.excel.parameter.GenerateParam; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.ExcelBuilder; import com.alibaba.excel.write.ExcelBuilderImpl; -import com.alibaba.excel.write.MergeStrategy; +import com.alibaba.excel.write.merge.MergeStrategy; /** * Excel Writer This tool is used to write value out to Excel via POI. This object can perform the diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index 84bccb0..b7f721e 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -34,7 +34,7 @@ public class AnalysisContextImpl implements AnalysisContext { private boolean trim; private boolean use1904WindowDate = false; - + private ConverterRegistryCenter converterRegistryCenter; @Override @@ -74,13 +74,14 @@ public class AnalysisContextImpl implements AnalysisContext { this.converterRegistryCenter = converterRegistryCenter; } - + @Override public void setCurrentSheet(Sheet currentSheet) { cleanCurrentSheet(); this.currentSheet = currentSheet; if (currentSheet.getClazz() != null) { - ExcelHeadProperty.buildExcelHeadProperty(this.excelHeadProperty, currentSheet.getClazz(), null); + excelHeadProperty = + ExcelHeadProperty.buildExcelHeadProperty(this.excelHeadProperty, currentSheet.getClazz(), null); } } @@ -156,7 +157,7 @@ public class AnalysisContextImpl implements AnalysisContext { public ExcelHeadProperty getExcelHeadProperty() { return this.excelHeadProperty; } - + @Override public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) { diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java index 92b936e..3a24606 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContext.java +++ b/src/main/java/com/alibaba/excel/context/WriteContext.java @@ -9,6 +9,7 @@ import org.apache.poi.ss.usermodel.Workbook; import com.alibaba.excel.converters.ConverterRegistryCenter; import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.ExcelHeadProperty; +import com.alibaba.excel.metadata.SheetHolder; import com.alibaba.excel.metadata.Table; public interface WriteContext { @@ -26,7 +27,8 @@ public interface WriteContext { OutputStream getOutputStream(); Workbook getWorkbook(); - + + @Deprecated WriteHandler getWriteHandler(); CellStyle getCurrentContentStyle(); diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 434f67d..d1404f7 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -1,13 +1,11 @@ package com.alibaba.excel.context; -import static com.alibaba.excel.util.StyleUtil.buildSheetStyle; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -18,13 +16,15 @@ import org.apache.poi.ss.util.CellRangeAddress; import com.alibaba.excel.converters.ConverterRegistryCenter; import com.alibaba.excel.event.WriteHandler; -import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.ExcelHeadProperty; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.SheetHolder; import com.alibaba.excel.metadata.Table; +import com.alibaba.excel.metadata.TableHolder; 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 com.alibaba.excel.write.style.CellStyleStrategy; /** * A context is the main anchorage point of a excel writer. @@ -32,27 +32,18 @@ import com.alibaba.excel.util.WorkBookUtil; * @author jipengfei */ public class WriteContextImpl implements WriteContext { - - /*** - * The sheet currently written - */ - private Sheet currentSheet; - /** - * current param + * prevent duplicate creation of sheet objects */ - private com.alibaba.excel.metadata.Sheet currentSheetParam; - + private final Map hasBeenInitializedSheet = new HashMap(); /** - * The sheet currently written's name + * Current sheet holder */ - private String currentSheetName; - + private SheetHolder currentSheetHolder; /** - * + * The table currently written */ - private Table currentTable; - + private TableHolder currentTableHolder; /** * Excel type */ @@ -69,42 +60,16 @@ public class WriteContextImpl implements WriteContext { private OutputStream outputStream; /** - * Written form collection - */ - private Map tableMap = new ConcurrentHashMap(); - - /** - * Cell default style - */ - private CellStyle defaultCellStyle; - - /** - * Current table head style - */ - private CellStyle currentHeadCellStyle; - - /** - * Current table content style - */ - private CellStyle currentContentCellStyle; - - /** - * the header attribute of excel + * If sheet and table don't have {@link CellStyleStrategy} , use this one. If they have, use their own */ - private ExcelHeadProperty excelHeadProperty; - - private boolean needHead = true; + private CellStyleStrategy defalutCellStyleStrategy; private WriteHandler writeHandler; - - private ConverterRegistryCenter registryCenter; - public WriteHandler getWriteHandler() { - return writeHandler; - } + private ConverterRegistryCenter registryCenter; public WriteContextImpl(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType, - boolean needHead, WriteHandler writeHandler, ConverterRegistryCenter registryCenter) throws IOException { + boolean needHead, WriteHandler writeHandler, ConverterRegistryCenter registryCenter) throws IOException { this.needHead = needHead; this.outputStream = out; this.writeHandler = writeHandler; @@ -118,103 +83,146 @@ public class WriteContextImpl implements WriteContext { */ @Override public void currentSheet(com.alibaba.excel.metadata.Sheet sheet) { - if (null == currentSheetParam || currentSheetParam.getSheetNo() != sheet.getSheetNo()) { - cleanCurrentSheet(); - currentSheetParam = sheet; - try { - this.currentSheet = workbook.getSheetAt(sheet.getSheetNo() - 1); - } catch (Exception e) { - this.currentSheet = WorkBookUtil.createSheet(workbook, sheet); - if (null != writeHandler) { - this.writeHandler.sheet(sheet.getSheetNo(), currentSheet); - } + if (sheet == null) { + throw new IllegalArgumentException("Sheet argument cannot be null"); + } + if (hasBeenInitializedSheet.containsKey(sheet.getSheetNo())) { + currentSheetHolder = hasBeenInitializedSheet.get(sheet.getSheetNo()); + return; + } + // create sheet + currentSheetParam = sheet; + try { + this.currentSheet = workbook.getSheetAt(sheet.getSheetNo() - 1); + } catch (Exception e) { + this.currentSheet = WorkBookUtil.createSheet(workbook, sheet); + if (null != writeHandler) { + this.writeHandler.sheet(sheet.getSheetNo(), currentSheet); } - buildSheetStyle(currentSheet, sheet.getColumnWidthMap()); - /** **/ - this.initCurrentSheet(sheet); } - + // Initialization current sheet + initCurrentSheet(); } - private void initCurrentSheet(com.alibaba.excel.metadata.Sheet sheet) { - - /** **/ - initExcelHeadProperty(sheet.getHead(), sheet.getClazz()); - - initTableStyle(sheet.getTableStyle()); + private void initCurrentSheet() { + // Initialization head + initExcelHeadProperty(); + // Initialization cell style strategy + initCellStyleStrategy(); + // Initialization sheet head + initSheetHead(); + } - initTableHead(); + private void initCellStyleStrategy() { + if (currentSheetParam.getCellStyleStrategy() != null) { + currentSheetHolder.setCellStyleStrategy(currentSheetParam.getCellStyleStrategy()); + } + currentSheetHolder.setCellStyleStrategy(defalutCellStyleStrategy); + } + private void initTableCellStyleStrategy() { + if (.getCellStyleStrategy() != null) { + currentSheetHolder.setCellStyleStrategy(currentSheetParam.getCellStyleStrategy()); + } + currentSheetHolder.setCellStyleStrategy(defalutCellStyleStrategy); } - private void cleanCurrentSheet() { - this.currentSheet = null; - this.currentSheetParam = null; - this.excelHeadProperty = null; - this.currentHeadCellStyle = null; - this.currentContentCellStyle = null; - this.currentTable = null; + /** + * init excel header + */ + private void initExcelHeadProperty() { + currentSheetHolder + .setExcelHeadProperty(new ExcelHeadProperty(currentSheetParam.getClazz(), currentSheetParam.getHead())); + } + /** + * init table excel header + */ + private void initTableExcelHeadProperty() { + currentTableHolder.setExcelHeadProperty( + new ExcelHeadProperty(getCurrentTableParam().getClazz(), getCurrentTableParam().getHead())); } /** - * init excel header - * - * @param head - * @param clazz + * init sheet column with */ - private void initExcelHeadProperty(List> head, Class clazz) { - if (head != null || clazz != null) { this.excelHeadProperty = new ExcelHeadProperty(clazz, head); } + public void initSheetColumnWidth() { + for (Head head : currentSheetHolder.getExcelHeadProperty().getHeadList()) { + currentSheet.setColumnWidth(head.getColumnIndex(), currentSheetHolder.getColumnWidthStyleStrategy() + .columnWidth(head.getColumnIndex(), head.getFieldName())); + } } - public void initTableHead() { - if (needHead && null != excelHeadProperty && !CollectionUtils.isEmpty(excelHeadProperty.getHead())) { - int startRow = currentSheet.getLastRowNum(); - if (startRow > 0) { - startRow += 4; - } else { - startRow = currentSheetParam.getStartRow(); + public void initSheetHead() { + if (!currentSheetHolder.isNeedHead() || !currentSheetHolder.getExcelHeadProperty().hasHead()) { + return; + } + int startRow = getCurrentSheet().getLastRowNum(); + if (startRow > 0) { + startRow += 4; + } else { + startRow = getCurrentSheetParam().getStartRow(); + } + // Combined head + addMergedRegionToCurrentSheet(startRow); + for (int i = startRow; i < currentSheetHolder.getExcelHeadProperty().getHeadRowNumber() + startRow; i++) { + Row row = WorkBookUtil.createRow(getCurrentSheet(), i); + // Set the row height of the header + currentSheetHolder.getRowHighStyleStrategy().headColumnHigh(i); + if (null != writeHandler) { + this.writeHandler.row(i, row); } - addMergedRegionToCurrentSheet(startRow); - int i = startRow; - for (; i < this.excelHeadProperty.getRowNum() + startRow; i++) { - Row row = WorkBookUtil.createRow(currentSheet, i); - if (null != writeHandler) { - this.writeHandler.row(i, row); - } - addOneRowOfHeadDataToExcel(row, this.excelHeadProperty.getHeadByRowNum(i - startRow)); + addOneRowOfHeadDataToExcel(row, i, currentSheetHolder.getExcelHeadProperty().getHeadList()); + } + // Initialization sheet column width + initSheetColumnWidth(); + } + + public void initTableHead() { + if (!currentTableHolder.isNeedHead() || !currentTableHolder.getExcelHeadProperty().hasHead()) { + return; + } + int startRow = getCurrentSheet().getLastRowNum(); + if (startRow > 0) { + startRow += 4; + } else { + startRow = getCurrentSheetParam().getStartRow(); + } + // Combined head + addMergedRegionToCurrentSheet(startRow); + for (int i = startRow; i < currentTableHolder.getExcelHeadProperty().getHeadRowNumber() + startRow; i++) { + Row row = WorkBookUtil.createRow(getCurrentSheet(), i); + // Set the row height of the header + currentTableHolder.getRowHighStyleStrategy().headColumnHigh(i); + if (null != writeHandler) { + this.writeHandler.row(i, row); } + addOneRowOfHeadDataToExcel(row, i, currentTableHolder.getExcelHeadProperty().getHeadList()); } + // Initialization sheet column width + initSheetColumnWidth(); } private void addMergedRegionToCurrentSheet(int startRow) { - for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelHeadProperty.getCellRangeModels()) { + for (com.alibaba.excel.metadata.CellRange cellRangeModel : currentSheetHolder.getExcelHeadProperty() + .getCellRangeModels()) { currentSheet.addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + startRow, - cellRangeModel.getLastRow() + startRow, - cellRangeModel.getFirstCol(), cellRangeModel.getLastCol())); + cellRangeModel.getLastRow() + startRow, cellRangeModel.getFirstCol(), cellRangeModel.getLastCol())); } } - private void addOneRowOfHeadDataToExcel(Row row, List headByRowNum) { - if (headByRowNum != null && headByRowNum.size() > 0) { - for (int i = 0; i < headByRowNum.size(); i++) { - Cell cell = WorkBookUtil.createCell(row, i, getCurrentHeadCellStyle(), headByRowNum.get(i)); - if (null != writeHandler) { - this.writeHandler.cell(i, cell); - } + private void addOneRowOfHeadDataToExcel(Row row, int rowIndex, List headList) { + for (int i = 0; i < headList.size(); i++) { + Head head = headList.get(i); + Cell cell = WorkBookUtil.createCell(row, i, + currentSheetHolder.getCellStyleStrategy().headCellStyle(rowIndex, headList.get(i)), + head.getHeadName(i)); + if (null != writeHandler) { + this.writeHandler.cell(i, cell); } } } - private void initTableStyle(com.alibaba.excel.metadata.TableStyle tableStyle) { - if (tableStyle != null) { - this.currentHeadCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableHeadFont(), - tableStyle.getTableHeadBackGroundColor()); - this.currentContentCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableContentFont(), - tableStyle.getTableContentBackGroundColor()); - } - } - private void cleanCurrentTable() { this.excelHeadProperty = null; this.currentHeadCellStyle = null; @@ -225,6 +233,23 @@ public class WriteContextImpl implements WriteContext { @Override public void currentTable(Table table) { + if (table == null) { + return; + } + if (currentSheetHolder == null) { + throw new IllegalStateException("Must first call WriteContextImpl#currentSheet"); + } + if(currentSheetHolder.getHasBeenInitializedTable().containsKey(table.getTableNo())){ + currentTableHolder=currentSheetHolder.getHasBeenInitializedTable().get(table.getTableNo()); + return; + } + + + + + currentTable.getTableNo() + + if (null == currentTable || currentTable.getTableNo() != table.getTableNo()) { cleanCurrentTable(); this.currentTable = table; @@ -235,17 +260,19 @@ public class WriteContextImpl implements WriteContext { } + @Override public ExcelHeadProperty getExcelHeadProperty() { - return this.excelHeadProperty; + return currentSheetHolder.getExcelHeadProperty(); } + @Override public boolean needHead() { return this.needHead; } @Override public Sheet getCurrentSheet() { - return currentSheet; + return currentSheetHolder.getSheet(); } public void setCurrentSheet(Sheet currentSheet) { @@ -253,7 +280,7 @@ public class WriteContextImpl implements WriteContext { } public String getCurrentSheetName() { - return currentSheetName; + return currentSheetHolder.getCurrentSheetParam(); } public void setCurrentSheetName(String currentSheetName) { @@ -287,19 +314,19 @@ public class WriteContextImpl implements WriteContext { } public com.alibaba.excel.metadata.Sheet getCurrentSheetParam() { - return currentSheetParam; + return currentSheetHolder.getCurrentSheetParam(); } public void setCurrentSheetParam(com.alibaba.excel.metadata.Sheet currentSheetParam) { this.currentSheetParam = currentSheetParam; } - public Table getCurrentTable() { - return currentTable; + public Table getCurrentTableParam() { + return currentTableHolder.getCurrentTableParam(); } - public void setCurrentTable(Table currentTable) { - this.currentTable = currentTable; + public Table getCurrentTable() { + return currentTable; } @Override @@ -307,5 +334,3 @@ public class WriteContextImpl implements WriteContext { return registryCenter; } } - - diff --git a/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java b/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java new file mode 100644 index 0000000..e7f19d9 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java @@ -0,0 +1,21 @@ +package com.alibaba.excel.enums; + +/** + * The types of head + * + * @author zhuangjiaju + **/ +public enum HeadKindEnum { + /** + * none + */ + NONE, + /** + * class + */ + CLASS, + /** + * String + */ + STRING; +} diff --git a/src/main/java/com/alibaba/excel/event/Handler.java b/src/main/java/com/alibaba/excel/event/Handler.java new file mode 100644 index 0000000..2d3af06 --- /dev/null +++ b/src/main/java/com/alibaba/excel/event/Handler.java @@ -0,0 +1,8 @@ +package com.alibaba.excel.event; + +/** + * intercepts handle some business logic + * + * @author zhuangjiaju + **/ +public interface Handler {} diff --git a/src/main/java/com/alibaba/excel/event/WriteHandler.java b/src/main/java/com/alibaba/excel/event/WriteHandler.java index 408799f..1927f63 100644 --- a/src/main/java/com/alibaba/excel/event/WriteHandler.java +++ b/src/main/java/com/alibaba/excel/event/WriteHandler.java @@ -4,11 +4,17 @@ 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.write.handler.ExcelWriteHandler; + /** * + * @deprecated Separate implementations + * @see com.alibaba.excel.write.handler.SheetExcelWriteHandler + * @see com.alibaba.excel.write.handler.RowExcelWriteHandler + * @see com.alibaba.excel.write.handler.CellExcelWriteHandler * @author jipengfei */ -public interface WriteHandler { +public interface WriteHandler extends ExcelWriteHandler { /** * Custom operation after creating each sheet @@ -28,6 +34,7 @@ public interface WriteHandler { /** * Custom operation after creating each cell + * * @param cellNum * @param cell */ diff --git a/src/main/java/com/alibaba/excel/metadata/CellStyle.java b/src/main/java/com/alibaba/excel/metadata/CellStyle.java new file mode 100644 index 0000000..62a42ea --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/CellStyle.java @@ -0,0 +1,36 @@ +package com.alibaba.excel.metadata; + +import org.apache.poi.ss.usermodel.IndexedColors; + +/** + * Simple cell style + * + * @author zhuangjiaju + */ +public class CellStyle { + /** + * 表头背景颜色 + */ + private IndexedColors indexedColors; + + /** + * 表头字体样式 + */ + private Font simpleFont; + + public IndexedColors getIndexedColors() { + return indexedColors; + } + + public void setIndexedColors(IndexedColors indexedColors) { + this.indexedColors = indexedColors; + } + + public Font getSimpleFont() { + return simpleFont; + } + + public void setSimpleFont(Font simpleFont) { + this.simpleFont = simpleFont; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java index 7486a72..354b17d 100644 --- a/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java @@ -1,11 +1,16 @@ package com.alibaba.excel.metadata; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.alibaba.excel.annotation.ExcelColumnNum; import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.util.StringUtils; - -import java.lang.reflect.Field; -import java.util.*; +import com.alibaba.excel.enums.HeadKindEnum; /** * Define the header attribute of excel @@ -22,7 +27,7 @@ public class ExcelHeadProperty { /** * A two-dimensional array describing the header */ - private List> head = new ArrayList>(); + private List headList; /** * Attributes described by the header @@ -33,11 +38,53 @@ public class ExcelHeadProperty { * Attributes described by the header */ private Map excelColumnPropertyMap1 = new HashMap(); + /** + * The types of head + */ + private HeadKindEnum headKind; + /** + * The number of rows in the line with the most rows + */ + private int headRowNumber; public ExcelHeadProperty(Class headClazz, List> head) { this.headClazz = headClazz; - this.head = head; - initColumnProperties(); + headList = new ArrayList(); + headKind = HeadKindEnum.NONE; + headRowNumber = 0; + if (head != null && !head.isEmpty()) { + int index = 0; + for (List headData : head) { + headList.add(new Head(index++, null, headData)); + } + headKind = HeadKindEnum.STRING; + } else { + // convert headClazz to head + initColumnProperties(); + } + + initHeadRowNumber(); + } + + public static ExcelHeadProperty buildExcelHeadProperty(ExcelHeadProperty excelHeadProperty, + Class clazz, List headOneRow) { + if (excelHeadProperty == null) { + return new ExcelHeadProperty(clazz, new ArrayList>()); + } + if (headOneRow != null) { + excelHeadProperty.appendOneRow(headOneRow); + } + return excelHeadProperty; + } + + private void initHeadRowNumber() { + headRowNumber = 0; + for (Head head : headList) { + List list = head.getHeadNames(); + if (list != null && list.size() > headRowNumber) { + headRowNumber = list.size(); + } + } } /** @@ -46,25 +93,28 @@ public class ExcelHeadProperty { if (this.headClazz != null) { List fieldList = new ArrayList(); Class tempClass = this.headClazz; - //When the parent class is null, it indicates that the parent class (Object class) has reached the top + // When the parent class is null, it indicates that the parent class (Object class) has reached the top // level. while (tempClass != null) { fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields())); - //Get the parent class and give it to yourself + // Get the parent class and give it to yourself tempClass = tempClass.getSuperclass(); } - List> headList = new ArrayList>(); for (Field f : fieldList) { initOneColumnProperty(f); } - //对列排序 + // 对列排序 Collections.sort(columnPropertyList); - if (head == null || head.size() == 0) { - for (ExcelColumnProperty excelColumnProperty : columnPropertyList) { - headList.add(excelColumnProperty.getHead()); + + int index = 0; + for (ExcelColumnProperty excelColumnProperty : columnPropertyList) { + if (excelColumnProperty.getHead() != null && excelColumnProperty.getHead().size() > headRowNumber) { + headRowNumber = excelColumnProperty.getHead().size(); } - this.head = headList; + headList + .add(new Head(index++, excelColumnProperty.getField().getName(), excelColumnProperty.getHead())); } + headKind = HeadKindEnum.CLASS; } } @@ -98,21 +148,21 @@ public class ExcelHeadProperty { } /** - * + * Add one more head under the last head */ public void appendOneRow(List row) { - + int headSize = headList.size(); for (int i = 0; i < row.size(); i++) { - List list; - if (head.size() <= i) { - list = new ArrayList(); - head.add(list); + String rowData = row.get(i); + // join + if (i <= headSize) { + headList.get(i).getHeadNames().add(rowData); } else { - list = head.get(0); + // create and join + headList.add(new Head(i, null, rowData)); } - list.add(row.get(i)); } - + initHeadRowNumber(); } /** @@ -131,14 +181,6 @@ public class ExcelHeadProperty { this.headClazz = headClazz; } - public List> getHead() { - return this.head; - } - - public void setHead(List> head) { - this.head = head; - } - public List getColumnPropertyList() { return columnPropertyList; } @@ -147,6 +189,34 @@ public class ExcelHeadProperty { this.columnPropertyList = columnPropertyList; } + public List getHeadList() { + return headList; + } + + public void setHeadList(List headList) { + this.headList = headList; + } + + public HeadKindEnum getHeadKind() { + return headKind; + } + + public void setHeadKind(HeadKindEnum headKind) { + this.headKind = headKind; + } + + public boolean hasHead() { + return headKind == HeadKindEnum.NONE; + } + + public int getHeadRowNumber() { + return headRowNumber; + } + + public void setHeadRowNumber(int headRowNumber) { + this.headRowNumber = headRowNumber; + } + /** * Calculate all cells that need to be merged * @@ -154,8 +224,8 @@ public class ExcelHeadProperty { */ public List getCellRangeModels() { List cellRanges = new ArrayList(); - for (int i = 0; i < head.size(); i++) { - List columnValues = head.get(i); + for (int i = 0; i < headList.size(); i++) { + List columnValues = headList.get(i).getHeadNames(); for (int j = 0; j < columnValues.size(); j++) { int lastRow = getLastRangNum(j, columnValues.get(j), columnValues); int lastColumn = getLastRangNum(i, columnValues.get(j), getHeadByRowNum(j)); @@ -168,8 +238,9 @@ public class ExcelHeadProperty { } public List getHeadByRowNum(int rowNum) { - List l = new ArrayList(head.size()); - for (List list : head) { + List l = new ArrayList(headList.size()); + for (Head head : headList) { + List list = head.getHeadNames(); if (list.size() > rowNum) { l.add(list.get(rowNum)); } else { @@ -182,9 +253,12 @@ public class ExcelHeadProperty { /** * Get the last consecutive string position * - * @param j current value position - * @param value value content - * @param values values + * @param j + * current value position + * @param value + * value content + * @param values + * values * @return the last consecutive string position */ private int getLastRangNum(int j, String value, List values) { @@ -210,27 +284,5 @@ public class ExcelHeadProperty { } } return last; - - } - - public int getRowNum() { - int headRowNum = 0; - for (List list : head) { - if (list != null && list.size() > 0) { - if (list.size() > headRowNum) { - headRowNum = list.size(); - } - } - } - return headRowNum; - } - public static ExcelHeadProperty buildExcelHeadProperty(ExcelHeadProperty excelHeadProperty, Class clazz, List headOneRow) { - if (excelHeadProperty == null && (clazz != null || headOneRow != null)) { - excelHeadProperty = new ExcelHeadProperty(clazz, new ArrayList>()); - } - if (excelHeadProperty.getHead() == null && headOneRow != null) { - excelHeadProperty.appendOneRow(headOneRow); - } - return excelHeadProperty; } } diff --git a/src/main/java/com/alibaba/excel/metadata/Head.java b/src/main/java/com/alibaba/excel/metadata/Head.java new file mode 100644 index 0000000..d88d038 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/Head.java @@ -0,0 +1,73 @@ +package com.alibaba.excel.metadata; + +import java.util.ArrayList; +import java.util.List; + +/** + * excel head + * + * @author zhuangjiaju + **/ +public class Head { + private Integer columnIndex; + private String fieldName; + private List headNames; + + public Head(Integer columnIndex, String fieldName, String headName) { + this.columnIndex = columnIndex; + this.fieldName = fieldName; + List headNamesTmp = new ArrayList(); + headNamesTmp.add(headName); + this.headNames = headNamesTmp; + } + + public Head(Integer columnIndex, String fieldName, List headNames) { + this.columnIndex = columnIndex; + this.fieldName = fieldName; + if (headNames == null) { + headNames = new ArrayList(); + } + this.headNames = headNames; + } + + public Integer getColumnIndex() { + return columnIndex; + } + + public void setColumnIndex(Integer columnIndex) { + this.columnIndex = columnIndex; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public List getHeadNames() { + return headNames; + } + + public void setHeadNames(List headNames) { + this.headNames = headNames; + } + + /** + * Get head name with index + * + * @param index + * @return + */ + public String getHeadName(int index) { + if (headNames == null || headNames.isEmpty()) { + return null; + } + if (index >= headNames.size()) { + return headNames.get(headNames.size() - 1); + } else { + return headNames.get(index); + } + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/Sheet.java b/src/main/java/com/alibaba/excel/metadata/Sheet.java index ef98b9c..8aaa076 100644 --- a/src/main/java/com/alibaba/excel/metadata/Sheet.java +++ b/src/main/java/com/alibaba/excel/metadata/Sheet.java @@ -4,6 +4,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.poi.ss.usermodel.TableStyle; + +import com.alibaba.excel.write.style.CellStyleStrategy; +import com.alibaba.excel.write.style.column.ColumnWihtStyleStrategy; +import com.alibaba.excel.write.style.column.ColumnWithStyleStrategy; +import com.oracle.webservices.internal.api.databinding.DatabindingMode; + /** * * @author jipengfei @@ -34,11 +41,13 @@ public class Sheet { /** * */ + @Deprecated private TableStyle tableStyle; /** * column with */ + @Deprecated private Map columnWidthMap = new HashMap(); /** @@ -51,6 +60,17 @@ public class Sheet { */ private int startRow = 0; + private CellStyleStrategy cellStyleStrategy; + + private ColumnWithStyleStrategy columnWithStyleStrategy; + + public ColumnWithStyleStrategy getColumnWithStyleStrategy() { + return columnWithStyleStrategy; + } + + public void setColumnWithStyleStrategy(ColumnWithStyleStrategy columnWithStyleStrategy) { + this.columnWithStyleStrategy = columnWithStyleStrategy; + } public Sheet(int sheetNo) { this.sheetNo = sheetNo; @@ -165,4 +185,12 @@ public class Sheet { public void setStartRow(int startRow) { this.startRow = startRow; } + + public CellStyleStrategy getCellStyleStrategy() { + return cellStyleStrategy; + } + + public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { + this.cellStyleStrategy = cellStyleStrategy; + } } diff --git a/src/main/java/com/alibaba/excel/metadata/SheetHolder.java b/src/main/java/com/alibaba/excel/metadata/SheetHolder.java new file mode 100644 index 0000000..c51103a --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/SheetHolder.java @@ -0,0 +1,104 @@ +package com.alibaba.excel.metadata; + +import java.util.Map; + +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.write.style.CellStyleStrategy; +import com.alibaba.excel.write.style.column.ColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.row.RowHighStyleStrategy; + +/** + * sheet holder + * + * @author zhuangjiaju + */ +public class SheetHolder { + /*** + * poi sheet + */ + private Sheet sheet; + /*** + * has been initialized table + */ + private Map hasBeenInitializedTable; + /** + * the header attribute of excel + */ + private ExcelHeadProperty excelHeadProperty; + + private CellStyleStrategy cellStyleStrategy; + + private ColumnWidthStyleStrategy columnWidthStyleStrategy; + private RowHighStyleStrategy rowHighStyleStrategy; + /** + * current param + */ + private com.alibaba.excel.metadata.Sheet currentSheetParam; + + private boolean needHead = true; + + public com.alibaba.excel.metadata.Sheet getCurrentSheetParam() { + return currentSheetParam; + } + + public void setCurrentSheetParam(com.alibaba.excel.metadata.Sheet currentSheetParam) { + this.currentSheetParam = currentSheetParam; + } + + public RowHighStyleStrategy getRowHighStyleStrategy() { + return rowHighStyleStrategy; + } + + public void setRowHighStyleStrategy(RowHighStyleStrategy rowHighStyleStrategy) { + this.rowHighStyleStrategy = rowHighStyleStrategy; + } + + public ColumnWidthStyleStrategy getColumnWidthStyleStrategy() { + return columnWidthStyleStrategy; + } + + public void setColumnWidthStyleStrategy(ColumnWidthStyleStrategy columnWidthStyleStrategy) { + this.columnWidthStyleStrategy = columnWidthStyleStrategy; + } + + public boolean isNeedHead() { + return needHead; + } + + public void setNeedHead(boolean needHead) { + this.needHead = needHead; + } + + public ExcelHeadProperty getExcelHeadProperty() { + return excelHeadProperty; + } + + public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) { + this.excelHeadProperty = excelHeadProperty; + } + + public Sheet getSheet() { + return sheet; + } + + public void setSheet(Sheet sheet) { + this.sheet = sheet; + } + + public Map getHasBeenInitializedTable() { + return hasBeenInitializedTable; + } + + public void setHasBeenInitializedTable(Map hasBeenInitializedTable) { + this.hasBeenInitializedTable = hasBeenInitializedTable; + } + + public CellStyleStrategy getCellStyleStrategy() { + return cellStyleStrategy; + } + + public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { + this.cellStyleStrategy = cellStyleStrategy; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/Table.java b/src/main/java/com/alibaba/excel/metadata/Table.java index 6643c46..afa23ff 100644 --- a/src/main/java/com/alibaba/excel/metadata/Table.java +++ b/src/main/java/com/alibaba/excel/metadata/Table.java @@ -2,6 +2,8 @@ package com.alibaba.excel.metadata; import java.util.List; +import com.alibaba.excel.write.style.CellStyleStrategy; + /** * @author jipengfei */ @@ -20,8 +22,19 @@ public class Table { /** */ + @Deprecated private TableStyle tableStyle; + private CellStyleStrategy cellStyleStrategy; + + public CellStyleStrategy getCellStyleStrategy() { + return cellStyleStrategy; + } + + public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { + this.cellStyleStrategy = cellStyleStrategy; + } + public TableStyle getTableStyle() { return tableStyle; } diff --git a/src/main/java/com/alibaba/excel/metadata/TableHolder.java b/src/main/java/com/alibaba/excel/metadata/TableHolder.java new file mode 100644 index 0000000..d07c3b6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/TableHolder.java @@ -0,0 +1,89 @@ +package com.alibaba.excel.metadata; + +import com.alibaba.excel.write.style.CellStyleStrategy; +import com.alibaba.excel.write.style.column.ColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.row.RowHighStyleStrategy; + +/** + * sheet holder + * + * @author zhuangjiaju + */ +public class TableHolder { + /*** + * poi sheet + */ + private SheetHolder parentSheet; + /** + * the header attribute of excel + */ + private ExcelHeadProperty excelHeadProperty; + + private CellStyleStrategy cellStyleStrategy; + + private ColumnWidthStyleStrategy columnWidthStyleStrategy; + private RowHighStyleStrategy rowHighStyleStrategy; + + private boolean needHead = true; + + /** + * current table param + */ + private Table currentTableParam; + + public Table getCurrentTableParam() { + return currentTableParam; + } + + public void setCurrentTableParam(Table currentTableParam) { + this.currentTableParam = currentTableParam; + } + + public SheetHolder getParentSheet() { + return parentSheet; + } + + public void setParentSheet(SheetHolder parentSheet) { + this.parentSheet = parentSheet; + } + + public ExcelHeadProperty getExcelHeadProperty() { + return excelHeadProperty; + } + + public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) { + this.excelHeadProperty = excelHeadProperty; + } + + public CellStyleStrategy getCellStyleStrategy() { + return cellStyleStrategy; + } + + public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { + this.cellStyleStrategy = cellStyleStrategy; + } + + public ColumnWidthStyleStrategy getColumnWidthStyleStrategy() { + return columnWidthStyleStrategy; + } + + public void setColumnWidthStyleStrategy(ColumnWidthStyleStrategy columnWidthStyleStrategy) { + this.columnWidthStyleStrategy = columnWidthStyleStrategy; + } + + public RowHighStyleStrategy getRowHighStyleStrategy() { + return rowHighStyleStrategy; + } + + public void setRowHighStyleStrategy(RowHighStyleStrategy rowHighStyleStrategy) { + this.rowHighStyleStrategy = rowHighStyleStrategy; + } + + public boolean isNeedHead() { + return needHead; + } + + public void setNeedHead(boolean needHead) { + this.needHead = needHead; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/TableStyle.java b/src/main/java/com/alibaba/excel/metadata/TableStyle.java deleted file mode 100644 index 228019c..0000000 --- a/src/main/java/com/alibaba/excel/metadata/TableStyle.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.alibaba.excel.metadata; - -import org.apache.poi.ss.usermodel.IndexedColors; - -/** - * @author jipengfei - */ -public class TableStyle { - - /** - * 表头背景颜色 - */ - private IndexedColors tableHeadBackGroundColor; - - /** - * 表头字体样式 - */ - private Font tableHeadFont; - - /** - * 表格内容字体样式 - */ - private Font tableContentFont; - - /** - * 表格内容背景颜色 - */ - private IndexedColors tableContentBackGroundColor; - - public IndexedColors getTableHeadBackGroundColor() { - return tableHeadBackGroundColor; - } - - public void setTableHeadBackGroundColor(IndexedColors tableHeadBackGroundColor) { - this.tableHeadBackGroundColor = tableHeadBackGroundColor; - } - - public Font getTableHeadFont() { - return tableHeadFont; - } - - public void setTableHeadFont(Font tableHeadFont) { - this.tableHeadFont = tableHeadFont; - } - - public Font getTableContentFont() { - return tableContentFont; - } - - public void setTableContentFont(Font tableContentFont) { - this.tableContentFont = tableContentFont; - } - - public IndexedColors getTableContentBackGroundColor() { - return tableContentBackGroundColor; - } - - public void setTableContentBackGroundColor(IndexedColors tableContentBackGroundColor) { - this.tableContentBackGroundColor = tableContentBackGroundColor; - } -} diff --git a/src/main/java/com/alibaba/excel/util/StyleUtil.java b/src/main/java/com/alibaba/excel/util/StyleUtil.java index cfb9c12..7e83c88 100644 --- a/src/main/java/com/alibaba/excel/util/StyleUtil.java +++ b/src/main/java/com/alibaba/excel/util/StyleUtil.java @@ -1,14 +1,38 @@ package com.alibaba.excel.util; -import org.apache.poi.ss.usermodel.*; - import java.util.Map; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; + /** * @author jipengfei */ public class StyleUtil { + public static void defaultCellStyle(Workbook workbook, CellStyle newCellStyle) { + Font font = workbook.createFont(); + font.setFontName("宋体"); + font.setFontHeightInPoints((short)14); + font.setBold(true); + newCellStyle.setFont(font); + newCellStyle.setWrapText(true); + newCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + newCellStyle.setAlignment(HorizontalAlignment.CENTER); + newCellStyle.setLocked(true); + newCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + newCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + newCellStyle.setBorderBottom(BorderStyle.THIN); + newCellStyle.setBorderLeft(BorderStyle.THIN); + } + /** * * @param workbook @@ -40,7 +64,7 @@ public class StyleUtil { * @return */ public static CellStyle buildCellStyle(Workbook workbook, com.alibaba.excel.metadata.Font f, - IndexedColors indexedColors) { + IndexedColors indexedColors) { CellStyle cellStyle = buildDefaultCellStyle(workbook); if (f != null) { Font font = workbook.createFont(); @@ -55,7 +79,18 @@ public class StyleUtil { return cellStyle; } - public static Sheet buildSheetStyle(Sheet currentSheet, Map sheetWidthMap){ + /** + * Convert {@link com.alibaba.excel.metadata.CellStyle} to {@link CellStyle} + * + * @param workbook + * @param cellStyle + * @return + */ + public static CellStyle buildCellStyle(Workbook workbook, com.alibaba.excel.metadata.CellStyle cellStyle) { + return buildCellStyle(workbook, cellStyle.getSimpleFont(), cellStyle.getIndexedColors()); + } + + public static Sheet buildSheetStyle(Sheet currentSheet, Map sheetWidthMap) { currentSheet.setDefaultColumnWidth(20); for (Map.Entry entry : sheetWidthMap.entrySet()) { currentSheet.setColumnWidth(entry.getKey(), entry.getValue()); @@ -63,5 +98,4 @@ public class StyleUtil { return currentSheet; } - } diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index 62d47ee..4135f31 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -2,6 +2,7 @@ package com.alibaba.excel.write; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; +import com.alibaba.excel.write.merge.MergeStrategy; import java.util.List; diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index 3655bb5..da09a90 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -24,8 +24,8 @@ import com.alibaba.excel.metadata.Table; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.POITempFile; -import com.alibaba.excel.util.TypeUtil; import com.alibaba.excel.util.WorkBookUtil; +import com.alibaba.excel.write.merge.MergeStrategy; import net.sf.cglib.beans.BeanMap; @@ -34,6 +34,7 @@ import net.sf.cglib.beans.BeanMap; */ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { + private WriteContext context; private final List converters = new ArrayList(); @@ -89,6 +90,7 @@ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { addContent(data, sheetParam.getStartRow()); } + @Override public void merge(List strategies) { if (strategies != null) { diff --git a/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java new file mode 100644 index 0000000..869b787 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java @@ -0,0 +1,30 @@ +package com.alibaba.excel.write; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.support.ExcelTypeEnum; + +public class ExcelWriterBuilder { + /** + * Excel type + */ + private ExcelTypeEnum excelType; + + /** + * Final output stream + */ + private OutputStream outputStream; + + /** + * + */ + private List customConverter = new ArrayList(); + + public ExcelWriter build() { + new ExcelBuilderImpl(templateInputStream, outputStream, typeEnum, needHead, writeHandler, converters); + } +} diff --git a/src/main/java/com/alibaba/excel/write/MergeStrategy.java b/src/main/java/com/alibaba/excel/write/MergeStrategy.java deleted file mode 100644 index a585d0e..0000000 --- a/src/main/java/com/alibaba/excel/write/MergeStrategy.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.alibaba.excel.write; - -public interface MergeStrategy { - int getFirstRow(); - int getLastRow(); - int getFirstCol(); - int getLastCol(); -} diff --git a/src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java new file mode 100644 index 0000000..ed78b98 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java @@ -0,0 +1,33 @@ +package com.alibaba.excel.write.handler; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.sun.istack.internal.Nullable; + +/** + * intercepts handle cell creation + * + * @author zhuangjiaju + */ +public interface CellExcelWriteHandler extends ExcelWriteHandler { + + /** + * called before create the cell + * + * @param writeContext + */ + void beforeCellCreate(SheetHolder sheetHolder, @Nullable TableHolder tableHolder, Row row, Head head, + int relativeRowIndex, boolean isHead); + + /** + * called after the cell is created + * + * @param writeContext + */ + void afterCellCreate(SheetHolder sheetHolder, @Nullable TableHolder tableHolder, Cell cell, Head head, + int relativeRowIndex, boolean isHead); +} diff --git a/src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java new file mode 100644 index 0000000..d37fc02 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java @@ -0,0 +1,10 @@ +package com.alibaba.excel.write.handler; + +import com.alibaba.excel.event.Handler; + +/** + * intercepts handle excel write + * + * @author zhuangjiaju + */ +public interface ExcelWriteHandler extends Handler {} diff --git a/src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java new file mode 100644 index 0000000..d0c4099 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java @@ -0,0 +1,31 @@ +package com.alibaba.excel.write.handler; + +import org.apache.poi.ss.usermodel.Row; + +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.sun.istack.internal.Nullable; + +/** + * intercepts handle row creation + * + * @author zhuangjiaju + */ +public interface RowExcelWriteHandler extends ExcelWriteHandler { + + /** + * called before create the row + * + * @param writeContext + */ + void beforeRowCreate(SheetHolder sheetHolder, @Nullable TableHolder tableHolder, int rowIndex, int relativeRowIndex, + boolean isHead); + + /** + * called after the row is created + * + * @param writeContext + */ + void afterRowCreate(SheetHolder sheetHolder, @Nullable TableHolder tableHolder, Row row, int relativeRowIndex, + boolean isHead); +} diff --git a/src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java new file mode 100644 index 0000000..d46eaab --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java @@ -0,0 +1,27 @@ +package com.alibaba.excel.write.handler; + +import org.apache.poi.ss.usermodel.Workbook; + +import com.alibaba.excel.metadata.SheetHolder; + +/** + * intercepts handle sheet creation + * + * @author zhuangjiaju + */ +public interface SheetExcelWriteHandler extends ExcelWriteHandler { + + /** + * called before create the sheet + * + * @param writeContext + */ + void beforeSheetCreate(Workbook workbook, SheetHolder sheetHolder); + + /** + * called after the sheet is created + * + * @param writeContext + */ + void afterSheetCreate(Workbook workbook, SheetHolder sheetHolder); +} diff --git a/src/main/java/com/alibaba/excel/write/handler/WookbookExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/WookbookExcelWriteHandler.java new file mode 100644 index 0000000..1441747 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/WookbookExcelWriteHandler.java @@ -0,0 +1,25 @@ +package com.alibaba.excel.write.handler; + +import org.apache.poi.ss.usermodel.Workbook; + +/** + * intercepts handle Wookbook creation + * + * @author zhuangjiaju + */ +public interface WookbookExcelWriteHandler extends ExcelWriteHandler { + + /** + * called before create the sheet + * + * @param writeContext + */ + void beforeWookbookCreate(); + + /** + * called after the sheet is created + * + * @param writeContext + */ + void afterWookbookCreate(Workbook workbook); +} 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 0000000..35e84e3 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java @@ -0,0 +1,28 @@ +package com.alibaba.excel.write.merge; + +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.Head; +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.write.handler.CellExcelWriteHandler; + +public abstract class AbstractMergeStrategy implements CellExcelWriteHandler { + + @Override + public void beforeCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, Head head, + int relativeRowIndex, boolean isHead) {} + + @Override + public void afterCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Cell cell, Head head, + int relativeRowIndex, boolean isHead) { + if (isHead) { + return; + } + merge(sheetHolder.getSheet(), cell, head, relativeRowIndex); + } + + protected abstract void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex); +} diff --git a/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java new file mode 100644 index 0000000..ad4843f --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.write.merge; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import com.alibaba.excel.metadata.Head; + +/** + * The regions of the loop merge + * + * @author zhuangjiaju + */ +public class LoopMergeStrategy extends AbstractMergeStrategy { + private int eachRow; + private int eachColumn; + + public LoopMergeStrategy(int eachRow, int eachColumn) { + if (eachRow < 1 || eachColumn < 1) { + throw new IllegalArgumentException("All parameters must be greater than 1"); + } + this.eachRow = eachRow; + this.eachColumn = eachColumn; + } + + @Override + protected void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex) { + if (relativeRowIndex % eachRow == 0 && head.getColumnIndex() % eachColumn == 0) { + CellRangeAddress cellRangeAddress = new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex() + eachRow, + cell.getColumnIndex(), cell.getColumnIndex() + eachColumn); + sheet.addMergedRegion(cellRangeAddress); + } + } +} diff --git a/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java new file mode 100644 index 0000000..939ed0b --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java @@ -0,0 +1,39 @@ +package com.alibaba.excel.write.merge; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import com.alibaba.excel.metadata.Head; + +/** + * It only merges once when create cell(firstRowIndex,lastRowIndex) + * + * @author zhuangjiaju + */ +public class OnceAbsoluteMergeStrategy extends AbstractMergeStrategy { + + private int firstRowIndex; + private int lastRowIndex; + private int firstColumnIndex; + private int lastColumnIndex; + + public OnceAbsoluteMergeStrategy(int firstRowIndex, int lastRowIndex, int firstColumnIndex, int lastColumnIndex) { + if (firstRowIndex < 0 || lastRowIndex < 0 || firstColumnIndex < 0 || lastColumnIndex < 0) { + throw new IllegalArgumentException("All parameters must be greater than 0"); + } + this.firstRowIndex = firstRowIndex; + this.lastRowIndex = lastRowIndex; + this.firstColumnIndex = firstColumnIndex; + this.lastColumnIndex = lastColumnIndex; + } + + @Override + protected void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex) { + if (cell.getRowIndex() == firstRowIndex && cell.getColumnIndex() == firstColumnIndex) { + CellRangeAddress cellRangeAddress = + new CellRangeAddress(firstRowIndex, lastRowIndex, firstColumnIndex, lastColumnIndex); + sheet.addMergedRegion(cellRangeAddress); + } + } +} diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java new file mode 100644 index 0000000..a96e834 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java @@ -0,0 +1,43 @@ +package com.alibaba.excel.write.style; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Workbook; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.write.handler.CellExcelWriteHandler; +import com.alibaba.excel.write.handler.WookbookExcelWriteHandler; + +public abstract class AbstractCellStyleStrategy implements CellExcelWriteHandler, WookbookExcelWriteHandler { + @Override + public void beforeWookbookCreate() {} + + @Override + public void afterWookbookCreate(Workbook workbook) { + initCellStyle(workbook); + } + + @Override + public void beforeCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, Head head, + int relativeRowIndex, boolean isHead) {} + + @Override + public void afterCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Cell cell, Head head, + int relativeRowIndex, boolean isHead) { + if (isHead) { + setHeadCellStyle(cell, head, relativeRowIndex); + } else { + setContentCellStyle(cell, head, relativeRowIndex); + } + + } + + protected abstract void initCellStyle(Workbook workbook); + + protected abstract void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex); + + protected abstract void setContentCellStyle(Cell cell, Head head, int relativeRowIndex); + +} diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java new file mode 100644 index 0000000..4fcd180 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java @@ -0,0 +1,65 @@ +package com.alibaba.excel.write.style; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Workbook; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.util.StyleUtil; + +/** + * Head of style shareholders and content of style loop + */ +public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyleStrategy { + + private Workbook workbook; + private Map headCellStyleCache = new HashMap(); + private Map contentCellStyleCache = new HashMap(); + + @Override + protected void initCellStyle(Workbook workbook) { + this.workbook = workbook; + } + + @Override + protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { + int columnIndex = head.getColumnIndex(); + if (headCellStyleCache.containsKey(columnIndex)) { + cell.setCellStyle(headCellStyleCache.get(columnIndex)); + } + CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, headCellStyle(head)); + headCellStyleCache.put(columnIndex, cellStyle); + cell.setCellStyle(cellStyle); + } + + @Override + protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { + int columnIndex = head.getColumnIndex(); + if (contentCellStyleCache.containsKey(columnIndex)) { + cell.setCellStyle(contentCellStyleCache.get(columnIndex)); + } + CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, contentCellStyle(head)); + contentCellStyleCache.put(columnIndex, cellStyle); + cell.setCellStyle(cellStyle); + } + + /** + * Returns the column width corresponding to each column header + * + * @param head + * @return + */ + protected abstract com.alibaba.excel.metadata.CellStyle headCellStyle(Head head); + + /** + * Returns the column width corresponding to each column header + * + * @param head + * @return + */ + protected abstract com.alibaba.excel.metadata.CellStyle contentCellStyle(Head head); + +} diff --git a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java new file mode 100644 index 0000000..aecc7c6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java @@ -0,0 +1,57 @@ +package com.alibaba.excel.write.style; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Workbook; + +import com.alibaba.excel.metadata.CellStyle; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.util.StyleUtil; + +public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { + + private CellStyle headCellStyle; + private List contentCellStyleList; + + private org.apache.poi.ss.usermodel.CellStyle poiHeadCellStyle; + private List poiContentCellStyleList; + + public HorizontalCellStyleStrategy(CellStyle headCellStyle, List contentCellStyleList) { + if (headCellStyle == null || contentCellStyleList == null || contentCellStyleList.isEmpty()) { + throw new IllegalArgumentException("All parameters can not be null"); + } + this.headCellStyle = headCellStyle; + this.contentCellStyleList = contentCellStyleList; + } + + public HorizontalCellStyleStrategy(CellStyle headCellStyle, CellStyle contentCellStyle) { + if (headCellStyle == null || contentCellStyle == null) { + throw new IllegalArgumentException("All parameters can not be null"); + } + this.headCellStyle = headCellStyle; + contentCellStyleList = new ArrayList(); + contentCellStyleList.add(contentCellStyle); + } + + @Override + protected void initCellStyle(Workbook workbook) { + poiHeadCellStyle = StyleUtil.buildCellStyle(workbook, headCellStyle); + poiContentCellStyleList = new ArrayList(); + for (CellStyle cellStyle : contentCellStyleList) { + poiContentCellStyleList.add(StyleUtil.buildCellStyle(workbook, cellStyle)); + } + } + + @Override + protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { + cell.setCellStyle(poiHeadCellStyle); + } + + @Override + protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { + cell.setCellStyle(poiContentCellStyleList.get(relativeRowIndex % poiContentCellStyleList.size())); + } + +} diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java new file mode 100644 index 0000000..ce78053 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java @@ -0,0 +1,41 @@ +package com.alibaba.excel.write.style.column; + +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.Head; +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.write.handler.CellExcelWriteHandler; + +/** + * Column width style strategy + * + * @author zhuangjiaju + */ +public abstract class AbstractColumnWidthStyleStrategy implements CellExcelWriteHandler { + + @Override + public void beforeCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, Head head, + int relativeRowIndex, boolean isHead) {} + + @Override + public void afterCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Cell cell, Head head, + int relativeRowIndex, boolean isHead) { + if (!isHead) { + return; + } + setColumnWidth(sheetHolder.getSheet(), cell, head); + } + + /** + * Sets the column width when head create + * + * @param sheet + * @param cell + * @param head + */ + protected abstract void setColumnWidth(Sheet sheet, Cell cell, Head head); + +} diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java new file mode 100644 index 0000000..f58b92e --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java @@ -0,0 +1,26 @@ +package com.alibaba.excel.write.style.column; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.metadata.Head; + +/** + * Returns the column width according to each column header + * + * @author zhuangjiaju + */ +public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { + @Override + protected void setColumnWidth(Sheet sheet, Cell cell, Head head) { + sheet.setColumnWidth(cell.getColumnIndex(), columnWidth(head)); + } + + /** + * Returns the column width corresponding to each column header + * + * @param head + * @return + */ + protected abstract int columnWidth(Head head); +} diff --git a/src/main/java/com/alibaba/excel/write/style/column/SimpleColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/SimpleColumnWidthStyleStrategy.java new file mode 100644 index 0000000..4b1ec08 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/column/SimpleColumnWidthStyleStrategy.java @@ -0,0 +1,24 @@ +package com.alibaba.excel.write.style.column; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.metadata.Head; + +/** + * All the columns are the same width + * + * @author zhuangjiaju + */ +public class SimpleColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { + private int columnWidth; + + public SimpleColumnWidthStyleStrategy(int columnWidth) { + this.columnWidth = columnWidth; + } + + @Override + protected void setColumnWidth(Sheet sheet, Cell cell, Head head) { + sheet.setColumnWidth(cell.getColumnIndex(), columnWidth); + } +} diff --git a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java new file mode 100644 index 0000000..9ccc332 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java @@ -0,0 +1,31 @@ +package com.alibaba.excel.write.style.row; + +import org.apache.poi.ss.usermodel.Row; + +import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.write.handler.RowExcelWriteHandler; + +public abstract class AbstractRowHighStyleStrategy implements RowExcelWriteHandler { + + @Override + public void beforeRowCreate(SheetHolder sheetHolder, TableHolder tableHolder, int rowIndex, int relativeRowIndex, + boolean isHead) { + + } + + @Override + public void afterRowCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, int relativeRowIndex, + boolean isHead) { + if (isHead) { + setHeadColumnHigh(row, relativeRowIndex); + } else { + setContentColumnHigh(row, relativeRowIndex); + } + } + + protected abstract void setHeadColumnHigh(Row row, int relativeRowIndex); + + protected abstract void setContentColumnHigh(Row row, int relativeRowIndex); + +} diff --git a/src/main/java/com/alibaba/excel/write/style/row/SimpleRowHighStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/row/SimpleRowHighStyleStrategy.java new file mode 100644 index 0000000..f49b618 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/style/row/SimpleRowHighStyleStrategy.java @@ -0,0 +1,29 @@ +package com.alibaba.excel.write.style.row; + +import org.apache.poi.ss.usermodel.Row; + +/** + * Set the head column high and content column high + * + * @author zhuangjiaju + */ +public class SimpleRowHighStyleStrategy extends AbstractRowHighStyleStrategy { + private short headColumnHigh; + private short contentColumnHigh; + + public SimpleRowHighStyleStrategy(short headColumnHigh, short contentColumnHigh) { + this.headColumnHigh = headColumnHigh; + this.contentColumnHigh = contentColumnHigh; + } + + @Override + protected void setHeadColumnHigh(Row row, int relativeRowIndex) { + row.setHeight(headColumnHigh); + } + + @Override + protected void setContentColumnHigh(Row row, int relativeRowIndex) { + row.setHeight(contentColumnHigh); + } + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/WriteTest.java index 5acc49e..074c584 100644 --- a/src/test/java/com/alibaba/easyexcel/test/WriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/WriteTest.java @@ -25,13 +25,13 @@ import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.write.MergeStrategy; +import com.alibaba.excel.write.merge.MergeStrategy; public class WriteTest { @Test public void writeV2007() throws IOException { - OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2007.xlsx")); + OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2007"+System.currentTimeMillis()+".xlsx")); ExcelWriter writer = EasyExcelFactory.getWriter(out); // 写第一个sheet, sheet1 数据全是List 无模型映射关系 Sheet sheet1 = new Sheet(1, 3);