Estrategia de fusión de celdas de fila universal easyexcel

La combinación de celdas de la tabla ElementUI debe devolver los siguientes datos, que representan el número de filas y columnas que se fusionarán. A continuación, solo se analizará la combinación de filas.

      objectSpanMethod({ row, column, rowIndex, columnIndex }) {
        if (columnIndex === 0) {
          if (rowIndex % 2 === 0) {
            return {
              rowspan: 2,
              colspan: 1
            };
          } else {
            return {
              rowspan: 0,
              colspan: 0
            };
          }
        }
      }

El código anterior significa que la primera columna se fusiona cada dos filas y el momento de la fusión está en la primera fila. Es decir, cuando el número de filas es 1, 3, 5 ... (los subíndices son 0, 2, 4 ...), fusionar (el rowIndex de la primera fila de la tabla elementUI es 0, independientemente de la fila del encabezado) , el código java a continuación es de

1,3,5 .. Establezca la línea de inicio de fusión y luego fusionar en 2,4,6 ... (es decir, fusionar en la última fila de las celdas que se fusionarán). Esta es una fusión cíclica, y la mayor parte del negocio real no es así, por lo que el punto clave es el juicio de la declaración condicional.

Como se mencionó anteriormente, el código java se pasa 1, 3, 5 .., aquí ya no hay una combinación de bucle, sino el número de fila de la primera celda cuando se combinan celdas. Por ejemplo, si desea fusionar las filas 2, 3 y 4 en la primera columna, entonces necesita 2. Combine las filas 5, 6, 7 y 8 en la primera columna, por lo que todo lo que necesita es 5. Entonces, ¿cómo saber si es 2 o 5? De hecho, siempre que agregue un parámetro booleano a la segunda fila de datos, el valor de verdadero representa la fila inicial de la celda que se fusionará y la no inicial la fila se establece en falso. De esta manera, los números de fila de juicio 2 y 5 se convierten en parámetros de tipo booleano para juzgar los datos de fila correspondientes. Entonces debe haber este parámetro en la fila, para que cualquier fila pueda fusionarse. (Si diferentes columnas y filas se combinan de manera diferente, diferentes columnas pueden corresponder a diferentes parámetros booleanos y al número de filas que se fusionarán en el espacio de filas).

Establezca el parámetro de tipo booleano, más el valor del intervalo de filas, de hecho, ya ha especificado qué celda fusionar y cuántas filas fusionar. La siguiente es la implementación del código java.

AbstractGenericMergeStrategy es una estrategia de fusión general abstracta y GenericRowMergeStrategy es una implementación de fusión de filas.

public abstract class AbstractGenericMergeStrategy<T extends GenericMerge> extends AbstractMergeStrategy {
    //所有数据 目的就是从所有数据找到当前行数据row
    protected List<T> list;
    //表头行数
    protected int headRowNumber = 1;

    protected AbstractGenericMergeStrategy(List<T> list){
        this.list = list;
    }
    protected AbstractGenericMergeStrategy(List<T> list, int headRowNumber){
        this.list = list;
        this.headRowNumber = headRowNumber;
    }

    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, int relativeRowIndex) {
        int columnIndex = cell.getColumnIndex();
        int rowIndex = cell.getRowIndex();
        //找到cell对应的当前行数据row
        T t = list.get(rowIndex - headRowNumber);
        GenericMergeBO bo = t.merge(columnIndex);
        if (bo != null){
            merge(sheet,cell,bo);
        }
    }

    protected abstract void merge(Sheet sheet, Cell cell,GenericMergeBO bo);

    protected void executorMerge(CellPoint cellPoint, Sheet sheet){
            CellRangeAddress cellRangeAddress = new CellRangeAddress(
                    cellPoint.getStartY(),
                    cellPoint.getEndY(),
                    cellPoint.getStartX(),
                    cellPoint.getEndX());
            sheet.addMergedRegionUnsafe(cellRangeAddress);
    }

    String getCellText(Cell cell){
        String text = "";
        CellType cellType = cell.getCellTypeEnum();
        if(CellType.STRING.equals(cellType)){
            text = cell.getStringCellValue();
        }else if(CellType.NUMERIC.equals(cellType)){
            text = Double.toString(cell.getNumericCellValue());
        }else if(CellType.BOOLEAN.equals(cellType)){
            text = Boolean.toString(cell.getBooleanCellValue());
        }
        return text;
    }
}
public class GenericRowMergeStrategy<T extends GenericMerge> extends AbstractGenericMergeStrategy<T> {
    private Map<String, CellPoint> col = new HashMap<>();

    public GenericRowMergeStrategy(List<T> list) {
        super(list);
    }

    public GenericRowMergeStrategy(List<T> list, int headRowNumber) {
        super(list, headRowNumber);
    }

