excel获取分级展示 折叠展开 父子级关系

excel获取分级展示 折叠展开 父子级关系

在这里插入图片描述

apache poi 4.1.2 通过方法Row.getOutlineLevel和Row.getZeroHeight来提供

我们可以遍历工作表中的所有行,并具有可以从一行中收集行组信息的方法来确定每一行的父子。在以下代码中,这是方法

// 行级别
int findStartOfRowOutlineGroup(Row row)
int findEndOfRowOutlineGroup(Row row)
boolean getIsWholeRowGroupHidden(Sheet sheet, int startOfRowOutlineGroup, int endOfRowOutlineGroup)
// 列级别
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();
 }
}

上面是参考 :
https://www.nuomiphp.com/eplan/173104.html

下面代码是构造图一的代码

  @ApiOperation(value = "excel自动分级")
    @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;

        // 这里跳过第一行。后面再补充顶级节点
        for (Row row : sheet) {
            MsgDto dto = getRowGroupInfos(row);
            if(dto == null || dto.getRow() == 1) {
                continue;
            }
            // 这里是关键一
            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));
            }
        }

        // 遍历二
        for (Row row : sheet) {
            MsgDto dto = getRowGroupInfos(row);
            if(dto == null || dto.getRow() == 1) {
                continue;
            }
            String parentNumberStr = StrUtil.join("",dto.getStartOfRowOutlineGroup(), dto.getEndOfRowOutlineGroup());

			// 这里是关键二
            list.add(new RowParentPo(dto.getRow().toString(), parentmap.get(parentNumberStr)));
        }

		// 补充顶级节点
        list.add(new RowParentPo("1","0"));

        // 这个地方可以用自己的根据父子级构造树结构方法,如果想用我的。请参照我另外一篇内容
        // https://blog.youkuaiyun.com/qq_37749537/article/details/128949451
        TreeUtils<RowParentPo, String> tree = new TreeUtils<>(
                list, RowParentPo::getRow,
                RowParentPo::getParent,
                RowParentPo::setChild);

        tree.build();

        // 这里已经完成excel层级的父子构建
        List<RowParentPo> jsonToList = list.stream().filter(f -> f.getRow().equals("1")).collect(Collectors.toList());

		// 生成
		//	   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();
        
        //扁平化
        recursionEq(jsonToList, excels);

		// 根据行号排序
        excels = excels.stream()
                .sorted(Comparator.comparing(RowParentPo::getSort))
                .collect(Collectors.toList());
        
        // 控制台输出的号码可以直接负责粘贴到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);
    }

}
### Axure中实现树形结构的方法 在Axure中创建树形结构可以通过多种方式完成,具体取决于需求的复杂程度以及期望的效果。以下是几种常见的方法及其特点: #### 方法一:使用中继器构建动态树结构 通过中继器可以灵活地实现动态树形结构,这种方法适用于复杂的交互场景,例如组织架构图或文件夹浏览功能。 - 中继器允许绑定数据集,并根据条件动态生成节点内容和层级关系[^1]。 - 可以设置交互事件来控制节点的展开折叠行为。 示例代码如下: ```javascript // 动态加载子节点的数据逻辑(伪代码) onNodeClick(event) { let currentNodeId = event.target.id; if (!isExpanded(currentNodeId)) { loadChildNodes(currentNodeId); // 加载子节点数据 toggleExpandState(currentNodeId, true); } else { toggleExpandState(currentNodeId, false); } } ``` #### 方法二:利用内置树形小部件 Axure提供了简单的树形小部件,默认支持基本的功能,如点击节点切换页面或显示隐藏区域。然而,这种原生组件存在一定的局限性,例如无法自定义样式或调整间距等问题[^2]。 尽管如此,对于简单的需求来说,它仍然是快速搭建原型的有效手段之一。 #### 方法三:借助图形工具手动绘制层次结构 当需要完全掌控视觉效果时,可以选择手工制作整个树状布局。这通常涉及以下几个步骤: 1. 插入矩形作为节点容器; 2. 添加连接线表示父子关系; 3. 设置必要的交互动作以便于操作者探索更多信息层。 一种推荐的做法是从“绘图”面板启动流程——即选取合适的模板类型并逐步完善细节直至满足目标规格为止[^3]。 另外值得注意的是,无论采用哪种技术路线,都应考虑用户体验因素,确保最终产品既美观又易于导航理解[^4]。 最后还有一种特别情况涉及到Excel表单内的分级视图处理技巧[^5],虽然这不是严格意义上的Axure专属解决方案,但对于某些特定场合下的应用可能会有所帮助。 ### 总结 综上所述,在Axure里建立树形结构主要有三种途径可供选择:一是运用高特性像中继器来自动生成;二是依赖预置好的简易版插件;三是纯手工地拼凑定制化版本。每种方案各有优劣之处,需依据实际项目背景做出明智抉择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值