All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moon.poi.excel.table.TableRenderer Maven / Gradle / Ivy

package com.moon.poi.excel.table;

import com.moon.core.lang.ref.IntAccessor;
import com.moon.core.util.MapUtil;
import com.moon.poi.excel.*;
import com.moon.poi.excel.annotation.style.StyleBuilder;
import com.moon.poi.excel.annotation.style.StyleFontBuilder;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * @author moonsky
 */
final class TableRenderer implements Renderer {

    private final static TableCol[] EMPTY = new TableCol[0];

    private final Map definitions;
    private final Class targetClass;
    private final List[] tableHeadCells;
    private final List[] headerCells;
    private final Integer[] columnsWidth;
    private final TableCol[] columns;
    private final int depth;

    TableRenderer(Class targetClass, Map styleMap, TableCol[] columns) {
        this.columns = columns == null ? EMPTY : columns;
        // 计算表头行数
        int maxTitleRowCount = HeadUtil.maxHeaderRowNum(columns);
        // 获取所有表头单元格配置信息
        List[] tableHead = HeadUtil.collectTableHead(columns, maxTitleRowCount);
        // 列宽
        Integer[] columnsWidth = HeadUtil.collectColumnsWidth(columns);
        // 计算表头合并的单元格
        List[] headerCells = HeadUtil.collectHeaderCells(tableHead);

        this.depth = HeadUtil.groupDepth(columns);
        // 收集样式
        Map definitionsMap = MapUtil.newHashMap(styleMap);
        for (TableCol column : columns) {
            column.collectStyleMap(definitionsMap);
        }
        this.definitions = MapUtil.immutableIfEmpty(definitionsMap);

        this.targetClass = targetClass;
        this.headerCells = headerCells;
        this.tableHeadCells = tableHead;
        this.columnsWidth = columnsWidth;
    }

    public int getDepth() { return depth; }

    public Class getTargetClass() { return targetClass; }

    /**
     * 获取表头行数
     *
     * @return 行数或 0
     */
    int getHeaderRowsCount() {
        Object[] cells = this.headerCells;
        return cells == null ? 0 : cells.length;
    }

    /**
     * 内部方法,获取表头列数
     *
     * @return 如果存在表头,返回表头列数,否则返回 0
     */
    final int getHeaderColsCount() {
        TableCol[] cols = this.columns;
        int columnsCount = 0;
        for (TableCol col : cols) {
            columnsCount += col.getCrossColsCount();
        }
        return columnsCount;
    }

    final void collectStyleMap(Map collector) {
        collector.putAll(definitions);
    }

    void appendColumnWidth(List columnsWidth) {
        Integer[] widthArr = this.columnsWidth;
        for (Integer width : widthArr) {
            columnsWidth.add(width == null ? -1 : width);
        }
    }

    final void appendTitlesAtRowIdx(List rowTitles, int rowIdx) {
        int rowsCount = getHeaderRowsCount();
        if (rowsCount < 1) {
            int length = getHeaderColsCount();
            for (int i = 0; i < length; i++) {
                rowTitles.add(HeadCell.EMPTY);
            }
        } else if (rowIdx < rowsCount) {
            rowTitles.addAll(tableHeadCells[rowIdx]);
        } else {
            int index = rowsCount - 1;
            rowTitles.addAll(tableHeadCells[index]);
        }
    }

    private short maxHeight(HeaderCell cell, short otherHeight) {
        return cell != null && cell.getHeight() > otherHeight ? cell.getHeight() : otherHeight;
    }

    private void maxHeight(RowFactory factory, List cells) {
        short finalHeight = -1;
        if (cells != null) {
            for (HeaderCell cell : cells) {
                finalHeight = maxHeight(cell, finalHeight);
            }
        }
        if (finalHeight > -1) {
            factory.height(finalHeight);
        }
    }

    @Override
    public void title(SheetFactory factory, TableTitle title) {
        if (title == null || title.getTitle() == null) {
            return;
        }
        int colspan;
        List[] cells = this.headerCells;
        if (cells.length > 0) {
            colspan = cells[0].size();
        } else {
            colspan = getHeaderColsCount();
        }

        RowFactory rowFactory = factory.row();
        CellFactory cellFactory = rowFactory.newCell(1, colspan).val(title.getTitle());
        if (title.getClassname() != null) {
            cellFactory.styleAs(title.getClassname());
        }
        if (title.getHeight() > -1) {
            rowFactory.height(title.getHeight());
        }
    }

    /**
     * 渲染表头
     *
     * @param sheetFactory sheet 渲染器
     */
    @Override
    public void renderHead(SheetFactory sheetFactory) {
        Sheet sheet = sheetFactory.getSheet();
        List[] headerCells = this.headerCells;
        final int rowIdx = sheetFactory.getRowIndex();
        for (List rowCells : headerCells) {
            RowFactory factory = sheetFactory.row();
            for (HeaderCell cell : rowCells) {
                // 设置表头标题
                if (cell.isOffsetCell()) {
                    if (cell.isFillSkipped()) {
                        factory.index(cell.getColIdx());
                    }
                } else {
                    factory.index(cell.getColIdx()).val(cell.getValue());
                }
                // 合并表头单元格
                cell.merge(sheet, rowIdx);
            }
            maxHeight(factory, rowCells);
        }

        // 设置列宽
        sheetFactory.setColumnsWidthBegin(0, this.columnsWidth);
    }

    final void definitionStyles(TableFactory factory) {
        for (Map.Entry builderEntry : definitions.entrySet()) {
            final String classname = builderEntry.getKey();
            StyleBuilder builder = builderEntry.getValue();
            if (builder instanceof StyleFontBuilder) {
                BiConsumer consumer = (BiConsumer) builder;
                factory.definitionStyle(classname, consumer);
            } else {
                factory.definitionStyle(builderEntry.getKey(), builder);
            }
        }
    }

    /**
     * 渲染一条数据
     *
     * @param sheetFactory sheet 渲染器
     * @param iterator     数据集合,
     *                     如果存在第一项(first != null),集合中从第一项开始迭代
     *                     否则从第二项开始迭代
     * @param first        第一项数据(有些数据类型不能获取到第一条数据,所以要单独传第一条数据)
     */
    @Override
    public void renderBody(SheetFactory sheetFactory, Iterator iterator, Object first) {
        doRenderBody1(sheetFactory, iterator, first);
    }

    private void doRenderBody1(SheetFactory sheetFactory, Iterator iterator, Object first) {
        TableProxy proxy = new TableProxy(sheetFactory, definitions, depth);
        if (first != null) {
            renderRecord(proxy, first);
        }
        if (iterator != null) {
            while (iterator.hasNext()) {
                renderRecord(proxy, iterator.next());
            }
        }
    }

    private void renderRecord(TableProxy proxy, Object data) {
        proxy.setRowData(data);
        proxy.nextRow();
        doRenderRow(proxy);
    }

    final void doRenderRow(TableProxy proxy) {
        for (TableCol column : columns) {
            column.render(proxy);
        }
    }

    final void doRenderRow(IntAccessor indexer, RowFactory rowFactory, Object entityData) {
        for (TableCol column : columns) {
            column.render(indexer, rowFactory, entityData);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy