After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 811 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,17 @@ |
|||||||
|
package com.alibaba.excel.enums; |
||||||
|
|
||||||
|
/** |
||||||
|
* Direction of writing |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
**/ |
||||||
|
public enum WriteDirectionEnum { |
||||||
|
/** |
||||||
|
* Vertical write. |
||||||
|
*/ |
||||||
|
VERTICAL, |
||||||
|
/** |
||||||
|
* Horizontal write. |
||||||
|
*/ |
||||||
|
HORIZONTAL,; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.alibaba.excel.enums; |
||||||
|
|
||||||
|
/** |
||||||
|
* Type of template to read when writing |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
**/ |
||||||
|
public enum WriteTemplateAnalysisCellTypeEnum { |
||||||
|
/** |
||||||
|
* Common field. |
||||||
|
*/ |
||||||
|
COMMON, |
||||||
|
/** |
||||||
|
* A collection of fields. |
||||||
|
*/ |
||||||
|
COLLECTION,; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.alibaba.excel.enums; |
||||||
|
|
||||||
|
/** |
||||||
|
* Enumeration of write methods |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
**/ |
||||||
|
public enum WriteTypeEnum { |
||||||
|
/** |
||||||
|
* Add. |
||||||
|
*/ |
||||||
|
ADD, |
||||||
|
/** |
||||||
|
* Fill. |
||||||
|
*/ |
||||||
|
FILL,; |
||||||
|
} |
@ -0,0 +1,196 @@ |
|||||||
|
package com.alibaba.excel.util; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||||
|
import org.apache.poi.ss.usermodel.Row; |
||||||
|
|
||||||
|
import com.alibaba.excel.context.WriteContext; |
||||||
|
import com.alibaba.excel.metadata.CellData; |
||||||
|
import com.alibaba.excel.metadata.Head; |
||||||
|
import com.alibaba.excel.write.handler.CellWriteHandler; |
||||||
|
import com.alibaba.excel.write.handler.RowWriteHandler; |
||||||
|
import com.alibaba.excel.write.handler.SheetWriteHandler; |
||||||
|
import com.alibaba.excel.write.handler.WorkbookWriteHandler; |
||||||
|
import com.alibaba.excel.write.handler.WriteHandler; |
||||||
|
|
||||||
|
/** |
||||||
|
* Write handler utils |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
public class WriteHandlerUtils { |
||||||
|
|
||||||
|
private WriteHandlerUtils() {} |
||||||
|
|
||||||
|
public static void beforeWorkbookCreate(WriteContext writeContext) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof WorkbookWriteHandler) { |
||||||
|
((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterWorkbookCreate(WriteContext writeContext) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof WorkbookWriteHandler) { |
||||||
|
((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterWorkbookDispose(WriteContext writeContext) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof WorkbookWriteHandler) { |
||||||
|
((WorkbookWriteHandler)writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void beforeSheetCreate(WriteContext writeContext) { |
||||||
|
List<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof SheetWriteHandler) { |
||||||
|
((SheetWriteHandler)writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(), |
||||||
|
writeContext.writeSheetHolder()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterSheetCreate(WriteContext writeContext) { |
||||||
|
List<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof SheetWriteHandler) { |
||||||
|
((SheetWriteHandler)writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(), |
||||||
|
writeContext.writeSheetHolder()); |
||||||
|
} |
||||||
|
} |
||||||
|
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { |
||||||
|
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler() |
||||||
|
.sheet(writeContext.writeSheetHolder().getSheetNo(), writeContext.writeSheetHolder().getSheet()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void beforeCellCreate(WriteContext writeContext, Row row, Head head, Integer columnIndex, |
||||||
|
Integer relativeRowIndex, Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof CellWriteHandler) { |
||||||
|
((CellWriteHandler)writeHandler).beforeCellCreate(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterCellCreate(WriteContext writeContext, Cell cell, Head head, Integer relativeRowIndex, |
||||||
|
Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof CellWriteHandler) { |
||||||
|
((CellWriteHandler)writeHandler).afterCellCreate(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterCellDispose(WriteContext writeContext, CellData cellData, Cell cell, Head head, |
||||||
|
Integer relativeRowIndex, Boolean isHead) { |
||||||
|
List<CellData> cellDataList = new ArrayList<CellData>(); |
||||||
|
if (cell != null) { |
||||||
|
cellDataList.add(cellData); |
||||||
|
} |
||||||
|
afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterCellDispose(WriteContext writeContext, List<CellData> cellDataList, Cell cell, Head head, |
||||||
|
Integer relativeRowIndex, Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = |
||||||
|
writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof CellWriteHandler) { |
||||||
|
((CellWriteHandler)writeHandler).afterCellDispose(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { |
||||||
|
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void beforeRowCreate(WriteContext writeContext, Integer rowIndex, Integer relativeRowIndex, |
||||||
|
Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof RowWriteHandler) { |
||||||
|
((RowWriteHandler)writeHandler).beforeRowCreate(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void afterRowCreate(WriteContext writeContext, Row row, Integer relativeRowIndex, Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof RowWriteHandler) { |
||||||
|
((RowWriteHandler)writeHandler).afterRowCreate(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), row, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void afterRowDispose(WriteContext writeContext, Row row, Integer relativeRowIndex, Boolean isHead) { |
||||||
|
List<WriteHandler> handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class); |
||||||
|
if (handlerList == null || handlerList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (WriteHandler writeHandler : handlerList) { |
||||||
|
if (writeHandler instanceof RowWriteHandler) { |
||||||
|
((RowWriteHandler)writeHandler).afterRowDispose(writeContext.writeSheetHolder(), |
||||||
|
writeContext.writeTableHolder(), row, relativeRowIndex, isHead); |
||||||
|
} |
||||||
|
} |
||||||
|
if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { |
||||||
|
writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,140 @@ |
|||||||
|
package com.alibaba.excel.write.executor; |
||||||
|
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
||||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||||
|
import org.apache.poi.ss.usermodel.ClientAnchor; |
||||||
|
import org.apache.poi.ss.usermodel.CreationHelper; |
||||||
|
import org.apache.poi.ss.usermodel.Drawing; |
||||||
|
import org.apache.poi.ss.usermodel.Sheet; |
||||||
|
|
||||||
|
import com.alibaba.excel.context.WriteContext; |
||||||
|
import com.alibaba.excel.converters.Converter; |
||||||
|
import com.alibaba.excel.converters.ConverterKeyBuild; |
||||||
|
import com.alibaba.excel.enums.CellDataTypeEnum; |
||||||
|
import com.alibaba.excel.exception.ExcelDataConvertException; |
||||||
|
import com.alibaba.excel.metadata.CellData; |
||||||
|
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
||||||
|
import com.alibaba.excel.write.metadata.holder.WriteHolder; |
||||||
|
|
||||||
|
/** |
||||||
|
* Excel write Executor |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { |
||||||
|
protected WriteContext writeContext; |
||||||
|
|
||||||
|
public AbstractExcelWriteExecutor(WriteContext writeContext) { |
||||||
|
this.writeContext = writeContext; |
||||||
|
} |
||||||
|
|
||||||
|
protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, |
||||||
|
ExcelContentProperty excelContentProperty) { |
||||||
|
if (value == null) { |
||||||
|
return new CellData(); |
||||||
|
} |
||||||
|
if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) { |
||||||
|
value = ((String)value).trim(); |
||||||
|
} |
||||||
|
CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty); |
||||||
|
if (cellData.getFormula() != null && cellData.getFormula()) { |
||||||
|
cell.setCellFormula(cellData.getFormulaValue()); |
||||||
|
} |
||||||
|
switch (cellData.getType()) { |
||||||
|
case STRING: |
||||||
|
cell.setCellValue(cellData.getStringValue()); |
||||||
|
return cellData; |
||||||
|
case BOOLEAN: |
||||||
|
cell.setCellValue(cellData.getBooleanValue()); |
||||||
|
return cellData; |
||||||
|
case NUMBER: |
||||||
|
cell.setCellValue(cellData.getNumberValue().doubleValue()); |
||||||
|
return cellData; |
||||||
|
case IMAGE: |
||||||
|
setImageValue(cellData, cell); |
||||||
|
return cellData; |
||||||
|
case EMPTY: |
||||||
|
return cellData; |
||||||
|
default: |
||||||
|
throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType() |
||||||
|
+ "at row:" + cell.getRow().getRowNum()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, |
||||||
|
ExcelContentProperty excelContentProperty) { |
||||||
|
if (value == null) { |
||||||
|
return new CellData(); |
||||||
|
} |
||||||
|
// This means that the user has defined the data.
|
||||||
|
if (value instanceof CellData) { |
||||||
|
CellData cellDataValue = (CellData)value; |
||||||
|
if (cellDataValue.getType() != null) { |
||||||
|
return cellDataValue; |
||||||
|
} else { |
||||||
|
if (cellDataValue.getData() == null) { |
||||||
|
cellDataValue.setType(CellDataTypeEnum.EMPTY); |
||||||
|
return cellDataValue; |
||||||
|
} |
||||||
|
} |
||||||
|
CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell, |
||||||
|
cellDataValue.getData(), excelContentProperty); |
||||||
|
// The formula information is subject to user input
|
||||||
|
if (cellDataValue.getFormula() != null) { |
||||||
|
cellDataReturn.setFormula(cellDataValue.getFormula()); |
||||||
|
cellDataReturn.setFormulaValue(cellDataValue.getFormulaValue()); |
||||||
|
} |
||||||
|
return cellDataReturn; |
||||||
|
} |
||||||
|
return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty); |
||||||
|
} |
||||||
|
|
||||||
|
private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, |
||||||
|
ExcelContentProperty excelContentProperty) { |
||||||
|
Converter converter = null; |
||||||
|
if (excelContentProperty != null) { |
||||||
|
converter = excelContentProperty.getConverter(); |
||||||
|
} |
||||||
|
if (converter == null) { |
||||||
|
converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz)); |
||||||
|
} |
||||||
|
if (converter == null) { |
||||||
|
throw new ExcelDataConvertException( |
||||||
|
"Can not find 'Converter' support class " + clazz.getSimpleName() + "."); |
||||||
|
} |
||||||
|
CellData cellData; |
||||||
|
try { |
||||||
|
cellData = |
||||||
|
converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration()); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new ExcelDataConvertException("Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), |
||||||
|
e); |
||||||
|
} |
||||||
|
if (cellData == null || cellData.getType() == null) { |
||||||
|
throw new ExcelDataConvertException( |
||||||
|
"Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum()); |
||||||
|
} |
||||||
|
return cellData; |
||||||
|
} |
||||||
|
|
||||||
|
private void setImageValue(CellData cellData, Cell cell) { |
||||||
|
Sheet sheet = cell.getSheet(); |
||||||
|
int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG); |
||||||
|
Drawing drawing = sheet.getDrawingPatriarch(); |
||||||
|
if (drawing == null) { |
||||||
|
drawing = sheet.createDrawingPatriarch(); |
||||||
|
} |
||||||
|
CreationHelper helper = sheet.getWorkbook().getCreationHelper(); |
||||||
|
ClientAnchor anchor = helper.createClientAnchor(); |
||||||
|
anchor.setDx1(0); |
||||||
|
anchor.setDx2(0); |
||||||
|
anchor.setDy1(0); |
||||||
|
anchor.setDy2(0); |
||||||
|
anchor.setCol1(cell.getColumnIndex()); |
||||||
|
anchor.setCol2(cell.getColumnIndex() + 1); |
||||||
|
anchor.setRow1(cell.getRowIndex()); |
||||||
|
anchor.setRow2(cell.getRowIndex() + 1); |
||||||
|
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE); |
||||||
|
drawing.createPicture(anchor, index); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,179 @@ |
|||||||
|
package com.alibaba.excel.write.executor; |
||||||
|
|
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||||
|
import org.apache.poi.ss.usermodel.Row; |
||||||
|
|
||||||
|
import com.alibaba.excel.context.WriteContext; |
||||||
|
import com.alibaba.excel.enums.HeadKindEnum; |
||||||
|
import com.alibaba.excel.metadata.BaseRowModel; |
||||||
|
import com.alibaba.excel.metadata.CellData; |
||||||
|
import com.alibaba.excel.metadata.Head; |
||||||
|
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
||||||
|
import com.alibaba.excel.util.CollectionUtils; |
||||||
|
import com.alibaba.excel.util.WorkBookUtil; |
||||||
|
import com.alibaba.excel.util.WriteHandlerUtils; |
||||||
|
import com.alibaba.excel.write.metadata.holder.WriteHolder; |
||||||
|
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; |
||||||
|
|
||||||
|
import net.sf.cglib.beans.BeanMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Add the data into excel |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { |
||||||
|
|
||||||
|
public ExcelWriteAddExecutor(WriteContext writeContext) { |
||||||
|
super(writeContext); |
||||||
|
} |
||||||
|
|
||||||
|
public void add(List data) { |
||||||
|
if (CollectionUtils.isEmpty(data)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); |
||||||
|
int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); |
||||||
|
if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) { |
||||||
|
newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); |
||||||
|
} |
||||||
|
// BeanMap is out of order,so use fieldList
|
||||||
|
List<Field> fieldList = new ArrayList<Field>(); |
||||||
|
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) { |
||||||
|
int n = relativeRowIndex + newRowIndex; |
||||||
|
addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) { |
||||||
|
if (oneRowData == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE); |
||||||
|
Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n); |
||||||
|
WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE); |
||||||
|
if (oneRowData instanceof List) { |
||||||
|
addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex); |
||||||
|
} else { |
||||||
|
addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList); |
||||||
|
} |
||||||
|
WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE); |
||||||
|
} |
||||||
|
|
||||||
|
private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) { |
||||||
|
if (CollectionUtils.isEmpty(oneRowData)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); |
||||||
|
int dataIndex = 0; |
||||||
|
int cellIndex = 0; |
||||||
|
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) { |
||||||
|
if (dataIndex >= oneRowData.size()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
cellIndex = entry.getKey(); |
||||||
|
Head head = entry.getValue(); |
||||||
|
doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex); |
||||||
|
} |
||||||
|
// Finish
|
||||||
|
if (dataIndex >= oneRowData.size()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (cellIndex != 0) { |
||||||
|
cellIndex++; |
||||||
|
} |
||||||
|
int size = oneRowData.size() - dataIndex; |
||||||
|
for (int i = 0; i < size; i++) { |
||||||
|
doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex, |
||||||
|
int cellIndex) { |
||||||
|
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE); |
||||||
|
Cell cell = WorkBookUtil.createCell(row, cellIndex); |
||||||
|
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); |
||||||
|
Object value = oneRowData.get(dataIndex); |
||||||
|
CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(), |
||||||
|
cell, value, null); |
||||||
|
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); |
||||||
|
} |
||||||
|
|
||||||
|
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, List<Field> fieldList) { |
||||||
|
WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); |
||||||
|
BeanMap beanMap = BeanMap.create(oneRowData); |
||||||
|
Set<String> beanMapHandledSet = new HashSet<String>(); |
||||||
|
int cellIndex = 0; |
||||||
|
// If it's a class it needs to be cast by type
|
||||||
|
if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { |
||||||
|
Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); |
||||||
|
Map<Integer, ExcelContentProperty> contentPropertyMap = |
||||||
|
writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap(); |
||||||
|
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) { |
||||||
|
cellIndex = entry.getKey(); |
||||||
|
ExcelContentProperty excelContentProperty = entry.getValue(); |
||||||
|
String name = excelContentProperty.getField().getName(); |
||||||
|
if (!beanMap.containsKey(name)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Head head = headMap.get(cellIndex); |
||||||
|
WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE); |
||||||
|
Cell cell = WorkBookUtil.createCell(row, cellIndex); |
||||||
|
WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); |
||||||
|
Object value = beanMap.get(name); |
||||||
|
CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell, |
||||||
|
value, excelContentProperty); |
||||||
|
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); |
||||||
|
beanMapHandledSet.add(name); |
||||||
|
} |
||||||
|
} |
||||||
|
// Finish
|
||||||
|
if (beanMapHandledSet.size() == beanMap.size()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (cellIndex != 0) { |
||||||
|
cellIndex++; |
||||||
|
} |
||||||
|
Map<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap(); |
||||||
|
initFieldList(oneRowData.getClass(), fieldList); |
||||||
|
for (Field field : fieldList) { |
||||||
|
String filedName = field.getName(); |
||||||
|
boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName) |
||||||
|
|| ignoreMap.containsKey(filedName); |
||||||
|
if (uselessData) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Object value = beanMap.get(filedName); |
||||||
|
if (value == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); |
||||||
|
Cell cell = WorkBookUtil.createCell(row, cellIndex++); |
||||||
|
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); |
||||||
|
CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null); |
||||||
|
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void initFieldList(Class clazz, List<Field> fieldList) { |
||||||
|
if (!fieldList.isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Class tempClass = clazz; |
||||||
|
while (tempClass != null) { |
||||||
|
if (tempClass != BaseRowModel.class) { |
||||||
|
Collections.addAll(fieldList, tempClass.getDeclaredFields()); |
||||||
|
} |
||||||
|
tempClass = tempClass.getSuperclass(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
package com.alibaba.excel.write.executor; |
||||||
|
|
||||||
|
/** |
||||||
|
* Excel write Executor |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
public interface ExcelWriteExecutor { |
||||||
|
} |
@ -0,0 +1,377 @@ |
|||||||
|
package com.alibaba.excel.write.executor; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
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.usermodel.Sheet; |
||||||
|
|
||||||
|
import com.alibaba.excel.context.WriteContext; |
||||||
|
import com.alibaba.excel.enums.WriteDirectionEnum; |
||||||
|
import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum; |
||||||
|
import com.alibaba.excel.exception.ExcelGenerateException; |
||||||
|
import com.alibaba.excel.metadata.CellData; |
||||||
|
import com.alibaba.excel.metadata.Head; |
||||||
|
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
||||||
|
import com.alibaba.excel.util.CollectionUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.util.WriteHandlerUtils; |
||||||
|
import com.alibaba.excel.write.metadata.fill.AnalysisCell; |
||||||
|
import com.alibaba.excel.write.metadata.fill.FillConfig; |
||||||
|
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; |
||||||
|
|
||||||
|
import net.sf.cglib.beans.BeanMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* Fill the data into excel |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { |
||||||
|
|
||||||
|
private static final String ESCAPE_FILL_PREFIX = "\\\\\\{"; |
||||||
|
private static final String ESCAPE_FILL_SUFFIX = "\\\\\\}"; |
||||||
|
private static final String FILL_PREFIX = "{"; |
||||||
|
private static final String FILL_SUFFIX = "}"; |
||||||
|
private static final char IGNORE_CHAR = '\\'; |
||||||
|
private static final String COLLECTION_PREFIX = "."; |
||||||
|
/** |
||||||
|
* Fields to replace in the template |
||||||
|
*/ |
||||||
|
private Map<Integer, List<AnalysisCell>> templateAnalysisCache = new HashMap<Integer, List<AnalysisCell>>(8); |
||||||
|
/** |
||||||
|
* Collection fields to replace in the template |
||||||
|
*/ |
||||||
|
private Map<Integer, List<AnalysisCell>> templateCollectionAnalysisCache = |
||||||
|
new HashMap<Integer, List<AnalysisCell>>(8); |
||||||
|
/** |
||||||
|
* Style cache for collection fields |
||||||
|
*/ |
||||||
|
private Map<Integer, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache = |
||||||
|
new HashMap<Integer, Map<AnalysisCell, CellStyle>>(8); |
||||||
|
/** |
||||||
|
* Last index cache for collection fields |
||||||
|
*/ |
||||||
|
private Map<Integer, Map<AnalysisCell, Integer>> collectionLastIndexCache = |
||||||
|
new HashMap<Integer, Map<AnalysisCell, Integer>>(8); |
||||||
|
|
||||||
|
public ExcelWriteFillExecutor(WriteContext writeContext) { |
||||||
|
super(writeContext); |
||||||
|
} |
||||||
|
|
||||||
|
public void fill(Object data, FillConfig fillConfig) { |
||||||
|
if (fillConfig == null) { |
||||||
|
fillConfig = FillConfig.builder().build(true); |
||||||
|
} |
||||||
|
fillConfig.init(); |
||||||
|
if (data instanceof Collection) { |
||||||
|
List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache); |
||||||
|
Collection collectionData = (Collection)data; |
||||||
|
if (CollectionUtils.isEmpty(collectionData)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Iterator iterator = collectionData.iterator(); |
||||||
|
if (WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection()) && fillConfig.getForceNewRow()) { |
||||||
|
shiftRows(collectionData.size(), analysisCellList); |
||||||
|
} |
||||||
|
while (iterator.hasNext()) { |
||||||
|
doFill(analysisCellList, iterator.next(), fillConfig); |
||||||
|
} |
||||||
|
} else { |
||||||
|
doFill(readTemplateData(templateAnalysisCache), data, fillConfig); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void shiftRows(int size, List<AnalysisCell> analysisCellList) { |
||||||
|
if (CollectionUtils.isEmpty(analysisCellList)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
int maxRowIndex = 0; |
||||||
|
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); |
||||||
|
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo); |
||||||
|
for (AnalysisCell analysisCell : analysisCellList) { |
||||||
|
if (collectionLastIndexMap != null) { |
||||||
|
Integer lastRowIndex = collectionLastIndexMap.get(analysisCell); |
||||||
|
if (lastRowIndex != null) { |
||||||
|
if (lastRowIndex > maxRowIndex) { |
||||||
|
maxRowIndex = lastRowIndex; |
||||||
|
} |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
if (analysisCell.getRowIndex() > maxRowIndex) { |
||||||
|
maxRowIndex = analysisCell.getRowIndex(); |
||||||
|
} |
||||||
|
} |
||||||
|
Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet(); |
||||||
|
int lastRowIndex = cachedSheet.getLastRowNum(); |
||||||
|
if (maxRowIndex >= lastRowIndex) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Sheet sheet = writeContext.writeSheetHolder().getCachedSheet(); |
||||||
|
int number = size; |
||||||
|
if (collectionLastIndexMap == null) { |
||||||
|
number--; |
||||||
|
} |
||||||
|
sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number); |
||||||
|
for (AnalysisCell analysisCell : templateAnalysisCache.get(writeContext.writeSheetHolder().getSheetNo())) { |
||||||
|
if (analysisCell.getRowIndex() > maxRowIndex) { |
||||||
|
analysisCell.setRowIndex(analysisCell.getRowIndex() + number); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void doFill(List<AnalysisCell> analysisCellList, Object oneRowData, FillConfig fillConfig) { |
||||||
|
Map dataMap; |
||||||
|
if (oneRowData instanceof Map) { |
||||||
|
dataMap = (Map)oneRowData; |
||||||
|
} else { |
||||||
|
dataMap = BeanMap.create(oneRowData); |
||||||
|
} |
||||||
|
WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); |
||||||
|
Map<String, ExcelContentProperty> fieldNameContentPropertyMap = |
||||||
|
writeContext.currentWriteHolder().excelWriteHeadProperty().getFieldNameContentPropertyMap(); |
||||||
|
for (AnalysisCell analysisCell : analysisCellList) { |
||||||
|
Cell cell = getOneCell(analysisCell, fillConfig); |
||||||
|
if (analysisCell.getOnlyOneVariable()) { |
||||||
|
String variable = analysisCell.getVariableList().get(0); |
||||||
|
if (!dataMap.containsKey(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Object value = dataMap.get(variable); |
||||||
|
CellData cellData = converterAndSet(writeSheetHolder, value == null ? null : value.getClass(), cell, |
||||||
|
value, fieldNameContentPropertyMap.get(variable)); |
||||||
|
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, null, Boolean.FALSE); |
||||||
|
} else { |
||||||
|
StringBuilder cellValueBuild = new StringBuilder(); |
||||||
|
int index = 0; |
||||||
|
List<CellData> cellDataList = new ArrayList<CellData>(); |
||||||
|
for (String variable : analysisCell.getVariableList()) { |
||||||
|
cellValueBuild.append(analysisCell.getPrepareDataList().get(index++)); |
||||||
|
if (!dataMap.containsKey(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Object value = dataMap.get(variable); |
||||||
|
CellData cellData = convert(writeSheetHolder, value == null ? null : value.getClass(), cell, value, |
||||||
|
fieldNameContentPropertyMap.get(variable)); |
||||||
|
cellDataList.add(cellData); |
||||||
|
switch (cellData.getType()) { |
||||||
|
case STRING: |
||||||
|
cellValueBuild.append(cellData.getStringValue()); |
||||||
|
break; |
||||||
|
case BOOLEAN: |
||||||
|
cellValueBuild.append(cellData.getBooleanValue()); |
||||||
|
break; |
||||||
|
case NUMBER: |
||||||
|
cellValueBuild.append(cellData.getNumberValue()); |
||||||
|
break; |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
cellValueBuild.append(analysisCell.getPrepareDataList().get(index)); |
||||||
|
cell.setCellValue(cellValueBuild.toString()); |
||||||
|
WriteHandlerUtils.afterCellDispose(writeContext, cellDataList, cell, null, null, Boolean.FALSE); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Cell getOneCell(AnalysisCell analysisCell, FillConfig fillConfig) { |
||||||
|
Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet(); |
||||||
|
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) { |
||||||
|
return cachedSheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex()); |
||||||
|
} |
||||||
|
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); |
||||||
|
Sheet sheet = writeContext.writeSheetHolder().getSheet(); |
||||||
|
|
||||||
|
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo); |
||||||
|
if (collectionLastIndexMap == null) { |
||||||
|
collectionLastIndexMap = new HashMap<AnalysisCell, Integer>(16); |
||||||
|
collectionLastIndexCache.put(sheetNo, collectionLastIndexMap); |
||||||
|
} |
||||||
|
boolean isOriginalCell = false; |
||||||
|
Integer lastRowIndex; |
||||||
|
Integer lastColumnIndex; |
||||||
|
switch (fillConfig.getDirection()) { |
||||||
|
case VERTICAL: |
||||||
|
lastRowIndex = collectionLastIndexMap.get(analysisCell); |
||||||
|
if (lastRowIndex == null) { |
||||||
|
lastRowIndex = analysisCell.getRowIndex(); |
||||||
|
collectionLastIndexMap.put(analysisCell, lastRowIndex); |
||||||
|
isOriginalCell = true; |
||||||
|
} else { |
||||||
|
collectionLastIndexMap.put(analysisCell, ++lastRowIndex); |
||||||
|
} |
||||||
|
lastColumnIndex = analysisCell.getColumnIndex(); |
||||||
|
break; |
||||||
|
case HORIZONTAL: |
||||||
|
lastRowIndex = analysisCell.getRowIndex(); |
||||||
|
lastColumnIndex = collectionLastIndexMap.get(analysisCell); |
||||||
|
if (lastColumnIndex == null) { |
||||||
|
lastColumnIndex = analysisCell.getColumnIndex(); |
||||||
|
collectionLastIndexMap.put(analysisCell, lastColumnIndex); |
||||||
|
isOriginalCell = true; |
||||||
|
} else { |
||||||
|
collectionLastIndexMap.put(analysisCell, ++lastColumnIndex); |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new ExcelGenerateException("The wrong direction."); |
||||||
|
} |
||||||
|
Row row = sheet.getRow(lastRowIndex); |
||||||
|
if (row == null) { |
||||||
|
row = cachedSheet.getRow(lastRowIndex); |
||||||
|
if (row == null) { |
||||||
|
WriteHandlerUtils.beforeRowCreate(writeContext, lastRowIndex, null, Boolean.FALSE); |
||||||
|
if (fillConfig.getForceNewRow()) { |
||||||
|
row = cachedSheet.createRow(lastRowIndex); |
||||||
|
} else { |
||||||
|
row = sheet.createRow(lastRowIndex); |
||||||
|
} |
||||||
|
WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE); |
||||||
|
} |
||||||
|
} |
||||||
|
Cell cell = row.getCell(lastColumnIndex); |
||||||
|
if (cell == null) { |
||||||
|
WriteHandlerUtils.beforeCellCreate(writeContext, row, null, lastColumnIndex, null, Boolean.FALSE); |
||||||
|
cell = row.createCell(lastColumnIndex); |
||||||
|
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, null, Boolean.FALSE); |
||||||
|
} |
||||||
|
|
||||||
|
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(sheetNo); |
||||||
|
if (collectionFieldStyleMap == null) { |
||||||
|
collectionFieldStyleMap = new HashMap<AnalysisCell, CellStyle>(16); |
||||||
|
collectionFieldStyleCache.put(sheetNo, collectionFieldStyleMap); |
||||||
|
} |
||||||
|
if (isOriginalCell) { |
||||||
|
collectionFieldStyleMap.put(analysisCell, cell.getCellStyle()); |
||||||
|
} else { |
||||||
|
CellStyle cellStyle = collectionFieldStyleMap.get(analysisCell); |
||||||
|
if (cellStyle != null) { |
||||||
|
cell.setCellStyle(cellStyle); |
||||||
|
} |
||||||
|
} |
||||||
|
return cell; |
||||||
|
} |
||||||
|
|
||||||
|
private List<AnalysisCell> readTemplateData(Map<Integer, List<AnalysisCell>> analysisCache) { |
||||||
|
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo(); |
||||||
|
List<AnalysisCell> analysisCellList = analysisCache.get(sheetNo); |
||||||
|
if (analysisCellList != null) { |
||||||
|
return analysisCellList; |
||||||
|
} |
||||||
|
Sheet sheet = writeContext.writeSheetHolder().getCachedSheet(); |
||||||
|
analysisCellList = new ArrayList<AnalysisCell>(); |
||||||
|
List<AnalysisCell> collectionAnalysisCellList = new ArrayList<AnalysisCell>(); |
||||||
|
for (int i = 0; i <= sheet.getLastRowNum(); i++) { |
||||||
|
Row row = sheet.getRow(i); |
||||||
|
if (row == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
for (int j = 0; j < row.getLastCellNum(); j++) { |
||||||
|
Cell cell = row.getCell(j); |
||||||
|
if (cell == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
prepareData(cell.getStringCellValue(), analysisCellList, collectionAnalysisCellList, i, j); |
||||||
|
} |
||||||
|
} |
||||||
|
templateAnalysisCache.put(sheetNo, analysisCellList); |
||||||
|
templateCollectionAnalysisCache.put(sheetNo, collectionAnalysisCellList); |
||||||
|
return analysisCache.get(sheetNo); |
||||||
|
} |
||||||
|
|
||||||
|
private void prepareData(String value, List<AnalysisCell> analysisCellList, |
||||||
|
List<AnalysisCell> collectionAnalysisCellList, int rowIndex, int columnIndex) { |
||||||
|
if (StringUtils.isEmpty(value)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
AnalysisCell analysisCell = null; |
||||||
|
int startIndex = 0; |
||||||
|
int length = value.length(); |
||||||
|
int lastPrepareDataIndex = 0; |
||||||
|
out: |
||||||
|
while (startIndex < length) { |
||||||
|
int prefixIndex = value.indexOf(FILL_PREFIX, startIndex); |
||||||
|
if (prefixIndex < 0) { |
||||||
|
break out; |
||||||
|
} |
||||||
|
if (prefixIndex != 0) { |
||||||
|
char prefixPrefixChar = value.charAt(prefixIndex - 1); |
||||||
|
if (prefixPrefixChar == IGNORE_CHAR) { |
||||||
|
startIndex = prefixIndex + 1; |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
int suffixIndex = -1; |
||||||
|
while (suffixIndex == -1 && startIndex < length) { |
||||||
|
suffixIndex = value.indexOf(FILL_SUFFIX, startIndex + 1); |
||||||
|
if (suffixIndex < 0) { |
||||||
|
break out; |
||||||
|
} |
||||||
|
startIndex = suffixIndex + 1; |
||||||
|
char prefixSuffixChar = value.charAt(suffixIndex - 1); |
||||||
|
if (prefixSuffixChar == IGNORE_CHAR) { |
||||||
|
suffixIndex = -1; |
||||||
|
} |
||||||
|
} |
||||||
|
if (analysisCell == null) { |
||||||
|
analysisCell = new AnalysisCell(); |
||||||
|
analysisCell.setRowIndex(rowIndex); |
||||||
|
analysisCell.setColumnIndex(columnIndex); |
||||||
|
analysisCell.setOnlyOneVariable(Boolean.TRUE); |
||||||
|
List<String> variableList = new ArrayList<String>(); |
||||||
|
analysisCell.setVariableList(variableList); |
||||||
|
List<String> prepareDataList = new ArrayList<String>(); |
||||||
|
analysisCell.setPrepareDataList(prepareDataList); |
||||||
|
analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COMMON); |
||||||
|
} |
||||||
|
String variable = value.substring(prefixIndex + 1, suffixIndex); |
||||||
|
if (StringUtils.isEmpty(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (variable.startsWith(COLLECTION_PREFIX)) { |
||||||
|
variable = variable.substring(1); |
||||||
|
if (StringUtils.isEmpty(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COLLECTION); |
||||||
|
} |
||||||
|
analysisCell.getVariableList().add(variable); |
||||||
|
if (lastPrepareDataIndex == prefixIndex) { |
||||||
|
analysisCell.getPrepareDataList().add(StringUtils.EMPTY); |
||||||
|
} else { |
||||||
|
analysisCell.getPrepareDataList() |
||||||
|
.add(convertPrepareData(value.substring(lastPrepareDataIndex, prefixIndex))); |
||||||
|
analysisCell.setOnlyOneVariable(Boolean.FALSE); |
||||||
|
} |
||||||
|
lastPrepareDataIndex = suffixIndex + 1; |
||||||
|
} |
||||||
|
if (analysisCell != null) { |
||||||
|
if (lastPrepareDataIndex == length) { |
||||||
|
analysisCell.getPrepareDataList().add(StringUtils.EMPTY); |
||||||
|
} else { |
||||||
|
analysisCell.getPrepareDataList().add(convertPrepareData(value.substring(lastPrepareDataIndex))); |
||||||
|
analysisCell.setOnlyOneVariable(Boolean.FALSE); |
||||||
|
} |
||||||
|
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) { |
||||||
|
analysisCellList.add(analysisCell); |
||||||
|
} else { |
||||||
|
collectionAnalysisCellList.add(analysisCell); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String convertPrepareData(String prepareData) { |
||||||
|
prepareData = prepareData.replaceAll(ESCAPE_FILL_PREFIX, FILL_PREFIX); |
||||||
|
prepareData = prepareData.replaceAll(ESCAPE_FILL_SUFFIX, FILL_SUFFIX); |
||||||
|
return prepareData; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
package com.alibaba.excel.write.metadata.fill; |
||||||
|
|
||||||
|
import com.alibaba.excel.enums.WriteDirectionEnum; |
||||||
|
|
||||||
|
/** |
||||||
|
* Fill config |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
**/ |
||||||
|
public class FillConfig { |
||||||
|
private WriteDirectionEnum direction; |
||||||
|
/** |
||||||
|
* Create a new row each time you use the list parameter.The default create if necessary. |
||||||
|
* <p> |
||||||
|
* Warnning:If you use <code>forceNewRow</code> set true, will not be able to use asynchronous write file, simply |
||||||
|
* say the whole file will be stored in memory. |
||||||
|
*/ |
||||||
|
private Boolean forceNewRow; |
||||||
|
private boolean hasInit; |
||||||
|
|
||||||
|
public WriteDirectionEnum getDirection() { |
||||||
|
return direction; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDirection(WriteDirectionEnum direction) { |
||||||
|
this.direction = direction; |
||||||
|
} |
||||||
|
|
||||||
|
public Boolean getForceNewRow() { |
||||||
|
return forceNewRow; |
||||||
|
} |
||||||
|
|
||||||
|
public void setForceNewRow(Boolean forceNewRow) { |
||||||
|
this.forceNewRow = forceNewRow; |
||||||
|
} |
||||||
|
|
||||||
|
public void init() { |
||||||
|
if (hasInit) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (direction == null) { |
||||||
|
direction = WriteDirectionEnum.VERTICAL; |
||||||
|
} |
||||||
|
if (forceNewRow == null) { |
||||||
|
forceNewRow = Boolean.FALSE; |
||||||
|
} |
||||||
|
hasInit = true; |
||||||
|
} |
||||||
|
|
||||||
|
public static FillConfigBuilder builder() { |
||||||
|
return new FillConfigBuilder(); |
||||||
|
} |
||||||
|
|
||||||
|
public static class FillConfigBuilder { |
||||||
|
private FillConfig fillConfig; |
||||||
|
|
||||||
|
FillConfigBuilder() { |
||||||
|
this.fillConfig = new FillConfig(); |
||||||
|
} |
||||||
|
|
||||||
|
public FillConfigBuilder direction(WriteDirectionEnum direction) { |
||||||
|
fillConfig.setDirection(direction); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public FillConfigBuilder forceNewRow(Boolean forceNewRow) { |
||||||
|
fillConfig.setForceNewRow(forceNewRow); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public FillConfig build() { |
||||||
|
return build(true); |
||||||
|
} |
||||||
|
|
||||||
|
public FillConfig build(boolean autoInit) { |
||||||
|
if (autoInit) { |
||||||
|
fillConfig.init(); |
||||||
|
} |
||||||
|
return fillConfig; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package com.alibaba.easyexcel.test.demo.fill; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class FillData { |
||||||
|
private String name; |
||||||
|
private double number; |
||||||
|
} |
@ -0,0 +1,181 @@ |
|||||||
|
package com.alibaba.easyexcel.test.demo.fill; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.junit.Ignore; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import com.alibaba.easyexcel.test.util.TestFileUtil; |
||||||
|
import com.alibaba.excel.EasyExcel; |
||||||
|
import com.alibaba.excel.ExcelWriter; |
||||||
|
import com.alibaba.excel.enums.WriteDirectionEnum; |
||||||
|
import com.alibaba.excel.write.metadata.WriteSheet; |
||||||
|
import com.alibaba.excel.write.metadata.fill.FillConfig; |
||||||
|
|
||||||
|
/** |
||||||
|
* 写的填充写法 |
||||||
|
* |
||||||
|
* @author Jiaju Zhuang |
||||||
|
*/ |
||||||
|
@Ignore |
||||||
|
public class FillTest { |
||||||
|
/** |
||||||
|
* 最简单的填充 |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void simpleFill() { |
||||||
|
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||||
|
String templateFileName = |
||||||
|
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "simple.xlsx"; |
||||||
|
|
||||||
|
// 方案1 根据对象填充
|
||||||
|
String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
|
||||||
|
FillData fillData = new FillData(); |
||||||
|
fillData.setName("张三"); |
||||||
|
fillData.setNumber(5.2); |
||||||
|
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData); |
||||||
|
|
||||||
|
// 方案2 根据Map填充
|
||||||
|
fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>(); |
||||||
|
map.put("name", "张三"); |
||||||
|
map.put("number", 5.2); |
||||||
|
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 填充列表 |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void listFill() { |
||||||
|
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||||
|
// 填充list 的时候还要注意 模板中{.} 多了个点 表示list
|
||||||
|
String templateFileName = |
||||||
|
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "list.xlsx"; |
||||||
|
|
||||||
|
// 方案1 一下子全部放到内存里面 并填充
|
||||||
|
String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
// 这里 会填充到第一个sheet, 然后文件流会自动关闭
|
||||||
|
EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data()); |
||||||
|
|
||||||
|
// 方案2 分多次 填充 会使用文件缓存(省内存)
|
||||||
|
fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); |
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build(); |
||||||
|
excelWriter.fill(data(), writeSheet); |
||||||
|
excelWriter.fill(data(), writeSheet); |
||||||
|
// 千万别忘记关闭流
|
||||||
|
excelWriter.finish(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 复杂的填充 |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void complexFill() { |
||||||
|
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||||
|
// {} 代表普通变量 {.} 代表是list的变量
|
||||||
|
String templateFileName = |
||||||
|
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complex.xlsx"; |
||||||
|
|
||||||
|
String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); |
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build(); |
||||||
|
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
|
||||||
|
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
|
||||||
|
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
|
||||||
|
// 如果数据量大 list不是最后一行 参照下一个
|
||||||
|
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); |
||||||
|
excelWriter.fill(data(), fillConfig, writeSheet); |
||||||
|
excelWriter.fill(data(), fillConfig, writeSheet); |
||||||
|
Map<String, Object> map = new HashMap<String, Object>(); |
||||||
|
map.put("date", "2019年10月9日13:28:28"); |
||||||
|
map.put("total", 1000); |
||||||
|
excelWriter.fill(map, writeSheet); |
||||||
|
excelWriter.finish(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据量大的复杂填充 |
||||||
|
* <p> |
||||||
|
* 这里的解决方案是 确保模板list为最后一行,然后再拼接table.还有03版没救,只能刚正面加内存。 |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void complexFillWithTable() { |
||||||
|
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||||
|
// {} 代表普通变量 {.} 代表是list的变量
|
||||||
|
// 这里模板 删除了list以后的数据,也就是统计的这一行
|
||||||
|
String templateFileName = |
||||||
|
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complexFillWithTable.xlsx"; |
||||||
|
|
||||||
|
String fileName = TestFileUtil.getPath() + "complexFillWithTable" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); |
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build(); |
||||||
|
// 直接写入数据
|
||||||
|
excelWriter.fill(data(), writeSheet); |
||||||
|
excelWriter.fill(data(), writeSheet); |
||||||
|
|
||||||
|
// 写入list之前的数据
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>(); |
||||||
|
map.put("date", "2019年10月9日13:28:28"); |
||||||
|
excelWriter.fill(map, writeSheet); |
||||||
|
|
||||||
|
// list 后面还有个统计 想办法手动写入
|
||||||
|
// 这里偷懒直接用list 也可以用对象
|
||||||
|
List<List<String>> totalListList = new ArrayList<List<String>>(); |
||||||
|
List<String> totalList = new ArrayList<String>(); |
||||||
|
totalListList.add(totalList); |
||||||
|
totalList.add(null); |
||||||
|
totalList.add(null); |
||||||
|
totalList.add(null); |
||||||
|
// 第四列
|
||||||
|
totalList.add("统计:1000"); |
||||||
|
// 这里是write 别和fill 搞错了
|
||||||
|
excelWriter.write(totalListList, writeSheet); |
||||||
|
excelWriter.finish(); |
||||||
|
// 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动,也不支持备注这种的写入,所以也排除了可以
|
||||||
|
// 新建一个 然后一点点复制过来的方案,最后导致list需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 横向的填充 |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void horizontalFill() { |
||||||
|
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
|
||||||
|
// {} 代表普通变量 {.} 代表是list的变量
|
||||||
|
String templateFileName = |
||||||
|
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "horizontal.xlsx"; |
||||||
|
|
||||||
|
String fileName = TestFileUtil.getPath() + "horizontalFill" + System.currentTimeMillis() + ".xlsx"; |
||||||
|
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); |
||||||
|
WriteSheet writeSheet = EasyExcel.writerSheet().build(); |
||||||
|
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); |
||||||
|
excelWriter.fill(data(), fillConfig, writeSheet); |
||||||
|
excelWriter.fill(data(), fillConfig, writeSheet); |
||||||
|
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>(); |
||||||
|
map.put("date", "2019年10月9日13:28:28"); |
||||||
|
excelWriter.fill(map, writeSheet); |
||||||
|
|
||||||
|
// 别忘记关闭流
|
||||||
|
excelWriter.finish(); |
||||||
|
} |
||||||
|
|
||||||
|
private List<FillData> data() { |
||||||
|
List<FillData> list = new ArrayList<FillData>(); |
||||||
|
for (int i = 0; i < 10; i++) { |
||||||
|
FillData fillData = new FillData(); |
||||||
|
list.add(fillData); |
||||||
|
fillData.setName("张三"); |
||||||
|
fillData.setNumber(5.2); |
||||||
|
} |
||||||
|
return list; |
||||||
|
} |
||||||
|
} |