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

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

package com.moon.poi.excel.table;

import com.moon.core.lang.JoinerUtil;
import com.moon.core.lang.StringUtil;
import com.moon.core.lang.ref.IntAccessor;
import com.moon.poi.excel.CellFactory;
import com.moon.poi.excel.PropertyControl;
import com.moon.poi.excel.RowFactory;
import com.moon.poi.excel.annotation.style.StyleBuilder;

import java.util.List;
import java.util.Map;

/**
 * @author moonsky
 */
class TableCol implements Comparable {

    private final static int MAX = Integer.MAX_VALUE / 2;

    final static short DEFAULT_HEIGHT = -1;

    private final String name;
    private final String defaultClassname;
    private final String[] titles;
    private final short[] rowsHeight4Head;
    private final int offsetHeadRowsCnt;
    // 列宽,如果当前是实体组合列,则为 null
    private final Integer width;
    private final int offset;
    private final int order;
    private final PropertyControl control;
    private final boolean fillSkipped;
    private final CellSetter setter;

    TableCol(AttrConfig config) {
        Attribute attr = config.getAttribute();
        this.control = attr.getValueGetter();
        this.titles = attr.getTitles();
        this.rowsHeight4Head = attr.getHeadHeightArr();

        this.name = attr.getName();
        this.order = attr.getOrder();
        this.width = attr.getColumnWidth();

        this.setter = CellSetter.of(attr);

        this.offset = attr.getOffsetVal();
        this.offsetHeadRowsCnt = Math.min(attr.getOffsetHeadRows(), MAX);
        this.fillSkipped = attr.isOffsetFillSkipped();
        this.defaultClassname = StyleUtil.getTableColClassname(config);
    }

    protected final PropertyControl getControl() { return control; }

    protected final int getOffset() { return offset; }

    protected final boolean isFillSkipped() { return fillSkipped; }

    int getDepth() { return 1; }

    /*
     * 收集样式
     */

    void collectStyleMap(Map collector) {}

    /*
     * 列宽
     */

    final void appendOffsetWidth(List columnsWidth) {
        int dftWidth = DEFAULT_HEIGHT;
        for (int i = 0; i < offset; i++) {
            columnsWidth.add(dftWidth);
        }
    }

    void appendColumnWidth(List columnsWidth) {
        this.appendOffsetWidth(columnsWidth);
        columnsWidth.add(width == null ? DEFAULT_HEIGHT : width);
    }

    /*
     * 表头标题
     */

    void appendTitlesAtRowIdx(List rowTitles, int rowIdx) {
        appendTitles4Offset(rowTitles, rowIdx);
        rowTitles.add(headCellAtIdx(rowIdx));
    }

    final void appendTitles4Offset(List rowTitles, int rowIdx) {
        HeadCell thisCell = HeadCell.EMPTY;
        if (rowIdx + offsetHeadRowsCnt < getHeaderRowsCount()) {
            thisCell = headCellAtIdx(rowIdx);
        }
        for (int i = 0; i < offset; i++) {
            rowTitles.add(thisCell);
        }
    }

    final HeadCell headCellAtIdx(int rowIdx) {
        return new HeadCell(titleAtIdx(rowIdx), rowHeightAtIdx(rowIdx), fillSkipped);
    }

    private final short rowHeightAtIdx(int rowIdx) {
        // 表头行高
        short[] values = this.rowsHeight4Head;
        int count = values.length;
        int heightIdx = rowIdx < count ? rowIdx : count - 1;
        return inRange(heightIdx, count) ? values[heightIdx] : DEFAULT_HEIGHT;
    }

    private final String titleAtIdx(int rowIdx) {
        // 表头标题
        int length = getHeaderRowsLength();
        int index = rowIdx < length ? rowIdx : length - 1;
        return inRange(index, length) ? titles[index] : null;
    }

    private static boolean inRange(int index, int length) { return index > -1 && index < length; }

    /*
     * 行列数计算
     */

    /**
     * 自身表头所占行数
     *
     * @return
     */
    final int getHeaderRowsLength() { return titles.length; }

    /**
     * 整“列”表头所占行数
     * 

* 这里单独写成一个获取 length 的方法是为了后面支持 ColumnGroup 时用计算的方式获取最大长度 * * @return */ int getHeaderRowsCount() { return getHeaderRowsLength(); } /** * 横跨单元格列数 * * @return */ int getCrossColsCount() { return offset + 1; } /** * 执行偏移 * * @param factory * @param indexer */ private final void doOffsetCells(RowFactory factory, IntAccessor indexer) { int offset = this.offset; if (fillSkipped) { int start = indexer.get(); for (int i = 0; i < offset; i++) { factory.index(i + start); } } indexer.increment(offset); } /** * 当前单元格实际有意义位置的单元格 * * @param rowFactory * @param indexer * * @return */ final CellFactory indexedCell(RowFactory rowFactory, IntAccessor indexer) { doOffsetCells(rowFactory, indexer); return rowFactory.index(indexer.getAndIncrement()); } /** * 跳过当前单元格(用在数据 null 时) * * @param factory * @param indexer */ final void skip(RowFactory factory, IntAccessor indexer) { if (fillSkipped) { indexedCell(factory, indexer); } else { indexer.increment(offset + 1); } } final void applyClassname(CellFactory factory) { if (defaultClassname != null) { factory.styleAs(defaultClassname); } } final void setNormalVal(CellFactory factory, Object value) { setter.set(factory, value); applyClassname(factory); } void render(TableProxy proxy) { if (proxy.isSkipped()) { proxy.skip(getOffset(), isFillSkipped()); } else { CellFactory cellFactory = proxy.indexedCell(getOffset(), isFillSkipped()); Object thisData = proxy.getThisData(getControl()); setNormalVal(cellFactory, thisData); } } void render(IntAccessor indexer, RowFactory factory, Object data) { if (data == null) { skip(factory, indexer); } else { CellFactory cellFactory = indexedCell(factory, indexer); setNormalVal(cellFactory, control.control(data)); } } @Override public final int compareTo(TableCol o) { return this.order - o.order; } @Override public String toString() { final StringBuilder sb = new StringBuilder("TableCol: "); sb.append(name).append("; Titles: "); sb.append(StringUtil.defaultIfEmpty(JoinerUtil.join(titles), "<空>")); return sb.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy