ExcelBuilderImpl.java 13.4 KB
Newer Older
J
update  
jipengfei.jpf 已提交
1 2
package com.alibaba.excel.write;

Z
zhuangjiaju 已提交
3
import java.lang.reflect.Field;
Z
zhuangjiaju 已提交
4
import java.util.HashSet;
clevertension's avatar
clevertension 已提交
5
import java.util.List;
Z
zhuangjiaju 已提交
6
import java.util.Map;
Z
zhuangjiaju 已提交
7
import java.util.Set;
clevertension's avatar
clevertension 已提交
8 9 10

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
11
import org.apache.poi.ss.usermodel.Sheet;
clevertension's avatar
clevertension 已提交
12 13
import org.apache.poi.ss.util.CellRangeAddress;

14
import com.alibaba.excel.context.WriteContext;
clevertension's avatar
clevertension 已提交
15 16
import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.converters.Converter;
17
import com.alibaba.excel.converters.ConverterKeyBuild;
Z
zhuangjiaju 已提交
18
import com.alibaba.excel.enums.WriteLastRowType;
Z
zhuangjiaju 已提交
19
import com.alibaba.excel.exception.ExcelDataConvertException;
20
import com.alibaba.excel.exception.ExcelGenerateException;
Z
zhuangjiaju 已提交
21
import com.alibaba.excel.metadata.CellData;
22
import com.alibaba.excel.metadata.Head;
Z
zhuangjiaju 已提交
23
import com.alibaba.excel.metadata.property.ExcelContentProperty;
24
import com.alibaba.excel.util.CollectionUtils;
25
import com.alibaba.excel.util.FileUtils;
26
import com.alibaba.excel.util.WorkBookUtil;
27 28 29
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.WriteHandler;
30 31 32 33
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import com.alibaba.excel.write.metadata.holder.WriteHolder;
Z
zhuangjiaju 已提交
34
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
J
update  
jipengfei.jpf 已提交
35

clevertension's avatar
clevertension 已提交
36
import net.sf.cglib.beans.BeanMap;
37

J
update  
jipengfei.jpf 已提交
38 39 40
/**
 * @author jipengfei
 */
Z
zhuangjiaju 已提交
41
public class ExcelBuilderImpl implements ExcelBuilder {
Z
zhuangjiaju 已提交
42

43
    private WriteContext context;
Z
zhuangjiaju 已提交
44

45
    public ExcelBuilderImpl(WriteWorkbook writeWorkbook) {
46 47 48 49 50 51 52 53 54 55 56
        try {
            // Create temporary cache directory at initialization time to avoid POI concurrent write bugs
            FileUtils.createPoiFilesDirectory();
            context = new WriteContextImpl(writeWorkbook);
        } catch (RuntimeException e) {
            finish();
            throw e;
        } catch (Throwable e) {
            finish();
            throw new ExcelGenerateException(e);
        }
J
update  
jipengfei.jpf 已提交
57 58
    }

Z
zhuangjiaju 已提交
59
    private void doAddContent(List data) {
60 61 62
        if (CollectionUtils.isEmpty(data)) {
            return;
        }
Z
zhuangjiaju 已提交
63 64 65 66 67 68 69 70 71 72
        WriteSheetHolder writeSheetHolder = context.writeSheetHolder();
        Sheet currentSheet = writeSheetHolder.getSheet();
        int lastRowNum = currentSheet.getLastRowNum();
        // 'lastRowNum' doesn't matter if it has one or zero,is's zero
        if (lastRowNum == 0 && WriteLastRowType.EMPTY == writeSheetHolder.getWriteLastRowType()) {
            lastRowNum--;
        }
        if (!data.isEmpty()) {
            context.writeSheetHolder().setWriteLastRowType(WriteLastRowType.HAVE_DATA);
        }
73
        if (context.currentWriteHolder().isNew()) {
Z
zhuangjiaju 已提交
74
            lastRowNum += context.currentWriteHolder().relativeHeadRowIndex();
75
        }
76
        for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
Z
zhuangjiaju 已提交
77
            int n = relativeRowIndex + lastRowNum + 1;
78
            addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex);
J
update  
jipengfei.jpf 已提交
79 80 81
        }
    }

82
    @Override
83 84
    public void addContent(List data, WriteSheet writeSheet) {
        addContent(data, writeSheet, null);
J
update  
jipengfei.jpf 已提交
85 86
    }

