poi excel 多级联动

本文介绍了一个使用 Java 实现的 Excel 文件生成器,能够创建包含下拉列表、级联选择等功能的复杂 Excel 表格。该程序通过读取模板文件,并利用 Apache POI 库动态设置工作表的数据验证规则来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddressList;
 
 
 


public class ExportExcel {
public static String outputFile = "d:\\shengcheng.xls "; // 生成的文件
public static String fileToBeRead = "d:\\aa.xls ";// 模板




private static String EXCEL_HIDE_SHEET_NAME = "paraSheet"; 
private static String fistName = ""; 



    //设置下拉列表的内容   
private static String[] provinceList = {"省份","浙江","山东","江西","江苏","四川"};     
private static String[] zjProvinceList = {"浙江","杭州","宁波","温州"};   
private static String[] sdProvinceList = {"山东","济南","青岛","烟台"};   
private static String[] jxProvinceList = {"江西","南昌","新余","鹰潭","抚州"};   
private static String[] jsProvinceList = {"江苏","南京","苏州","无锡"};  
private static String[] scProvinceList = {"四川","成都","绵阳","自贡"}; 
private static String[] jsCityList = {"无锡","西湖","杭州","断桥"}; 

private static String[] scCityList = {"成都","北川","青川","汶川"}; 
static ArrayList ztList;
static ArrayList kmList;
static ArrayList zkmList;

public static void main(String[] args) {
ztList=new ArrayList();
ztList.add(provinceList);

zkmList=new ArrayList();
zkmList.add(scCityList);
zkmList.add(jsCityList);
kmList=new ArrayList(); 
kmList.add(zjProvinceList);
kmList.add(sdProvinceList);
kmList.add(jxProvinceList);
kmList.add(jsProvinceList);
kmList.add(scProvinceList);

List  lst=new ArrayList();
lst.add(ztList);
lst.add(kmList);
lst.add(zkmList);
HSSFWorkbook wb=null;
 try {
wb = new HSSFWorkbook(new FileInputStream(
fileToBeRead));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
creatExcelHidePage(wb,false,lst);   //创建隐藏sheet
setDataValidation(wb,3,new int[]{1,2,3});  //设置校验
FileOutputStream fOut;//输出
try {
fOut = new FileOutputStream(outputFile);
wb.write(fOut);
fOut.flush();
fOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}

}
/**
* 
* @param workbook
* @param flag 创建的参数sheet是否隐藏
*/
    public static void creatExcelHidePage(Workbook workbook,boolean flag,List lst){   
        Sheet hideInfoSheet = workbook.createSheet(EXCEL_HIDE_SHEET_NAME);//隐藏一些信息   
        //创建参数sheet 里面内容 
        int row=0;
for(int i=0;i<lst.size();i++){
List m=(List) lst.get(i);
for(int j=0;j<m.size();j++){
if(i==0){
String[] t=(String[])m.get(j);
fistName=t[0];
}
Row r=hideInfoSheet.createRow(row++);
        creatRow(r, (String[])m.get(j));   
}
}        
        row=1;
for(int i=0;i<lst.size();i++){
List m=(List) lst.get(i);
for(int j=0;j<m.size();j++){
String[] temp=(String[]) m.get(j);
creatExcelName(workbook, temp[0], row++,2,temp.length);
}
}
        workbook.setSheetHidden(workbook.getSheetIndex(EXCEL_HIDE_SHEET_NAME), flag);   
    }  
    
    /**  
     * 创建excel名称
     * @param workbook  
     */  
    private static void creatExcelName(Workbook workbook,String cellName,int row,int start,int end){   
    Name name;   
    name = workbook.createName();   
    name.setNameName(cellName);   
    name.setRefersToFormula(getNamestr(cellName,row,start,end));   
    }   
    private static String getNamestr(String sheetName,int row,int start,int end){
    return EXCEL_HIDE_SHEET_NAME+"!"+"$"+CellReference.convertNumToColString(start-1) +"$"+row+":"+"$"+CellReference.convertNumToColString(end-1)+"$"+row;
    }
    
    
    /**  
     * 创建一行数据
     * @param currentRow  
     * @param textList  
     */  
    private static void creatRow(Row currentRow,String[] textList){   
        if(textList!=null&&textList.length>0){   
            int i = 0;   
            for(int j=0;j<textList.length;j++){   
                Cell userNameLableCell = currentRow.createCell(i++);   
                userNameLableCell.setCellValue(textList[j]);   
            }   
        }   
    }
   /**
    * 
    * @param wb
    * @param startRow  超始行
    * @param cols     级联的列号数组
    */
    public static void setDataValidation(Workbook wb,int startRow,int[] cols){   
        int sheetIndex = wb.getNumberOfSheets();  
        String[] colNames=getColName(cols);
        if(sheetIndex>0){   
                Sheet sheet = wb.getSheetAt(0);  
                DataValidation data_validation = null;
                for(int row=startRow;row<3002;row++){
                   data_validation = getDataValidationByFormula(fistName,row,cols[0]);   
                   sheet.addValidationData(data_validation);  
                     for(int i=0;i<colNames.length-1;i++){
                     data_validation = getDataValidationByFormula("INDIRECT("+colNames[i]+row+")",row,cols[i]+1);   
                     sheet.addValidationData(data_validation);  
                     
                     }
                }
//                }   
        }   
    }  
    static String[] getColName(int[] colIndex){
    String[] colName=new String[colIndex.length];
    for(int i=0;i<colIndex.length;i++){
    colName[i]=CellReference.convertNumToColString(colIndex[i]-1) ;
    }
    return colName;
    
    }
/**
 * 
 * @param formulaString  公式
 * @param naturalRowIndex 验证的行
 * @param naturalColumnIndex 验证的列
 * @return
 */
    private static DataValidation getDataValidationByFormula(String formulaString,int naturalRowIndex,int naturalColumnIndex){   
        //加载下拉列表内容     
        DVConstraint constraint = DVConstraint.createFormulaListConstraint(formulaString);    
        //设置数据有效性加载在哪个单元格上。     
        //四个参数分别是:起始行、终止行、起始列、终止列     
        int firstRow = naturalRowIndex-1;   
        int lastRow = naturalRowIndex-1;   
        int firstCol = naturalColumnIndex-1;   
        int lastCol = naturalColumnIndex-1;   
        CellRangeAddressList regions=new CellRangeAddressList(firstRow,lastRow,firstCol,lastCol);     
        //数据有效性对象    
        DataValidation data_validation = new HSSFDataValidation(regions,constraint);   
        //设置输入信息提示信息   
        data_validation.createPromptBox("提示","请使用下拉方式选择合适的值!");   
        //设置输入错误提示信息   
        data_validation.createErrorBox("提示","你输入的值不合法,请下拉选择合适的值!");   
        return data_validation;   
    }   
    
    
}

### 如何使用 Apache POI 实现 Excel 文件中的多级联动效果 为了实现在 Java 中利用 Apache POI 库创建具有多级联动功能的 Excel 表格,可以按照如下方法编写代码: #### 创建带有下拉列表的数据验证规则 首先定义好父级和子级选项所在的单元格区域,并设置相应的数据有效性约束。 ```java // 建立工作簿对象 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("MultiLevelDropdown"); // 准备一些测试数据作为父级菜单项 Row row0 = sheet.createRow(0); row0.createCell(0).setCellValue("Fruits"); row0.createCell(1).setCellValue("Vegetables"); // 将上述类别名称写入隐藏的工作表中供后续引用 HelperSheet helperSheet = (HelperSheet)wb.createSheet("HiddenList"); helperSheet.createRow(0).createCell(0).setCellValue("Apple"); helperSheet.createRow(1).createCell(0).setCellValue("Banana"); helperSheet.createRow(2).createCell(0).setCellValue("Carrot"); helperSheet.createRow(3).createCell(0).setCellValue("Broccoli"); // 定义父级选择范围 Name namedCell = wb.createName(); namedCell.setNameName("Category"); String reference = "HiddenList!$A$1:$B$2"; namedCell.setRefersToFormula(reference); // 设置第一个单元格为父级分类的选择框 DataValidationConstraint constraintCatgory = dvHelper.createExplicitListConstraint(new String[]{"Fruits", "Vegetables"}); CellRangeAddressList addressListParent = new CellRangeAddressList(1, 65530, 0, 0); // A2:A65531 dvHelper.createValidation(constraintCatgory, addressListParent); ``` #### 动态更新子级下拉列表依据所选父级项目调整其内容 当用户选择了不同的父级条目时,对应的子级应该展示与之匹配的具体选项。这一步骤可以通过监听事件并修改数据验证条件来完成;然而,在静态生成文件的情况下,则需预先设定所有可能组合。 ```java // 预设两个不同类型的食品清单用于演示目的 Map<String, List<String>> subItemsMapping = Map.of( "Fruits", Arrays.asList("Apple", "Banana"), "Vegetables", Arrays.asList("Carrot", "Broccoli") ); for (Entry<String, List<String>> entry : subItemsMapping.entrySet()) { DataValidationConstraint constraintSubItem = dvHelper.createFormulaListConstraint(entry.getKey()); int rowIndexStart = 1; for(String item : entry.getValue()){ Row tempRow = helperSheet.getRow(rowIndexStart++); if(tempRow == null){ tempRow = helperSheet.createRow(rowIndexStart-1); } tempRow.createCell(0).setCellValue(item); } CellRangeAddressList addrLstChild = new CellRangeAddressList(1, 65530, 1, 1); // B2:B65531 dvHelper.createValidation(constraintSubItem, addrLstChild); } ``` 以上代码片段展示了如何基于选定的不同父级类别动态改变子级可选项的内容[^2]。需要注意的是实际应用环境中通常会从数据库或其他持久化存储获取这些关联关系而非硬编码于程序内部。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值