首页 > 解决方案 > 有没有办法过滤掉 XSSFWorkbook.allNames 中的隐藏名称?

问题描述

我有兴趣使用 Apache POI 获取用户定义的命名范围列表(如 Excel 应用程序 UI 中所示)。

我可以使用XSSFName的静态属性过滤掉内置插件,但可能还有其他插件由插件等设置。下面是一个带有隐藏名称的(缩短的)真实示例:

<definedName name="user_named_range">...</definedName>
<definedName name="_xlnm._FilterDatabase" hidden="1">...</definedName>
<definedName name="CIQWBGuid" hidden="1">...</definedName>
<definedName name="ExactAddinConnection" hidden="1">...</definedName>

workbook.allNames返回所有这些。如何识别user_named_range为用户定义并跳过所有其他?

标签: apache-poi

解决方案


直到现在还XSSFName无法访问hidden底层的属性CTDefinedName。因此,如果需要,需要获得该底层CTDefinedName. 不幸的是,该方法getCTName仅具有受保护的访问权限。不过幸好有java.lang.reflect

例子:

import java.io.FileInputStream;

import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;

import java.lang.reflect.Method;

class ReadExcelXSSFNameDetails {

 public static void main(String[] args) throws Exception {

  XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("./inputFile.xlsm"));

  for (XSSFName name : workbook.getAllNames()) {
   String nameName = name.getNameName();

   Method getCTName = XSSFName.class.getDeclaredMethod("getCTName");
   getCTName.setAccessible(true);
   CTDefinedName ctName = (CTDefinedName)getCTName.invoke(name);
   //System.out.println(ctName);

   boolean isHidden = ctName.getHidden();
   System.out.println("Found name " + nameName + ". Is this name hidden? " + isHidden);

  }

  workbook.close();

 }

}

现在您可以检测存储的名称是否具有隐藏属性集。


推荐阅读