Excel obtains hierarchical display, folding and expansion, parent-child relationship

Excel obtains hierarchical display, folding and expansion, parent-child relationship

apache poi 4.1.2 is provided through the methods Row.getOutlineLevel and Row.getZeroHeight

We can iterate through all the rows in the worksheet and have methods that can collect row group information from a row to determine the parent and child of each row. In the following code this is the method

//Row level
int findStartOfRowOutlineGroup(Row row)
int findEndOfRowOutlineGroup(Row row)
boolean getIsWholeRowGroupHidden(Sheet sheet, int startOfRowOutlineGroup, int endOfRowOutlineGroup)
//Column level
int findStartOfColOutlineGroup(Sheet sheet, int col)
int findEndOfColOutlineGroup(Sheet sheet, int col)
boolean getIsWholeColGroupHidden(Sheet sheet, int startOfColOutlineGroup, int endOfColOutlineGroup)
import java.io.FileInputStream;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

public class ExcelColumnGroupsRowGroups {<!-- -->

 static String getRowGroupInfos(Row row) {<!-- -->
  int outlineLevel = row.getOutlineLevel();
  String result = "Row " + (row.getRowNum() + 1) + " belongs to no group.";
  if (outlineLevel > 0) {<!-- -->
   int startOfRowOutlineGroup = findStartOfRowOutlineGroup(row); //0-based
   int endOfRowOutlineGroup = findEndOfRowOutlineGroup(row); //0-based
   boolean isRowHidden = row.getZeroHeight();
   boolean isWholeGroupHidden = getIsWholeRowGroupHidden(row.getSheet(), startOfRowOutlineGroup, endOfRowOutlineGroup);
   result = "Row " + (row.getRowNum() + 1) + " belongs to group having outline level:" + outlineLevel + ". "
             + "Group starts at row " + (startOfRowOutlineGroup + 1) + " and ends at row " + (endOfRowOutlineGroup + 1) + ". "
             + "Row " + (row.getRowNum() + 1) + " is " + ((isRowHidden)?"hidden":"not hidden") + ". "
             + "Whole group is " + ((isWholeGroupHidden)?"hidden":"not hidden") + ". ";
  }
  return result;
 }

 static int findStartOfRowOutlineGroup(Row row) {<!-- --> //0-based
  int outlineLevel = row.getOutlineLevel();
  int r = row.getRowNum();
  if (outlineLevel > 0) {<!-- -->
   while (r >= 0) {<!-- -->
    row = row.getSheet().getRow(r);
    if (row == null) break;
    int prevOutlineLevel = row.getOutlineLevel();
    if (prevOutlineLevel < outlineLevel) break;
    r--;
   }
  }
  return r + 1;
 }

 static int findEndOfRowOutlineGroup(Row row) {<!-- --> //0-based
  int outlineLevel = row.getOutlineLevel();
  int r = row.getRowNum();
  if (outlineLevel > 0) {<!-- -->
   while (r <= row.getSheet().getLastRowNum()) {<!-- -->
    row = row.getSheet().getRow(r);
    if (row == null) break;
    int prevOutlineLevel = row.getOutlineLevel();
    if (prevOutlineLevel < outlineLevel) break;
    r + + ;
   }
  }
  return r-1;
 }

 static boolean getIsWholeRowGroupHidden(Sheet sheet, int startOfRowOutlineGroup, int endOfRowOutlineGroup) {<!-- -->
  boolean result = true;
  Row row;
  for (int r = startOfRowOutlineGroup; r <= endOfRowOutlineGroup; r + + ) {<!-- -->
   row = sheet.getRow(r);
   if (row == null) {<!-- -->
    result = false;
    break;
   } else if (!row.getZeroHeight()) {<!-- -->
    result = false;
    break;
   }
  }
  return result;
 }

