15

我正在尝试生成一个带有一些验证的 excel 文件,我已经阅读了poi 开发指南来实现它。在执行过程中,我遇到了一个异常 ( String literals in formulas can't be bigger than 255 characters ASCII)。POI 将所有下拉选项连接到以“0”分隔的字符串中并检查其长度并给我例外。:(
我正在使用最新版本的 POI 3.8 beta 5。
我的代码是:

try {
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("new sheet");
    HSSFRow row = sheet.createRow((short) 0);
    //CellRangeAddressList from org.apache.poi.ss.util package
    CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
    DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint(getCountries());
    DataValidation dataValidation = new HSSFDataValidation(addressList, dvConstraint);
    dataValidation.setSuppressDropDownArrow(false);
    sheet.addValidationData(dataValidation);
    FileOutputStream fileOut = new FileOutputStream("c:\\test.xls");
    wb.write(fileOut);
    fileOut.close();
    } catch (IOException e) {
       e.printStackTrace();
  }

之后,我尝试使用 XSSFWorkBook 使用以下代码:

XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("new sheet");
DataValidationHelper validationHelper = new XSSFDataValidationHelper(sheet);
DataValidationConstraint constraint = validationHelper.createExplicitListConstraint(getCountries());
CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
DataValidation dataValidation = validationHelper.createValidation(constraint, addressList);
dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
dataValidation.setSuppressDropDownArrow(true);
sheet.addValidationData(dataValidation);
FileOutputStream fileOut = new FileOutputStream("c:\\test.xlsx");

不幸的是,这种结果在一个单元格中以逗号分隔的长字符串没有成功:

在此处输入图像描述

但是在 excel 中手动,我可以用这个长长的国家列表创建下拉单元格。
有没有办法用长字符串生成下拉菜单,或者 API 不支持?

4

4 回答 4

33

我明白了,Excel 本身不允许输入超过 255 个字符的验证范围字符串,这不是 POI 限制。现在我正在使用命名范围和命名单元格,它对我来说工作正常。所以我不得不把我的验证范围标记放在另一张表中(隐藏),我从我的真实表中引用了所需的单元格范围。这是我的工作代码:

HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet realSheet = workbook.createSheet("Sheet xls");
HSSFSheet hidden = workbook.createSheet("hidden");
for (int i = 0, length= countryName.length; i < length; i++) {
   String name = countryName[i];
   HSSFRow row = hidden.createRow(i);
   HSSFCell cell = row.createCell(0);
   cell.setCellValue(name);
 }
 Name namedCell = workbook.createName();
 namedCell.setNameName("hidden");
 namedCell.setRefersToFormula("hidden!$A$1:$A$" + countryName.length);
 DVConstraint constraint = DVConstraint.createFormulaListConstraint("hidden");
 CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
 HSSFDataValidation validation = new HSSFDataValidation(addressList, constraint);
 workbook.setSheetHidden(1, true);
 realSheet.addValidationData(validation);
 FileOutputStream stream = new FileOutputStream("c:\\range.xls");
 workbook.write(stream);
 stream.close();
于 2012-01-18T17:15:01.323 回答
3

Õzbek 提供的强大解决方案只需稍作修改即可与 NPOI 完美配合(在 .NET 上使用 C#)。

这是我的代码,为 C# 编码人员提供方便。它以工作表和位置元素作为输入,当它们按列排列时,还可以处理多个下拉列表。

public static void CreateDropDownListForExcel(this ISheet sheet, IList<string> dropDownValues, int startRow, int lastRow, int column) {
    if (sheet == null) {
        return;
    }

    //Create a hidden sheet on the workbook (using the column as an id) with the dropdown values
    IWorkbook workbook = sheet.Workbook;
    string dropDownName = sheet.SheetName + "DropDownValuesForColumn" + column;
    ISheet hiddenSheet = workbook.CreateSheet(dropDownName);
    for (int i = 0, length = dropDownValues.Count; i < length; i++) {
        string name = dropDownValues[i];
        IRow row = hiddenSheet.CreateRow(i);
        ICell cell = row.CreateCell(0);
        cell.SetCellValue(name);
    }

    //Create the dropdown using the fields of the hidden sheet
    IName namedCell = workbook.CreateName();
    namedCell.NameName = dropDownName;
    namedCell.RefersToFormula = (dropDownName + "!$A$1:$A$" + dropDownValues.Count);
    DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(dropDownName);
    CellRangeAddressList addressList = new CellRangeAddressList(startRow, lastRow, column, column);
    HSSFDataValidation validation = new HSSFDataValidation(addressList, constraint);
    int hiddenSheetIndex = workbook.GetSheetIndex(hiddenSheet);
    workbook.SetSheetHidden(hiddenSheetIndex, SheetState.HIDDEN);

    //Add the Dropdown to the presenting sheet.
    sheet.AddValidationData(validation);
}
于 2018-05-01T12:54:36.537 回答
2

上面的代码工作正常。但是如果我使用 XSSF 类而不是 HSSF,它会在线程中说异常失败

"main" java.lang.NoSuchMethodError: org.apache.poi.ss.formula.FormulaParser.parse(Ljava/lang/String;Lorg/apache/poi/‌​ss/formula/FormulaParsingWorkbook;II)[Lorg/apache/poi/ss/formula/ptg/Ptg; at org.apache.poi.xssf.usermodel.XSSFName.setRefersToFormula(XSSFName.java:195) at XLDropdown.main(XLDropdown.java:35)

要使用 XSSF 接口创建下拉列表,我得到了解决方案

使用 apache poi XSSF 接口创建下拉列表

于 2014-05-21T05:34:42.850 回答
0

这就是我使用 XSSF 模型使用 FormulaListConstraint 的方式

byte[] addConstraint() throws IOException {
    ByteArrayOutputStream byteArrayOutputStream = null;
    byte[] output = null;
    XSSFWorkbook workbook = null;

    try {
        Resource resource = new ClassPathResource("Test.xlsx");
        InputStream input = resource.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        org.apache.commons.io.IOUtils.copy(input, baos);
        byte[] uploadedFile = baos.toByteArray();
        ByteArrayInputStream bais = new ByteArrayInputStream(uploadedFile);
        workbook = new XSSFWorkbook(bais);
        XSSFSheet sheet = workbook.getSheetAt(0);
        String originalSheet = "myhiddenSheet";
        String[] roles = new String[] { "val1", "val2"/* ...... */, "valn" };
        addHiddenSheet(workbook, roles, originalSheet);
        String formulae = originalSheet.concat("!$A$1:$A$");
        Name namedCell = workbook.createName();
        namedCell.setNameName(originalSheet);
        namedCell.setRefersToFormula(formulae + roles.length);
        XSSFDataValidationHelper userRoleDataValidationHelper = new XSSFDataValidationHelper(sheet);
        XSSFDataValidationConstraint userRoleConstraint = (XSSFDataValidationConstraint) userRoleDataValidationHelper
                .createFormulaListConstraint(originalSheet);
        CellRangeAddressList addressList = new CellRangeAddressList(0, 0, 0, 0);
        XSSFDataValidation userStatusValidation = (XSSFDataValidation) userRoleDataValidationHelper
                .createValidation(userRoleConstraint, addressList);
        sheet.addValidationData(userStatusValidation);

        byteArrayOutputStream = new ByteArrayOutputStream();
        workbook.write(byteArrayOutputStream);
        output = byteArrayOutputStream.toByteArray();
    } finally {
        workbook.close();
        byteArrayOutputStream.close();
    }
    return output;
}
private void addHiddenSheet(Workbook workbook, String[] values, String hiddenSheetName) {
    Sheet hiddenSheet = workbook.createSheet(hiddenSheetName);
    for (int i = 0, length = values.length; i < length; i++) {
        String name = values[i];
        Row row = hiddenSheet.createRow(i);
        Cell cell = row.createCell(0);
        cell.setCellValue(name);
    }
    workbook.setSheetHidden(1, true);

}


          
于 2021-12-12T21:36:16.160 回答