87
    @Override
88
    public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) {
89 90 91 92 93 94 95 96 97 98 99
        try {
            context.currentSheet(writeSheet);
            context.currentTable(writeTable);
            doAddContent(data);
        } catch (RuntimeException e) {
            finish();
            throw e;
        } catch (Throwable e) {
            finish();
            throw new ExcelGenerateException(e);
        }
J
update  
jipengfei.jpf 已提交
100 101
    }

102
    @Override
Z
zhuangjiaju 已提交
103
    public void finish() {
Z
zhuangjiaju 已提交
104 105 106
        if (context != null) {
            context.finish();
        }
107 108
    }

109
    @Override
Z
zhuangjiaju 已提交
110 111
    public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
        CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
112
        context.writeSheetHolder().getSheet().addMergedRegion(cra);
Z
zhuangjiaju 已提交
113 114
    }

115 116
    private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex) {
        beforeRowCreate(n, relativeRowIndex);
117
        Row row = WorkBookUtil.createRow(context.writeSheetHolder().getSheet(), n);
118
        afterRowCreate(row, relativeRowIndex);
Z
zhuangjiaju 已提交
119
        if (oneRowData instanceof List) {
120
            addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex);
Z
zhuangjiaju 已提交
121
        } else {
122
            addJavaObjectToExcel(oneRowData, row, relativeRowIndex);
Z
zhuangjiaju 已提交
123
        }
J
update  
jipengfei.jpf 已提交
124 125
    }

126
    private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
127
        List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
128 129 130 131 132
        if (handlerList == null || handlerList.isEmpty()) {
            return;
        }
        for (WriteHandler writeHandler : handlerList) {
            if (writeHandler instanceof RowWriteHandler) {
133 134
                ((RowWriteHandler)writeHandler).beforeRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
                    rowIndex, relativeRowIndex, false);
135 136 137 138 139
            }
        }
    }

    private void afterRowCreate(Row row, int relativeRowIndex) {
140
        List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(RowWriteHandler.class);
141 142 143 144 145
        if (handlerList == null || handlerList.isEmpty()) {
            return;
        }
        for (WriteHandler writeHandler : handlerList) {
            if (writeHandler instanceof RowWriteHandler) {
146 147
                ((RowWriteHandler)writeHandler).afterRowCreate(context.writeSheetHolder(), context.writeTableHolder(),
                    row, relativeRowIndex, false);
148 149
            }
        }
150 151
        if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
            context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row);
152 153 154 155
        }
    }

    private void addBasicTypeToExcel(List<Object> oneRowData, Row row, int relativeRowIndex) {
156 157 158
        if (CollectionUtils.isEmpty(oneRowData)) {
            return;
        }
159
        Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Z
zhuangjiaju 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        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++;
        }
        for (int i = 0; i < oneRowData.size() - dataIndex; i++) {
            doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++);
J
update  
jipengfei.jpf 已提交
179 180 181
        }
    }

Z
zhuangjiaju 已提交
182 183 184 185 186
    private void doAddBasicTypeToExcel(List<Object> oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex,
        int cellIndex) {
        beforeCellCreate(row, head, relativeRowIndex);
        Cell cell = WorkBookUtil.createCell(row, cellIndex);
        Object value = oneRowData.get(dataIndex);
187
        converterAndSet(context.currentWriteHolder(), value.getClass(), cell, value, null);
Z
zhuangjiaju 已提交
188 189 190
        afterCellCreate(head, cell, relativeRowIndex);
    }

191
    private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex) {
192
        WriteHolder currentWriteHolder = context.currentWriteHolder();
193
        BeanMap beanMap = BeanMap.create(oneRowData);
Z
zhuangjiaju 已提交
194
        Set<String> beanMapHandledSet = new HashSet<String>();
195
        Map<Integer, Head> headMap = context.currentWriteHolder().excelWriteHeadProperty().getHeadMap();
Z
zhuangjiaju 已提交
196
        Map<Integer, ExcelContentProperty> contentPropertyMap =
197
            context.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap();
Z
zhuangjiaju 已提交
198 199 200 201 202 203 204 205 206
        int cellIndex = 0;
        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);
207
            beforeCellCreate(row, head, relativeRowIndex);
Z
zhuangjiaju 已提交
208 209
            Cell cell = WorkBookUtil.createCell(row, cellIndex);
            Object value = beanMap.get(name);
