package com.taover.easyexcel.write.metadata.holder; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.IndexedColors; import com.taover.easyexcel.converters.Converter; import com.taover.easyexcel.converters.ConverterKeyBuild; import com.taover.easyexcel.converters.DefaultConverterLoader; import com.taover.easyexcel.enums.HeadKindEnum; import com.taover.easyexcel.event.NotRepeatExecutor; import com.taover.easyexcel.event.Order; import com.taover.easyexcel.metadata.AbstractHolder; import com.taover.easyexcel.metadata.Font; import com.taover.easyexcel.metadata.Head; import com.taover.easyexcel.metadata.TableStyle; import com.taover.easyexcel.metadata.property.LoopMergeProperty; import com.taover.easyexcel.metadata.property.OnceAbsoluteMergeProperty; import com.taover.easyexcel.metadata.property.RowHeightProperty; import com.taover.easyexcel.util.CollectionUtils; import com.taover.easyexcel.write.handler.CellWriteHandler; import com.taover.easyexcel.write.handler.DefaultWriteHandlerLoader; import com.taover.easyexcel.write.handler.RowWriteHandler; import com.taover.easyexcel.write.handler.SheetWriteHandler; import com.taover.easyexcel.write.handler.WorkbookWriteHandler; import com.taover.easyexcel.write.handler.WriteHandler; import com.taover.easyexcel.write.merge.LoopMergeStrategy; import com.taover.easyexcel.write.merge.OnceAbsoluteMergeStrategy; import com.taover.easyexcel.write.metadata.WriteBasicParameter; import com.taover.easyexcel.write.metadata.WriteSheet; import com.taover.easyexcel.write.metadata.WriteTable; import com.taover.easyexcel.write.metadata.style.WriteCellStyle; import com.taover.easyexcel.write.metadata.style.WriteFont; import com.taover.easyexcel.write.property.ExcelWriteHeadProperty; import com.taover.easyexcel.write.style.AbstractVerticalCellStyleStrategy; import com.taover.easyexcel.write.style.HorizontalCellStyleStrategy; import com.taover.easyexcel.write.style.column.AbstractHeadColumnWidthStyleStrategy; import com.taover.easyexcel.write.style.row.SimpleRowHeightStyleStrategy; /** * Write holder configuration * * @author Jiaju Zhuang */ public abstract class AbstractWriteHolder extends AbstractHolder implements WriteHolder { /** * Need Head */ private Boolean needHead; /** * Writes the head relative to the existing contents of the sheet. Indexes are zero-based. */ private Integer relativeHeadRowIndex; /** * Excel head property */ private ExcelWriteHeadProperty excelWriteHeadProperty; /** * Write handler */ private Map, List> writeHandlerMap; /** * Own write handler.Created in the sheet in the workbook interceptors will not be executed because the workbook to * create an event long past. So when initializing sheet, supplementary workbook event. */ private Map, List> ownWriteHandlerMap; /** * Use the default style.Default is true. */ private Boolean useDefaultStyle; /** * Whether to automatically merge headers.Default is true. */ private Boolean automaticMergeHead; /** * Ignore the custom columns. */ private Collection excludeColumnIndexes; /** * Ignore the custom columns. */ private Collection excludeColumnFiledNames; /** * Only output the custom columns. */ private Collection includeColumnIndexes; /** * Only output the custom columns. */ private Collection includeColumnFiledNames; public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWriteHolder parentAbstractWriteHolder, Boolean convertAllFiled) { super(writeBasicParameter, parentAbstractWriteHolder); if (writeBasicParameter.getUse1904windowing() == null) { if (parentAbstractWriteHolder == null) { getGlobalConfiguration().setUse1904windowing(Boolean.FALSE); } else { getGlobalConfiguration() .setUse1904windowing(parentAbstractWriteHolder.getGlobalConfiguration().getUse1904windowing()); } } else { getGlobalConfiguration().setUse1904windowing(writeBasicParameter.getUse1904windowing()); } if (writeBasicParameter.getUseScientificFormat() != null) { throw new UnsupportedOperationException("Currently does not support setting useScientificFormat."); } if (writeBasicParameter.getNeedHead() == null) { if (parentAbstractWriteHolder == null) { this.needHead = Boolean.TRUE; } else { this.needHead = parentAbstractWriteHolder.getNeedHead(); } } else { this.needHead = writeBasicParameter.getNeedHead(); } if (writeBasicParameter.getRelativeHeadRowIndex() == null) { if (parentAbstractWriteHolder == null) { this.relativeHeadRowIndex = 0; } else { this.relativeHeadRowIndex = parentAbstractWriteHolder.getRelativeHeadRowIndex(); } } else { this.relativeHeadRowIndex = writeBasicParameter.getRelativeHeadRowIndex(); } if (writeBasicParameter.getUseDefaultStyle() == null) { if (parentAbstractWriteHolder == null) { this.useDefaultStyle = Boolean.TRUE; } else { this.useDefaultStyle = parentAbstractWriteHolder.getUseDefaultStyle(); } } else { this.useDefaultStyle = writeBasicParameter.getUseDefaultStyle(); } if (writeBasicParameter.getAutomaticMergeHead() == null) { if (parentAbstractWriteHolder == null) { this.automaticMergeHead = Boolean.TRUE; } else { this.automaticMergeHead = parentAbstractWriteHolder.getAutomaticMergeHead(); } } else { this.automaticMergeHead = writeBasicParameter.getAutomaticMergeHead(); } if (writeBasicParameter.getExcludeColumnFiledNames() == null && parentAbstractWriteHolder != null) { this.excludeColumnFiledNames = parentAbstractWriteHolder.getExcludeColumnFiledNames(); } else { this.excludeColumnFiledNames = writeBasicParameter.getExcludeColumnFiledNames(); } if (writeBasicParameter.getExcludeColumnIndexes() == null && parentAbstractWriteHolder != null) { this.excludeColumnIndexes = parentAbstractWriteHolder.getExcludeColumnIndexes(); } else { this.excludeColumnIndexes = writeBasicParameter.getExcludeColumnIndexes(); } if (writeBasicParameter.getIncludeColumnFiledNames() == null && parentAbstractWriteHolder != null) { this.includeColumnFiledNames = parentAbstractWriteHolder.getIncludeColumnFiledNames(); } else { this.includeColumnFiledNames = writeBasicParameter.getIncludeColumnFiledNames(); } if (writeBasicParameter.getIncludeColumnIndexes() == null && parentAbstractWriteHolder != null) { this.includeColumnIndexes = parentAbstractWriteHolder.getIncludeColumnIndexes(); } else { this.includeColumnIndexes = writeBasicParameter.getIncludeColumnIndexes(); } // Initialization property this.excelWriteHeadProperty = new ExcelWriteHeadProperty(this, getClazz(), getHead(), convertAllFiled); // Compatible with old code compatibleOldCode(writeBasicParameter); // Set writeHandlerMap List handlerList = new ArrayList(); // Initialization Annotation initAnnotationConfig(handlerList, writeBasicParameter); if (writeBasicParameter.getCustomWriteHandlerList() != null && !writeBasicParameter.getCustomWriteHandlerList().isEmpty()) { handlerList.addAll(writeBasicParameter.getCustomWriteHandlerList()); } this.ownWriteHandlerMap = sortAndClearUpHandler(handlerList); Map, List> parentWriteHandlerMap = null; if (parentAbstractWriteHolder != null) { parentWriteHandlerMap = parentAbstractWriteHolder.getWriteHandlerMap(); } else { handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler(useDefaultStyle)); } this.writeHandlerMap = sortAndClearUpAllHandler(handlerList, parentWriteHandlerMap); // Set converterMap if (parentAbstractWriteHolder == null) { setConverterMap(DefaultConverterLoader.loadDefaultWriteConverter()); } else { setConverterMap(new HashMap(parentAbstractWriteHolder.getConverterMap())); } if (writeBasicParameter.getCustomConverterList() != null && !writeBasicParameter.getCustomConverterList().isEmpty()) { for (Converter converter : writeBasicParameter.getCustomConverterList()) { getConverterMap().put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter); } } } /** * Compatible with old code */ @Deprecated private void compatibleOldCode(WriteBasicParameter writeBasicParameter) { switch (holderType()) { case SHEET: compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, ((WriteSheet) writeBasicParameter).getTableStyle()); compatibleOldCodeCreateHeadColumnWidthStyleStrategy(writeBasicParameter, ((WriteSheet) writeBasicParameter).getColumnWidthMap()); return; case TABLE: compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, ((WriteTable) writeBasicParameter).getTableStyle()); return; default: } } @Deprecated private void compatibleOldCodeCreateRowCellStyleStrategy(WriteBasicParameter writeBasicParameter, TableStyle tableStyle) { if (tableStyle == null) { return; } if (writeBasicParameter.getCustomWriteHandlerList() == null) { writeBasicParameter.setCustomWriteHandlerList(new ArrayList()); } writeBasicParameter.getCustomWriteHandlerList() .add(new HorizontalCellStyleStrategy( buildWriteCellStyle(tableStyle.getTableHeadFont(), tableStyle.getTableHeadBackGroundColor()), buildWriteCellStyle(tableStyle.getTableContentFont(), tableStyle.getTableContentBackGroundColor()))); } @Deprecated private WriteCellStyle buildWriteCellStyle(Font font, IndexedColors indexedColors) { WriteCellStyle writeCellStyle = new WriteCellStyle(); if (indexedColors != null) { writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); writeCellStyle.setFillForegroundColor(indexedColors.getIndex()); } if (font != null) { WriteFont writeFont = new WriteFont(); writeFont.setFontName(font.getFontName()); writeFont.setFontHeightInPoints(font.getFontHeightInPoints()); writeFont.setBold(font.isBold()); writeCellStyle.setWriteFont(writeFont); } return writeCellStyle; } @Deprecated private void compatibleOldCodeCreateHeadColumnWidthStyleStrategy(WriteBasicParameter writeBasicParameter, final Map columnWidthMap) { if (columnWidthMap == null || columnWidthMap.isEmpty()) { return; } if (writeBasicParameter.getCustomWriteHandlerList() == null) { writeBasicParameter.setCustomWriteHandlerList(new ArrayList()); } writeBasicParameter.getCustomWriteHandlerList().add(new AbstractHeadColumnWidthStyleStrategy() { @Override protected Integer columnWidth(Head head, Integer columnIndex) { if (columnWidthMap.containsKey(head.getColumnIndex())) { return columnWidthMap.get(head.getColumnIndex()) / 256; } return 20; } }); } protected void initAnnotationConfig(List handlerList, WriteBasicParameter writeBasicParameter) { if (!HeadKindEnum.CLASS.equals(getExcelWriteHeadProperty().getHeadKind())) { return; } if (writeBasicParameter.getClazz() == null) { return; } Map headMap = getExcelWriteHeadProperty().getHeadMap(); boolean hasColumnWidth = false; boolean hasStyle = false; for (Head head : headMap.values()) { if (head.getColumnWidthProperty() != null) { hasColumnWidth = true; } if (head.getHeadStyleProperty() != null || head.getHeadFontProperty() != null || head.getContentStyleProperty() != null || head.getContentFontProperty() != null) { hasStyle = true; } dealLoopMerge(handlerList, head); } if (hasColumnWidth) { dealColumnWidth(handlerList); } if (hasStyle) { dealStyle(handlerList); } dealRowHigh(handlerList); dealOnceAbsoluteMerge(handlerList); } private void dealStyle(List handlerList) { WriteHandler styleStrategy = new AbstractVerticalCellStyleStrategy() { @Override protected WriteCellStyle headCellStyle(Head head) { return WriteCellStyle.build(head.getHeadStyleProperty(), head.getHeadFontProperty()); } @Override protected WriteCellStyle contentCellStyle(Head head) { return WriteCellStyle.build(head.getContentStyleProperty(), head.getContentFontProperty()); } }; handlerList.add(styleStrategy); } private void dealLoopMerge(List handlerList, Head head) { LoopMergeProperty loopMergeProperty = head.getLoopMergeProperty(); if (loopMergeProperty == null) { return; } handlerList.add(new LoopMergeStrategy(loopMergeProperty, head.getColumnIndex())); } private void dealOnceAbsoluteMerge(List handlerList) { OnceAbsoluteMergeProperty onceAbsoluteMergeProperty = getExcelWriteHeadProperty().getOnceAbsoluteMergeProperty(); if (onceAbsoluteMergeProperty == null) { return; } handlerList.add(new OnceAbsoluteMergeStrategy(onceAbsoluteMergeProperty)); } private void dealRowHigh(List handlerList) { RowHeightProperty headRowHeightProperty = getExcelWriteHeadProperty().getHeadRowHeightProperty(); RowHeightProperty contentRowHeightProperty = getExcelWriteHeadProperty().getContentRowHeightProperty(); if (headRowHeightProperty == null && contentRowHeightProperty == null) { return; } Short headRowHeight = null; if (headRowHeightProperty != null) { headRowHeight = headRowHeightProperty.getHeight(); } Short contentRowHeight = null; if (contentRowHeightProperty != null) { contentRowHeight = contentRowHeightProperty.getHeight(); } handlerList.add(new SimpleRowHeightStyleStrategy(headRowHeight, contentRowHeight)); } private void dealColumnWidth(List handlerList) { WriteHandler columnWidthStyleStrategy = new AbstractHeadColumnWidthStyleStrategy() { @Override protected Integer columnWidth(Head head, Integer columnIndex) { if (head == null) { return null; } if (head.getColumnWidthProperty() != null) { return head.getColumnWidthProperty().getWidth(); } return null; } }; handlerList.add(columnWidthStyleStrategy); } protected Map, List> sortAndClearUpAllHandler( List handlerList, Map, List> parentHandlerMap) { // add if (parentHandlerMap != null) { List parentWriteHandler = parentHandlerMap.get(WriteHandler.class); if (!CollectionUtils.isEmpty(parentWriteHandler)) { handlerList.addAll(parentWriteHandler); } } return sortAndClearUpHandler(handlerList); } protected Map, List> sortAndClearUpHandler( List handlerList) { // sort Map> orderExcelWriteHandlerMap = new TreeMap>(); for (WriteHandler handler : handlerList) { int order = Integer.MIN_VALUE; if (handler instanceof Order) { order = ((Order) handler).order(); } if (orderExcelWriteHandlerMap.containsKey(order)) { orderExcelWriteHandlerMap.get(order).add(handler); } else { List tempHandlerList = new ArrayList(); tempHandlerList.add(handler); orderExcelWriteHandlerMap.put(order, tempHandlerList); } } // clean up Set alreadyExistedHandlerSet = new HashSet(); List cleanUpHandlerList = new ArrayList(); for (Map.Entry> entry : orderExcelWriteHandlerMap.entrySet()) { for (WriteHandler handler : entry.getValue()) { if (handler instanceof NotRepeatExecutor) { String uniqueValue = ((NotRepeatExecutor) handler).uniqueValue(); if (alreadyExistedHandlerSet.contains(uniqueValue)) { continue; } alreadyExistedHandlerSet.add(uniqueValue); } cleanUpHandlerList.add(handler); } } // classify Map, List> result = new HashMap, List>(16); result.put(WriteHandler.class, new ArrayList()); result.put(WorkbookWriteHandler.class, new ArrayList()); result.put(SheetWriteHandler.class, new ArrayList()); result.put(RowWriteHandler.class, new ArrayList()); result.put(CellWriteHandler.class, new ArrayList()); for (WriteHandler writeHandler : cleanUpHandlerList) { if (writeHandler instanceof CellWriteHandler) { result.get(CellWriteHandler.class).add(writeHandler); } if (writeHandler instanceof RowWriteHandler) { result.get(RowWriteHandler.class).add(writeHandler); } if (writeHandler instanceof SheetWriteHandler) { result.get(SheetWriteHandler.class).add(writeHandler); } if (writeHandler instanceof WorkbookWriteHandler) { result.get(WorkbookWriteHandler.class).add(writeHandler); } result.get(WriteHandler.class).add(writeHandler); } return result; } @Override public boolean ignore(String fieldName, Integer columnIndex) { if (fieldName != null) { if (includeColumnFiledNames != null && !includeColumnFiledNames.contains(fieldName)) { return true; } if (excludeColumnFiledNames != null && excludeColumnFiledNames.contains(fieldName)) { return true; } } if (columnIndex != null) { if (includeColumnIndexes != null && !includeColumnIndexes.contains(columnIndex)) { return true; } if (excludeColumnIndexes != null && excludeColumnIndexes.contains(columnIndex)) { return true; } } return false; } public Boolean getNeedHead() { return needHead; } public void setNeedHead(Boolean needHead) { this.needHead = needHead; } public Map, List> getWriteHandlerMap() { return writeHandlerMap; } public void setWriteHandlerMap(Map, List> writeHandlerMap) { this.writeHandlerMap = writeHandlerMap; } public Map, List> getOwnWriteHandlerMap() { return ownWriteHandlerMap; } public void setOwnWriteHandlerMap( Map, List> ownWriteHandlerMap) { this.ownWriteHandlerMap = ownWriteHandlerMap; } public ExcelWriteHeadProperty getExcelWriteHeadProperty() { return excelWriteHeadProperty; } public void setExcelWriteHeadProperty(ExcelWriteHeadProperty excelWriteHeadProperty) { this.excelWriteHeadProperty = excelWriteHeadProperty; } public Integer getRelativeHeadRowIndex() { return relativeHeadRowIndex; } public void setRelativeHeadRowIndex(Integer relativeHeadRowIndex) { this.relativeHeadRowIndex = relativeHeadRowIndex; } public Boolean getUseDefaultStyle() { return useDefaultStyle; } public void setUseDefaultStyle(Boolean useDefaultStyle) { this.useDefaultStyle = useDefaultStyle; } public Boolean getAutomaticMergeHead() { return automaticMergeHead; } public void setAutomaticMergeHead(Boolean automaticMergeHead) { this.automaticMergeHead = automaticMergeHead; } public Collection getExcludeColumnIndexes() { return excludeColumnIndexes; } public void setExcludeColumnIndexes(Collection excludeColumnIndexes) { this.excludeColumnIndexes = excludeColumnIndexes; } public Collection getExcludeColumnFiledNames() { return excludeColumnFiledNames; } public void setExcludeColumnFiledNames(Collection excludeColumnFiledNames) { this.excludeColumnFiledNames = excludeColumnFiledNames; } public Collection getIncludeColumnIndexes() { return includeColumnIndexes; } public void setIncludeColumnIndexes(Collection includeColumnIndexes) { this.includeColumnIndexes = includeColumnIndexes; } public Collection getIncludeColumnFiledNames() { return includeColumnFiledNames; } public void setIncludeColumnFiledNames(Collection includeColumnFiledNames) { this.includeColumnFiledNames = includeColumnFiledNames; } @Override public ExcelWriteHeadProperty excelWriteHeadProperty() { return getExcelWriteHeadProperty(); } @Override public Map, List> writeHandlerMap() { return getWriteHandlerMap(); } @Override public Map, List> ownWriteHandlerMap() { return getOwnWriteHandlerMap(); } @Override public boolean needHead() { return getNeedHead(); } @Override public int relativeHeadRowIndex() { return getRelativeHeadRowIndex(); } @Override public boolean automaticMergeHead() { return getAutomaticMergeHead(); } }