    @Override
    protected void merge(Sheet sheet, Cell cell, GenericMergeBO bo) {
        if (Boolean.TRUE.equals(bo.getStartMergeCell())) {
            CellPoint cellPoint = col.get(sheet.getSheetName() + "C" + cell.getColumnIndex());
            if (cellPoint == null) {
                cellPoint = new CellPoint();
                cellPoint.setStartX(cell.getColumnIndex());
                cellPoint.setStartY(cell.getRowIndex());
                cellPoint.setEndX(cell.getColumnIndex());
                cellPoint.setEndY(cell.getRowIndex() + bo.getRowspan() - 1);
                cellPoint.setText(getCellText(cell));
                col.put(sheet.getSheetName() + "C" + cell.getColumnIndex(), cellPoint);
            } else {
                if (cellPoint.getStartY() != cellPoint.getEndY()) {
                    executorMerge(cellPoint, sheet);
                }
                cellPoint.setStartX(cell.getColumnIndex());
                cellPoint.setStartY(cell.getRowIndex());
                cellPoint.setEndX(cell.getColumnIndex());
                cellPoint.setEndY(cell.getRowIndex() + bo.getRowspan() - 1);
            }
        }
    }
}
public interface GenericMerge {
    GenericMergeBO merge(int columnIndex);
}
public class CellPoint {
    /**
     * 开始单元格x坐标
     */
    private int startX;
    /**
     * 结束单元格x坐标
     */
    private int endX;
    /**
     * 开始单元格y坐标
     */
    private int startY;
    /**
     * 结束单元格y坐标
     */
    private int endY;
    /**
     * 单元格内容,文本
     */
    private String text;
}
@Data
public class GenericMergeBO {
    /**
     * 是否是开始合并的单元格
     */
    private Boolean startMergeCell;
    /**
     * 合并的行数
     */
    private Integer rowspan;
    /**
     * 合并的列数
     */
    private Integer colspan;
}

 

usar

Cuando se exporta easyexcel, pase la clase de estrategia GenericRowMergeStrategy. La clase de datos exportados implementa la interfaz GenericMerge. El cuerpo del método es traducir el método elementUI de combinar celdas en código java. El parámetro de retorno es una startMergeCell más si es la celda para comenzar a fusionarse, por el bien del juicio. No es necesario fusionarlo para devolver un valor nulo.

Desventaja

Cuando la estrategia de combinación de diferentes columnas es diferente, es más problemático construir los datos. Porque las diferentes estrategias deben corresponder a diferentes parámetros booleanos (ya sea que la celda startMergeCell comience a fusionarse) y el número de filas fusionadas (rowspan).

Análisis comparativo de métodos js / java

método

js: objectSpanMethod ({fila, columna, índice de fila, índice de columna}) {}

java: combinación GenericMergeBO (int columnIndex);

Comparado

js row-> java this (objeto actual)

js columnIndex-> ​​parámetro del método java columnIndex

Debido a que es solo una combinación de filas, no se utilizan column ni rowIndex. Si se requieren otras restricciones, los parámetros del método de interfaz GenericMerge se pueden enriquecer

principio

Para una columna, el primer verdadero es la celda inicial que debe fusionarse, los datos anteriores al segundo verdadero son los datos que se fusionarán, y así sucesivamente, para construir cómo fusionar los datos en esta columna.

Ejemplo

Como se muestra en la figura anterior, 0,1,2,8 es una estrategia de fusión 3,4 es otra estrategia de fusión 5,6,7 son columnas que no necesitan fusionarse

El código para construir los datos es el siguiente:

      List<User> list = new ArrayList<>();
        //根据用户姓名分组
        Map<String, List<User>> nameMap = list.stream().collect(Collectors.groupingBy(User::getName));
        nameMap.forEach((k,v)->{
            int index = v.size();
            for (User dto : v) {
                //给0,1,2,8列设置boolean参数和需要合并的行数
                dto.setIsRowSpan(index == v.size());
                dto.setRowIndexNumber(v.size());
                index--;
            }
            //每一个用户下又根据项目编号分组
            Map<String, List<User>> projectMap = v.stream().collect(Collectors.groupingBy(Project::getProjectNumber));
            projectMap.forEach((k1,v1)->{
                int j = v1.size();
                for (User dto : v1) {
                    //给3,4列设置boolean参数和需要合并的行数
                    dto.setIsProjectRowSpan(j == v1.size());
                    dto.setProjectRowIndexNumber(v1.size());
                    j--;
                }
            });
        });

La clase User implementa el código de la interfaz GenericMerge de la siguiente manera:

    @Override
    public GenericMergeBO merge(int columnIndex) {
        GenericMergeBO bo = null;
        if (columnIndex == 0 || columnIndex == 1 || columnIndex == 2 || columnIndex == 3 || columnIndex == 4 || columnIndex == 8) {
            if (columnIndex == 0 || columnIndex == 1 || columnIndex == 2 || columnIndex == 8) {
                bo = new GenericMergeBO();
                bo.setStartMergeCell(this.isRowSpan);
                bo.setRowspan(this.rowIndexNumber);
                bo.setColspan(1);
                return bo;
            } else if(columnIndex == 3 || columnIndex == 4){
                bo = new GenericMergeBO();
                bo.setStartMergeCell(this.isProjectRowSpan);
                bo.setRowspan(this.projectRowIndexNumber);
                bo.setColspan(1);
                return bo; 
            }
        }
        return bo;
    }

El código js es el siguiente:

    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 3 || columnIndex === 4 || columnIndex === 8) {
        if ((columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 8) && row.isRowSpan) {
          return {
            rowspan: row.rowIndexNumber,
            colspan: 1
          };
        } else if ((columnIndex === 3 || columnIndex === 4) && row.isProjectRowSpan) {
          return {
            rowspan: row.projectRowIndexNumber,
            colspan: 1
          };
        } else {
          return {
            rowspan: 0,
            colspan: 0
          };
        }
      }
    }

 

Nota: Parte del contenido usa el código en https://github.com/alibaba/easyexcel/pull/1091 para agregar una combinación horizontal y vertical de celdas de acuerdo con el mismo contenido de celda (uso de CellPoint, col map)

 

Supongo que te gusta

Origin blog.csdn.net/sinat_33472737/article/details/106339424
Recomendado
Clasificación