您的位置:首页 > 房产 > 建筑 > poi中导入excel时,获取下拉选项、解析从子表引用的下拉选项

poi中导入excel时,获取下拉选项、解析从子表引用的下拉选项

2025/2/26 2:22:37 来源:https://blog.csdn.net/weixin_43165220/article/details/141671863  浏览:    关键词:poi中导入excel时,获取下拉选项、解析从子表引用的下拉选项

我们导入excel表,解析数据时,有的时候需要把单元格是下拉框的所有下拉项拿到,有的下拉项是直接在单元格里面添加的下拉列表,还有的下拉项则是从其它表引用过来的,如下图:

在这里插入图片描述

在这里插入图片描述

那我们要怎么读取这两种不同方式添加的下拉列表数据呢?

如果是在当前表的单元格里添加的下拉列表,获取方式则比较简单,poi有专门的方法可以拿到指定sheet的所有下拉列表。

如果是从别的表引用过来的,则比较麻烦,poi那个方法拿到的被引用过来的下拉列表,拿到的并不是那些下拉项,而是范围区域字符串。例如:Sheet1!$A$1:$A$3Sheet1!$F$1:$F$4Sheet1!$B$1:$E$1 是这样的字符串,这个时候就需要我们自己解析这串字符,并根据范围去取数据。

实现

/*** 获取下拉项*/
public static Map<Integer,String> getSelectOption(Workbook workbook,Sheet sheet){Map<Integer,String> validations = new HashMap<>(); // 是下拉框的字段的列索引和下拉项(key为列索引,value为下拉项)// 通过正则表达式来解析引用的范围,获得被引用的sheet名和单元格范围// 这个正则表达式可以匹配包含中文、数字、字母、下划线的sheet名,但是不允许包含空格和其它特殊字符Pattern pattern = Pattern.compile("([^\\/:\\?\\*\\[\\]\\']+)!\\$(\\w+)\\$(\\d+)\\:\\$(\\w+)\\$(\\d+)");//DataValidationHelper validationHelper = sheet.getDataValidationHelper();// 获取下拉框数据for (DataValidation validation : sheet.getDataValidations()) {DataValidationConstraint constraint = validation.getValidationConstraint();CellRangeAddress cellRangeAddress = validation.getRegions().getCellRangeAddress(0);String selectOption = constraint.getFormula1().replaceAll("\"", "");Matcher matcher = pattern.matcher(selectOption);if (matcher.find()) {selectOption = selectOption(workbook,matcher,selectOption);}System.out.println("下拉数据:" + selectOption);validations.put(cellRangeAddress.getFirstColumn(),selectOption);}return headers;
}/*** 解析子表引用的下拉选项*/
public static String selectOption(Workbook workbook,Matcher matcher,String selectOption){String sheetName = matcher.group(1); // 被引用的sheet名称String startColumnName = matcher.group(2); // 开始的列名int startRowNum = Integer.parseInt(matcher.group(3)); // 开始的行号String endColumnName = matcher.group(4); // 结束的列名int endRowNum = Integer.parseInt(matcher.group(5)); // 结束的行号List<String> options = new ArrayList<>();Sheet child = workbook.getSheet(sheetName);if (startColumnName.equals(endColumnName)){ // 同一列不同行int colIndex = columnIndexFromName(startColumnName); // 获取列索引for (int rowNum = startRowNum - 1; rowNum < endRowNum; rowNum++) {Row row = child.getRow(rowNum);if (row != null) {Cell cell = row.getCell(colIndex);options.add(getCellValue(cell));}}}else if (!startColumnName.equals(endColumnName) && startRowNum == endRowNum){ // 同一行不同列Row row = child.getRow(startRowNum - 1); // 获取行索引int startColIndex = columnIndexFromName(startColumnName); // 获取开始的列索引int endColIndex = columnIndexFromName(endColumnName); // 获取结束的列索引for (int col = startColIndex; col <= endColIndex; col++) {Cell cell = row.getCell(col);options.add(getCellValue(cell));}}else {throw new ExceptionVo(-1,"下拉项的子表引用【 " + selectOption + " 】无法解析");}return StrUtil.join(",",options);
}/*** 根据列名获取列索引*/
public static int columnIndexFromName(String columnName) {int sum = 0;for (char ch : columnName.toCharArray()) {sum = sum * 26 + (ch - 'A' + 1);}return sum - 1; // 因为索引是从0开始的,而Excel的列名是从1开始的"感觉"
}/*** 获取单元格的值*/
public static String getCellValue(Cell cell){String cellValue = "";if (cell != null){switch (cell.getCellType()) {case STRING:cellValue = cell.getStringCellValue();break;case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {// 处理日期类型Date dateValue = cell.getDateCellValue();// 这里你可以根据需要将日期转换为字符串或其他格式SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");cellValue = dateFormat.format(dateValue);} else {cell.setCellType(CellType.STRING); // 将单元格内容以字符串形式获取// 处理数值类型//double numericValue = cell.getNumericCellValue();//cellValue = String.valueOf(numericValue);cellValue = cell.getStringCellValue();}break;// 其他类型的单元格可以根据需要进一步处理case BOOLEAN:cellValue = String.valueOf(cell.getBooleanCellValue());break;case BLANK:// 处理空单元格cellValue = "";break;default:// 处理其他类型的单元格throw new ExceptionVo(-1,"不支持的单元格类型");}}return cellValue;
}

获取结果

在这里插入图片描述

这样我们就可以完美获取这些下拉数据啦

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com