使用 Apache POI 生成 Excel 下拉列表时的限制

发布于 2024-12-23 07:01:59 字数 1942 浏览 1 评论 0原文

我正在尝试生成带有一些验证的 Excel 文件,我已阅读 poi开发指南来实现它。在实现过程中,我遇到了一个异常(公式中的字符串文字不能大于 255 个 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 不能支持?

I'm trying to generate an excel file with some validations, I've read the poi dev guides for implementing it. During implementation, I got an exception (String literals in formulas can't be bigger than 255 characters ASCII). POI concatenates all drop down options into '0' deliminated string and checking its length and giving me exception. :(
I'm using latest version of POI 3.8 beta 5.

And my code is:

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();
  }

After that I have tried with XSSFWorkBook with this code:

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");

Unfortunately, no success with such result which is comma delimenated long string in one cell:

enter image description here

But manually in excel, I can create dropdown cells with this long country list.
Is there any way generate dropdown with long strings, or API does not support?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奈何桥上唱咆哮 2024-12-30 07:01:59

据我了解,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();

I understood it, Excel itself does not allow entering validation range string more than 255 characters, this was not POI limitation. And now I'm using Named Ranges and Named Cells and it's working properly for me. So I had to put my validation range tokens in another sheet(made hidden) and I referenced desired cell ranges from my real sheet. Here is my working code:

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();
岁月流歌 2024-12-30 07:01:59

Õ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);
}

The formidable solution provided by Õzbek needs only slight modification to work flawlessly with NPOI (using C# on .NET).

Here's my code, provided as convenience for C# coders. It takes a sheet and positional elements as input and can also handle multiple dropdown, when they are arranged in columns.

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);
}
雨的味道风的声音 2024-12-30 07:01:59

上面的代码工作正常。但是,如果我使用 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 接口创建下拉列表

Above code works fine. But if I use XSSF classes instead of HSSF, it fails saying Exception in thread

"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)

To create dropdown list using XSSF interfaces I got the solution at

create dropdown list using apache poi XSSF interfaces

深居我梦 2024-12-30 07:01:59

这就是我使用 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);

}


          

This is how I used the FormulaListConstraint using the XSSF model

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
quot;);
        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);

}


          
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文