 static String getColGroupInfos(Sheet sheet, int c) {<!-- -->
  int outlineLevel = sheet.getColumnOutlineLevel(c);
  String result = "Col " + (c + 1) + " belongs to no group.";
  if (outlineLevel > 0) {<!-- -->
   int startOfColOutlineGroup = findStartOfColOutlineGroup(sheet, c); //0-based
   int endOfColOutlineGroup = findEndOfColOutlineGroup(sheet, c); //0-based
   boolean isColHidden = sheet.isColumnHidden(c);
   boolean isWholeGroupHidden = getIsWholeColGroupHidden(sheet, startOfColOutlineGroup, endOfColOutlineGroup);
   result = "Col " + (c + 1) + " belongs to group having outline level:" + outlineLevel + ". "
              + "Group starts at col " + (startOfColOutlineGroup + 1) + " and ends at col " + (endOfColOutlineGroup + 1) + ". "
              + "Col " + (c + 1) + " is " + ((isColHidden)?"hidden":"not hidden") + ". "
              + "Whole group is " + ((isWholeGroupHidden)?"hidden":"not hidden") + ". ";
  }
  return result;
 }

 static int findStartOfColOutlineGroup(Sheet sheet, int col) {<!-- --> //0-based
  int outlineLevel = sheet.getColumnOutlineLevel(col);
  int c = col;
  if (outlineLevel > 0) {<!-- -->
   while (c >= 0) {<!-- -->
    int prevOutlineLevel = sheet.getColumnOutlineLevel(c);
    if (prevOutlineLevel < outlineLevel) break;
    c--;
   }
  }
  return c + 1;
 }

 static int findEndOfColOutlineGroup(Sheet sheet, int col) {<!-- --> //0-based
  int outlineLevel = sheet.getColumnOutlineLevel(col);
  int c = col;
  if (outlineLevel > 0) {<!-- -->
   while (c <= sheet.getWorkbook().getSpreadsheetVersion().getLastColumnIndex()) {<!-- -->
    int prevOutlineLevel = sheet.getColumnOutlineLevel(c);
    if (prevOutlineLevel < outlineLevel) break;
    c++;
   }
  }
  return c-1;
 }

 static boolean getIsWholeColGroupHidden(Sheet sheet, int startOfColOutlineGroup, int endOfColOutlineGroup) {<!-- -->
  boolean result = true;
  for (int c = startOfColOutlineGroup; c <= endOfColOutlineGroup; c + + ) {<!-- -->
   if (!sheet.isColumnHidden(c)) {<!-- -->
    result = false;
    break;
   }
  }
  return result;
 }

 public static void main(String[] args) throws Exception {<!-- -->
  Workbook workbook = WorkbookFactory.create(new FileInputStream("./ExcelSheetGroupedColsAndRows.xlsx"));
  //Workbook workbook = WorkbookFactory.create(new FileInputStream("./ExcelSheetGroupedColsAndRows.xls"));
  Sheet sheet = workbook.getSheetAt(0);

  for (Row row : sheet) {<!-- -->
   String rowGroupInfos = getRowGroupInfos(row);
   System.out.println(rowGroupInfos);
  }

  for (int c = 0; c <= workbook.getSpreadsheetVersion().getLastColumnIndex(); c++ ) {<!-- -->
   if (sheet.getColumnOutlineLevel(c) > 0) {<!-- -->
    String colGroupInfos = getColGroupInfos(sheet, c);
    System.out.println(colGroupInfos);
   }
  }

  workbook.close();
 }
}

Above is the reference:
https://www.nuomiphp.com/eplan/173104.html

