使用Apache POI 3.7读取分组行Excel生成WBS编码遇缩进检测问题
问题原因
你当前的代码错误地将Excel行分组(大纲级别)和单元格文本缩进混为一谈。截图中的Excel是用**行分组功能(大纲视图)**实现的层级折叠,而非设置单元格样式的文本缩进。CellStyle.getIndention()仅能获取单元格内文本的缩进量(比如在单元格格式中设置的缩进),完全无法读取行分组的层级信息,所以始终返回0。
解决方案
要获取行分组的层级,需使用Apache POI中Row对象的getOutlineLevel()方法,该方法直接返回当前行的大纲级别(行分组的层级,从0开始,0表示无分组)。
同时需要调整WBS编码的生成逻辑:用一个列表维护每个层级的当前序号,根据行的级别变化动态更新序号列表,最终拼接出1.1.1格式的编码。
修改后的完整代码
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ExcelReaderforHierarchy { public static boolean importExcel() throws Exception { boolean ret = false; try { String a_fileName = "E:\\groupedRow.xls"; FileInputStream w_In = new FileInputStream(a_fileName); HSSFWorkbook workbook = new HSSFWorkbook(w_In); Sheet sheet = workbook.getSheetAt(0); generateWBSCodes(sheet); ret = true; workbook.close(); w_In.close(); } catch (IOException e) { e.printStackTrace(); return false; } return ret; } private static void generateWBSCodes(Sheet sheet) { // 存储各级别当前的序号,索引对应级别-1(如index=0对应级别1的序号) List<Integer> levelCounters = new ArrayList<>(); int previousLevel = 0; for (Row row : sheet) { int currentLevel = row.getOutlineLevel(); // 根据当前级别与上一行级别的关系更新计数器列表 if (currentLevel > previousLevel) { // 进入更深层级,为新增的每个层级初始化序号为1 for (int i = previousLevel; i < currentLevel; i++) { levelCounters.add(1); } } else if (currentLevel < previousLevel) { // 返回上层级,移除不需要的层级计数器 for (int i = previousLevel; i > currentLevel; i--) { levelCounters.remove(levelCounters.size() - 1); } // 回到同级后,当前层级序号加1 if (currentLevel > 0) { int counterIndex = currentLevel - 1; levelCounters.set(counterIndex, levelCounters.get(counterIndex) + 1); } } else if (currentLevel == previousLevel && currentLevel > 0) { // 同层级的下一行,序号加1 int counterIndex = currentLevel - 1; levelCounters.set(counterIndex, levelCounters.get(counterIndex) + 1); } // 生成并打印WBS编码 StringBuilder wbsCode = new StringBuilder(); for (int i = 0; i < currentLevel; i++) { if (i > 0) { wbsCode.append("."); } wbsCode.append(levelCounters.get(i)); } String wbsOutput = currentLevel > 0 ? wbsCode.toString() : "(无层级)"; System.out.println("Row: " + row.getRowNum() + ", WBS Code: " + wbsOutput); previousLevel = currentLevel; } } public static void main(String[] args) throws Exception { importExcel(); } }
关键说明
row.getOutlineLevel():直接获取行的分组层级,0表示无分组,1表示一级分组,2表示二级分组,以此类推。- 层级计数器列表:动态维护每个层级的当前序号,解决嵌套分组的序号递增问题,比如从二级回到一级时,一级序号会自动加1。
- 资源关闭:补充了
workbook.close()和w_In.close(),避免资源泄漏。
内容的提问来源于stack exchange,提问作者ømi
相关产品推荐
相关产品推荐

