记一次Java Poi使用事故

2019-08-22  本文已影响0人  学废君

由于业务需求,我需要处理一个excel表,读取数据库中的信息并作为下拉列表(即数据验证,旧版的叫数据有效性)添加到excel表中。由于是新版的excel, 这里就不考虑HSSF而是直接使用XSSF。
首先,由于我对poi,xssf这个东西不熟,所以直接采用createExplicitListConstraint实现,但是一开始就报错了。打开生成的excel表提示:
"无法读取表中的某些数据,如果对其信任,是否对数据源进行修复?"
选择“是”,就会发现弹出这样一个提示:
"已删除的功能:../../xx.xml,的数据验证"
然后数据验证功能被完全删除!
这是为什么呢?一开始,我以为是编码问题,后来发现不是,又以为是中文问题,手动测试后发现也不是。难道是因为出现了空格和特殊字符?都不是!我小心翼翼地测试,发现有时候报错有时候不报错,但总体规律就是:数据验证的条数越多、每条的字数越多,报错的几率越大。
后面,我终于知道了,这个它这个功能固有的缺陷,那怎么办?方法就是改用createFormulaListConstraint,创建一个隐藏的sheet,并往里放入枚举项,然后在真正的sheet内增加关联关系!
具体的实现步骤如下:

public static Workbook XSSFSetDropDownAndHidden(String[] formulaString) {
        Workbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("mysheet");
        // 创建隐藏sheet,写入枚举项
        Sheet hideSheet = workbook.createSheet("hiddenSheet");
        for (int i = 0; i < formulaString.length; i++) {
            hideSheet.createRow(i).createCell(0).setCellValue(formulaString[i]);
        }
        // 创建名称,作用是被其他单元格引用
        Name categoryName = workbook.createName();
        categoryName.setNameName("hidden");
        // 设置名称引用的公式
        categoryName.setRefersToFormula("hiddenSheet!" + "$A$1:$A$" + formulaString.length);
        //由于在hiddensheet中的每一行的第一个格子我们放入了等同于length的数据,所以这里用绝对引用第一列的1到length的数据
        // 设置下拉单位格范围,第5列的1到1024
        CellRangeAddressList regions = new CellRangeAddressList(0,1024,4,4);
        //获取数据
        XSSFDataValidationHelper dvHelper = (XSSFDataValidationHelper) sheet.getDataValidationHelper();
        XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint)dvHelper.createFormulaListConstraint("hidden");
        //将数据关联
        XSSFDataValidation dataValidation = (XSSFDataValidation)dvHelper.createValidation(dvConstraint,regions);
        //其他设置
        dataValidation.setSuppressDropDownArrow(true);
        dataValidation.setShowErrorBox(true);
        //添加到sheet中
        sheet.addValidationData(dataValidation);
        //设置隐藏
        workBook.setSheetHidden(1,true);
        return workbook;
    }

最后感谢博客园的"(00)"的博文。

上一篇 下一篇

猜你喜欢

热点阅读