The following code is the code to construct Figure 1

 @ApiOperation(value = "excel automatic grading")
    @PostMapping(value = "/EquipmentFenJi")
    public List EquipmentFenJi(@RequestParam("file") MultipartFile multipartFile) throws Exception {<!-- -->
// Workbook workbook = WorkbookFactory.create(new FileInputStream("./ExcelSheetGroupedColsAndRows.xlsx"));
        Workbook workbook = WorkbookFactory.create(multipartFile.getInputStream());
        Sheet sheet = workbook.getSheetAt(1);

        Map<String, String> parentmap = new HashMap<String, String>();
        List<RowParentPo> list =new ArrayList();
        List<String> parentNumberlist = new ArrayList<>();
        int parentNumberInt = 0;

        // Skip the first line here. We will add top-level nodes later.
        for (Row row : sheet) {<!-- -->
            MsgDto dto = getRowGroupInfos(row);
            if(dto == null || dto.getRow() == 1) {<!-- -->
                continue;
            }
            //Here is the key
            String parentNumberStr = StrUtil.join("",dto.getStartOfRowOutlineGroup(), dto.getEndOfRowOutlineGroup());

            if (!CollUtil.contains(parentNumberlist, parentNumberStr)) {<!-- -->
                parentNumberlist.add(parentNumberStr);
                parentNumberInt = parentNumberInt + 1;
                parentmap.put(parentNumberStr, String.valueOf(dto.getRow()-1));
            }
        }

        // Traverse two
        for (Row row : sheet) {<!-- -->
            MsgDto dto = getRowGroupInfos(row);
            if(dto == null || dto.getRow() == 1) {<!-- -->
                continue;
            }
            String parentNumberStr = StrUtil.join("",dto.getStartOfRowOutlineGroup(), dto.getEndOfRowOutlineGroup());

//Here is key two
            list.add(new RowParentPo(dto.getRow().toString(), parentmap.get(parentNumberStr)));
        }

//Add top-level nodes
        list.add(new RowParentPo("1","0"));

        // This place can use your own method to construct a tree structure based on parent-child levels, if you want to use mine. Please refer to my other article
        // https://blog.csdn.net/qq_37749537/article/details/128949451
        TreeUtils<RowParentPo, String> tree = new TreeUtils<>(
                list, RowParentPo::getRow,
                RowParentPo::getParent,
                RowParentPo::setChild);

        tree.build();

        // The parent-child construction of excel level has been completed here.
        List<RowParentPo> jsonToList = list.stream().filter(f -> f.getRow().equals("1")).collect(Collectors.toList());

// generate
\t\t//\t   1,
// 1.1,
// 1.2,
// 1.3
// 1.3.1
// 1.3.2
        for (int i = 0; i < jsonToList.size(); i + + ) {<!-- -->
            RowParentPo treeVO = jsonToList.get(i);
            String levelPath = i + 1 + "";
            treeVO.setStr(levelPath);
            recursiveLoopCreateSeqNum(treeVO.getChild(), levelPath);
        }
        List<RowParentPo> excels = new ArrayList();
        
        //Flat
        recursionEq(jsonToList, excels);

// Sort by line number
        excels = excels.stream()
                .sorted(Comparator.comparing(RowParentPo::getSort))
                .collect(Collectors.toList());
        
        //The number output by the console can be directly pasted into excel
        for (RowParentPo excel : excels) {<!-- -->
            System.out.println(excel.getStr());
        }
        workbook.close();
        return new ArrayList();
    }
 void recursiveLoopCreateSeqNum(List<RowParentPo> treeList, String levelPath) {<!-- -->
        if (null == treeList || treeList.size() < 1) {<!-- -->
            return;
        }
        for (int i = 0; i < treeList.size(); i + + ) {<!-- -->
            RowParentPo treeVO = treeList.get(i);
            String childLevelPath = levelPath + "." + (i + 1);
            treeVO.setStr(childLevelPath);
            recursiveLoopCreateSeqNum(treeVO.getChild(), childLevelPath);
        }
    }
 public void recursionEq(List<RowParentPo> jsonToList, List<RowParentPo> excels) {<!-- -->
        for (RowParentPo vo: jsonToList) {<!-- -->
            excels.add(vo);
            if (CollUtil.isNotEmpty(vo.getChild())) {<!-- -->
                recursionEq(vo.getChild(), excels);
            }
        }
    }
@Data
public class RowParentPo {<!-- -->

    private String row;

    private String parent;

    private String str = "0";

    private List<RowParentPo> child;

    private Integer sort;

    public RowParentPo() {<!-- -->
    }

    public RowParentPo(String row, String parent) {<!-- -->
        this.row = row;
        this.parent = parent;
    }

    public Integer getSort() {<!-- -->
        return Integer.valueOf(row);
    }

}