使用Java写入Excel下拉选择框选项过多不显示问题

1.问题描述

工作中遇到需要使用Java poi读写Excel文件的问题,因为需求中有要求在写文件时创建下拉选择框。按照传统的直接使用List集合保存下拉选择框的选项,再通过poi本身的方法将选择框的选项添加到下拉框中。

一开始编写demo测试时只有几个选项,可以正确的添加下拉框。后来把方法搬到项目中,发现创建的文件中的下拉框的选项数据不能正确的显示。通过对比两个文件,发现唯一的不同点就是下拉框选项的数量存在差异。通过一番查询,发现poi添加下拉框选项的数量被控制在20个以内(官方说法好像是256个字节?记不太清楚了,如果说错了,请大佬批评指正orz)

2.选项数量(<=20)较少的方法

  • 向Excel中写数据,简单样例

    /**
         * 将lines的内容写入excel中
         *
         * @param outputPath excel存放路径
         * @param lines      需要写入execl的文件
         * @throws IOException
         */
        public synchronized void writeInExcel(String outputPath, Collection<String[]> lines) throws IOException {
         
    
            @SuppressWarnings("resource")
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet();
            // 写入Excel表格开头
            Row firstRow = sheet.createRow(0);
            ArrayList<String> arrayList = new ArrayList<String>();
            String[] excelHeadList = {
         "a","b","c","d","e"};
            for (int i = 0; i < excelHeadList.length; i++) {
         
                arrayList.add(excelHeadList[i]);
            }
            String[] arr = new String[arrayList.size()];
            for (int i = 0; i < arrayList.size(); i++) {
         
                arr[i] = arrayList.get(i);
            }
            writeInRow(firstRow, arr);
    
            if (lines != null && lines.size() > 0) {
         
                // 写入Excel表格内容
                AtomicInteger i = new AtomicInteger(1);
                lines.forEach(line -> {
         
                    Row row = sheet.createRow(i.get());
                    writeInRow(row, line);
                    i.set(i.incrementAndGet());
                });
                DataValidationHelper helper = sheet.getDataValidationHelper();
                // 创建审核结果下拉框
                createDropDownBox(sheet, helper, checkResultList, 1, i.get() - 1, arr.length - 6, arr.length - 6);
            }
     
### 使用 EasyExcel 实现 Java 中导出带二级下拉列表Excel 表格 在实际开发过程中,使用 EasyExcel 可以简化复杂的数据处理逻辑并快速完成 Excel 文件的生成工作。以下是基于 EasyExcel 的具体实现方式。 #### 1. 明确需求背景 为了满足业务场景中对数据输入规范性的要求,通常会在 Excel 文件中设置下拉菜单来限定可选值范围。对于二级下拉列表的需求,则需要进一步定义父子关系,并通过特定配置使子选项依赖于父选项的选择结果[^2]。 --- #### 2. 技术准备 - **引入依赖** 确保项目中已添加 EasyExcel 和其他必要的 Maven 或 Gradle 依赖项。 ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> ``` - **核心概念** EasyExcel 提供了灵活的方式来操作单元格样式、验证规则以及自定义内容填充功能。其中 `WriteHandler` 接口允许开发者介入写入过程,从而支持复杂的交互行为如动态加载关联数据源等。 --- #### 3. 数据结构设计 假设存在两个维度的信息:“省份”作为一级分类,“城市”对应其下的次级单位。这些信息可以从数据库读取或者硬编码存储以便测试用途。 ```java // 示例实体类 - 省份及其下属的城市集合 public class ProvinceCity { private String provinceName; // 省名 private List<String> cityNames; // 所属城市的名称列表 public ProvinceCity(String provinceName, List<String> cityNames){ this.provinceName = provinceName; this.cityNames = cityNames; } // Getter & Setter 方法省略... } ``` 初始化模拟数据: ```java List<ProvinceCity> data = new ArrayList<>(); data.add(new ProvinceCity("广东", Arrays.asList("广州","深圳"))); data.add(new ProvinceCity("江苏", Arrays.asList("南京","苏州"))); ``` --- #### 4. 编码实现细节 下面给出完整的代码片段用于演示如何利用 EasyExcel 创建含两级联接式选择框的工作表: ```java import com.alibaba.excel.EasyExcel; import org.apache.poi.ss.usermodel.*; import java.io.FileOutputStream; import java.util.*; public class ExportWithDropdown { public static void main(String[] args) throws Exception{ String fileName = "output_with_dropdown.xlsx"; Workbook workbook = null; try(FileOutputStream fos=new FileOutputStream(fileName)){ workbook=WorkbookFactory.create(true); Sheet sheet =workbook.createSheet(); Row headerRow=sheet.createRow(0); CellStyle style=workbook.createCellStyle(); DataValidationConstraint dvConstraintProvinces=createDataValidationForProvinces(workbook,sheet,data.stream().map(pc->pc.getProvinceName()).toList()); addDataValidation(sheet,dvConstraintProvinces,"A2:A10"); Map<String,List<String>> citiesByProvince=getCitiesGroupedByProvince(data); Set<Map.Entry<String,List<String>>> entries=citiesByProvince.entrySet(); int indexOffset=entries.size()+1; for(Map.Entry<String,List<String>> entry : entries ){ String key=entry.getKey(); List<String> values=entry.getValue(); NamedRange namedRange=new NamedRange(key,null,indexOffset++,values.toArray(new Object[0])); workbook.setNamedRange(namedRange.getName(),namedRange.getRefersToFormula()); DataValidationConstraint dvConstraintCities=createIndirectDataValidation(workbook,key); addDataValidation(sheet,dvConstraintCities,"B2:B10"); } workbook.write(fos); }finally{ if (workbook !=null ) {workbook.close();} } } private static DataValidationConstraint createDataValidationForProvinces(Workbook wbk ,Sheet sh,List<String> provinces){ Helper helper=(Helper)(wbk instanceof XSSFWorkbook ?new XSSFHelper():new HSSFHelper()); Name name=helper.createDefinedName(wbk,"provinces",'=',"'"+sh.getSheetName()+"'!$C$1:$C$" +provinces.size() ); return helper.createExplicitListConstraint(name); } private static DataValidationConstraint createIndirectDataValidation(Workbook wbk,String referrerKey){ Helper helper=(Helper)(wbk instanceof XSSFWorkbook?new XSSFHelper():new HSSFHelper()); return helper.createFormulaListConstraint(referrerKey); } private static void addDataValidation(Sheet sheet,DataValidationConstraint constraint,String cellRegion){ DataValidation validation=new HSSFSheet.DataValidationImpl(CellRangeAddress.valueOf(cellRegion),constraint); validation.setSuppressDropDownArrow(false); ((org.apache.poi.xssf.usermodel.XSSFSheet)sheet).addValidationData(validation); } private static Map<String,List<String>> getCitiesGroupedByProvince(List<ProvinceCity> dataList){ HashMap<String,List<String>> result=new HashMap<>(); for(var item:dataList){ result.put(item.getProvinceName(),item.getCityNames()); } return result; } } abstract class Helper{ abstract Name createDefinedName(Workbook book,String definedNameStr,char operatorChar,Object...valueArray); abstract DataValidationConstraint createExplicitListConstraint(Name explicitList); abstract DataValidationConstraint createFormulaListConstraint(String formulaText); } class XSSFHelper extends Helper{ @Override Name createDefinedName(Workbook book, String definedNameStr, char operatorChar, Object... valueArray) { var xssfBook=(XSSFWorkbook)book; var name=xssfBook.createName(); StringBuilder sb=new StringBuilder("'").append(((XSSFWorkbook)xssfBook).getSheetAt(0).getSheetName()) .append("'!") .append("$D$") .append(xssfBook.getNumberOfSheets()+1); name.setNameName(definedNameStr); name.setRefersToFormula(sb.toString()); return name; } @Override DataValidationConstraint createExplicitListConstraint(Name explicitList) { return new XSSFDataValidationConstraint(explicitList); } @Override DataValidationConstraint createFormulaListConstraint(String formulaText) { return new XSSFDataValidationConstraint(formulaText); } } class HSSFHelper extends Helper{ @Override Name createDefinedName(Workbook book, String definedNameStr, char operatorChar, Object... valueArray) { throw new UnsupportedOperationException("Not supported yet."); } @Override DataValidationConstraint createExplicitListConstraint(Name explicitList) { throw new UnsupportedOperationException("Not supported yet."); } @Override DataValidationConstraint createFormulaListConstraint(String formulaText) { throw new UnsupportedOperationException("Not supported yet."); } } ``` 上述程序实现了以下目标: - 定义了一个名为“provinces”的全局命名区域,包含了所有可用的一级类别; - 对应每一级别的条目创建独立的名字空间(即每个省份都有专属标识符),并通过间接引用机制绑定到第二栏位上形成条件约束效果; --- ### 注意事项 当采用此方案时需要注意几点潜在问题: - 如果涉及大量候选词条可能会显著增加文件体积影响性能表现; - 用户端打开此类特殊格式化电子表格可能遇到兼容性障碍需提前告知对方安装最新版本Office软件或LibreOffice套件替代品解决冲突情况发生可能性较大一些情况下甚至无法正常显示预期界面布局等问题均有可能出现因此建议充分考虑实际情况后再决定是否采纳该种做法。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值