210
            converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell, value,
Z
zhuangjiaju 已提交
211
                excelContentProperty);
212
            afterCellCreate(head, cell, relativeRowIndex);
Z
zhuangjiaju 已提交
213
            beanMapHandledSet.add(name);
Z
zhuangjiaju 已提交
214 215
        }
        // Finish
Z
zhuangjiaju 已提交
216
        if (beanMapHandledSet.size() == beanMap.size()) {
Z
zhuangjiaju 已提交
217
            return;
J
update  
jipengfei.jpf 已提交
218
        }
Z
zhuangjiaju 已提交
219 220 221
        if (cellIndex != 0) {
            cellIndex++;
        }
Z
zhuangjiaju 已提交
222
        Map<String, Field> ignoreMap = context.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap();
Z
zhuangjiaju 已提交
223 224
        Set<Map.Entry<String, Object>> entrySet = beanMap.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
Z
zhuangjiaju 已提交
225 226
            if (entry.getValue() == null || beanMapHandledSet.contains(entry.getKey())
                || ignoreMap.containsKey(entry.getKey())) {
Z
zhuangjiaju 已提交
227 228
                continue;
            }
Z
zhuangjiaju 已提交
229 230
            beforeCellCreate(row, null, relativeRowIndex);
            Cell cell = WorkBookUtil.createCell(row, cellIndex++);
231
            converterAndSet(currentWriteHolder, entry.getValue().getClass(), cell, entry.getValue(), null);
Z
zhuangjiaju 已提交
232 233 234 235
            afterCellCreate(null, cell, relativeRowIndex);
        }
    }

236
    private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
237
        List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
238 239 240 241 242
        if (handlerList == null || handlerList.isEmpty()) {
            return;
        }
        for (WriteHandler writeHandler : handlerList) {
            if (writeHandler instanceof CellWriteHandler) {
243 244
                ((CellWriteHandler)writeHandler).beforeCellCreate(context.writeSheetHolder(),
                    context.writeTableHolder(), row, head, relativeRowIndex, false);
245 246 247 248 249 250
            }
        }

    }

    private void afterCellCreate(Head head, Cell cell, int relativeRowIndex) {
251
        List<WriteHandler> handlerList = context.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class);
252 253 254 255 256
        if (handlerList == null || handlerList.isEmpty()) {
            return;
        }
        for (WriteHandler writeHandler : handlerList) {
            if (writeHandler instanceof CellWriteHandler) {
257 258
                ((CellWriteHandler)writeHandler).afterCellCreate(context.writeSheetHolder(), context.writeTableHolder(),
                    cell, head, relativeRowIndex, false);
259 260
            }
        }
261 262
        if (null != context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) {
            context.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell);
263 264 265
        }
    }

266 267
    private void converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
        ExcelContentProperty excelContentProperty) {
Z
zhuangjiaju 已提交
268 269 270
        if (value == null) {
            return;
        }
271 272 273
        if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) {
            value = ((String)value).trim();
        }
Z
zhuangjiaju 已提交
274
        CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty);
Z
zhuangjiaju 已提交
275 276 277 278
        if (cellData == null || cellData.getType() == null) {
            throw new ExcelDataConvertException(
                "Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum());
        }
279 280 281
        if (cellData.getFormula() != null && cellData.getFormula()) {
            cell.setCellFormula(cellData.getFormulaValue());
        }
Z
zhuangjiaju 已提交
282 283
        switch (cellData.getType()) {
            case STRING:
284
                cell.setCellValue(cellData.getStringValue());
Z
zhuangjiaju 已提交
285 286
                return;
            case BOOLEAN:
287
                cell.setCellValue(cellData.getBooleanValue());
Z
zhuangjiaju 已提交
288 289
                return;
            case NUMBER:
290
                cell.setCellValue(cellData.getDoubleValue());
Z
zhuangjiaju 已提交
291 292 293 294
                return;
            default:
                throw new ExcelDataConvertException("Not supported data:" + value + " return type:" + cell.getCellType()
                    + "at row:" + cell.getRow().getRowNum());
J
update  
jipengfei.jpf 已提交
295 296
        }
    }
Z
zhuangjiaju 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

    private CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value,
        ExcelContentProperty excelContentProperty) {
        if (value instanceof CellData) {
            return (CellData)value;
        }
        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);
        }
        return cellData;
    }
J
update  
jipengfei.jpf 已提交
324
}