使用Apache POI生成具有三级联动下拉列表的Excel文档;

具体效果图与代码如下文。

先上效果图:


开始贴代码,代码中部分测试数据不影响功能。

第一部分(核心业务处理):

此部分包含几个方面:

  1. 获取三级下拉框各列的数据;
  2. 创建每个下拉功能的名称管理器
  3. 在隐藏的sheet中生成下拉菜单所需要的row
代码如下:
/**
* 第一部分
* 将三个列表所有字段从数据库查询出,并生成名称管理器,存放至隐藏的sheet中
*/
private static HSSFWorkbook writePorpData() {
int index = 1;
HSSFWorkbook wb = new HSSFWorkbook(); //Excel工作簿创建
wb.createSheet(DICT_SHEET_TEST); //创建主工作表sheet
Sheet dictDataSheet = wb.createSheet(DICT_SHEET_DATA); //创建数据源字段sheet
List<Province> provinceList = GetData.getProvinces(); //获取所有省份 --测试数据,不影响功能
List<String> provinceNames = new ArrayList<String>(); //1.存放所有省份的名称
provinceNames.add(" "); //使下拉框有置空的选择
//遍历每个省份
for (Province province : provinceList) {
String proName = province.getProvinceName(); //获取每个省份名称
provinceNames.add(proName);
String provinceId = province.getProvinceId(); //获取每个省份Id
List<Area> areaList = GetData.getAreas(provinceId); //获取每个地区 --测试数据,不影响功能
List<String> areaNames = new ArrayList<String>(); //2.存放所有地区名称
areaNames.add(" "); //使下拉框有置空的选择
//遍历每个地区
for (Area area : areaList) {
String areaName = area.getAreaName();
areaNames.add(areaName);
String areaId = area.getAreaId();
List<City> cityList = GetData.getCities(areaId); //获取每个城市 --测试数据,不影响功能
List<String> cityNames = new ArrayList<String>(); //3.存放所有城市名称
cityNames.add(" "); //使下拉框有置空的选择
//遍历每个城市
for (City city : cityList) {
String cityName = city.getCityName();
cityNames.add(cityName);
}
cityNames.add(0, areaName);
createRowData(dictDataSheet.createRow(index++),cityNames);// 3.创建城市row
int i2 = 0;
createExcelName(wb,cityNames.get(i2++),index,cityNames.size()-1,true); //3.城市row,指定名称管理
}
areaNames.add(0, proName);
createRowData(dictDataSheet.createRow(index++),areaNames);// 2.创建地区row
int i1 = 0;
createExcelName(wb,areaNames.get(i1++),index,areaNames.size()-1,true); //2.地区row,指定名称管理
}
createRowData(dictDataSheet.createRow(0),provinceNames); // 1.创建省份row,写入数据
createExcelName(wb,DICT_MNGNAME,1,provinceNames.size()-1, false); //1.省份row,指定名称管理
wb.setSheetHidden(wb.getSheetIndex(DICT_SHEET_DATA), true); //设置隐藏的sheet
return wb;
}

第二部分:

此部分方法都是第一部分核心处理所要使用的几个函数:

  1. 创建隐藏sheet数据行的函数
  2. 创建名称管理器的函数
  3. 创建名称管理器所需要的:计算列的表达式的函数
  4. 设置数据有效性的函数
  5. 数据验证的函数
代码如下:
/**
* 第二部分:2.1 创建隐藏sheet数据行的函数
*/
private static void createRowData(Row curRow,List<String> dataList){
if(dataList != null && dataList.size()>0){
int m = 0;
for (String dataValue : dataList) {
Cell dataCell = curRow.createCell(m++);
dataCell.setCellValue(dataValue);
}
}
}
/**
* 第二部分:2.2 创建名称管理器的函数 每一行数据创建一个
*/
private static void createExcelName(HSSFWorkbook workbook,String nameCode,int order,int size,boolean cascadeFlag){
Name name;
name = workbook.createName();
name.setNameName(nameCode);
String cellString = DICT_SHEET_DATA + "!" + createExcelNameList(order,size,cascadeFlag);
name.setRefersToFormula(cellString);
}
/**
* 第二部分:2.3 名称数据行列计算表达式
*/
private static String createExcelNameList(int order,int size,boolean cascadeFlag){
char start='A';
if(cascadeFlag){
start = 'B';
if(size <= 25){
char end = (char)(start + size -1);
return "$" + start + "$" + order + ":$" + end + "$" + order;
}else{
char endPrefix = 'A';
char endSuffix = 'A';
if((size-25)/26 == 0 || size ==51){ //26-51之间,包括边界
if((size-25)%26 == 0){ //边界值
endSuffix = (char)('A' + 25);
}else{
endSuffix = (char)('A' + (size-25)%26-1);
}
}else{ //51之上
if((size-25)%26 == 0){
endSuffix = (char)('A' + 25);
endPrefix = (char)(endPrefix + (size-25)/26 -1);
}else{
endSuffix = (char)('A' + (size-25)%26-1);
endPrefix = (char)(endPrefix + (size-25)/26);
}
}
return "$" + start + "$" + order + ":$" + endPrefix+endSuffix + "$" + order;
}
}else{
if(size<=26){
char end = (char)(start + size -1);
return "$" + start + "$" + order + ":$" + end + "$" + order;
}else{
char endPrefix = 'A';
char endSuffix = 'A';
if(size%26 == 0){
endSuffix = (char)('A' + 25);
if(size>52 && size/26>0){
endPrefix = (char)(endPrefix + size/26-2);
}
}else{
endSuffix = (char)('A' + size%26-1);
if(size>52 && size/26>0){
endPrefix = (char)(endPrefix + size/26-1);
}
}
return "$" + start + "$" + order + ":$" + endPrefix+endSuffix + "$" + order;
}
}
}
/**
* 第二部分:2.4 设置数据的有效性,即下拉列表的生成
*/
public static HSSFWorkbook getWorkbook(HSSFWorkbook wb, int size){
Sheet sheet = wb.getSheet(DICT_SHEET_TEST);
DataValidation dataValidation = null;
for (int x = 1; x <= size+1; x++) {
dataValidation = getDataValidation("IF($B$"+x+"=\" \",\" \",INDIRECT($B$"+x+"))", x, 3);
sheet.addValidationData(dataValidation); dataValidation = getDataValidation("IF($C$"+x+"=\" \",\" \",INDIRECT($C$"+x+"))", x, 4);
sheet.addValidationData(dataValidation);
}
return wb;
}
/**
* 第二部分:2.5 数据验证
*/
@SuppressWarnings("deprecation")
private static DataValidation getDataValidation(String formulaString,int naturalRowIndex,int naturalColIndex){
//设置数据有效性加载在哪个单元格上 四个参数:起始行、终止行、起始列、终止列
int firstRow = naturalRowIndex-1;
int lastRow = naturalRowIndex-1;
int firstCol = naturalColIndex-1;
int lastCol = naturalColIndex-1;
CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
//加载下拉列表
DVConstraint constraint = DVConstraint.createFormulaListConstraint(formulaString);
//数据有效性对象
DataValidation dataValidation = new HSSFDataValidation(regions, constraint);
//设置输入信息提示信息
dataValidation.createPromptBox("下拉提示", "请选择合适的值");
//设置输入错误提示信息
dataValidation.createErrorBox("非法输入", "不允许输入,请选取下拉值!");
return dataValidation;
}

第三部分:

此部分即获得上两部处理完成后的工作簿,然后填充数据即可。

代码如下:
/**
* 创建并生成excel文档
*/
public static void createExcelFile(){
List<Student> studens = GetData.getStudents(); //测试数据,不影响功能
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File(filePathName));
HSSFWorkbook wb = writePorpData(); // 创建工作簿
HSSFSheet sheet = wb.getSheet(DICT_SHEET_TEST); // 获取主工作表
wb = getWorkbook(wb, studens.size()); HSSFRow row = null;
HSSFCell cell = null;
sheet.setDefaultColumnWidth(28);
row = sheet.createRow(0); // 新增标题行
cell = row.createCell(0);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue("学生");
cell = row.createCell(1);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue("省份");
cell = row.createCell(2);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue("地区");
cell = row.createCell(3);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue("城市"); int i = 1;
for (Student stu : studens) {
row = sheet.createRow(i); // 新增一行
cell = row.createCell(0);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(stu.getStudentName()); // 学生姓名
cell = row.createCell(1);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(stu.getProvince()); //省份
cell = row.createCell(2);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(stu.getArea()); // 地区
cell = row.createCell(3);
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setCellValue(stu.getCity()); //城市
i++;
} sheet.setColumnWidth(0,5000);//设置列宽
sheet.setColumnWidth(1,5000);//设置列宽
sheet.setColumnWidth(2,5000);//设置列宽
sheet.setColumnWidth(3,5000);//设置列宽 wb.write(fileOutputStream); //生成文档
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

Java下使用Apache POI生成具有三级联动下拉列表的Excel文档的更多相关文章

  1. 【Java】使用Apache POI生成和解析Excel文件

    概述 Excel是我们平时工作中比较常用的用于存储二维表数据的,JAVA也可以直接对Excel进行操作,分别有jxl和poi,2种方式. HSSF is the POI Project's pure ...

  2. python3如何随机生成大数据存储到指定excel文档里

    本次主要采用的是python3的第三方库xlwt,来创建一个excel文件.具体步骤如下: 1.确认存储位置,文件命名跟随时间格式 2.封装写入格式 3.实现随机数列生成 4.定位行和列把随机数写入 ...

  3. java用org.apache.poi包操作excel

    一.POI简介 Jakarta POI 是apache的子项目,目标是处理ole2对象.它提供了一组操纵Windows文档的Java API 目前比较成熟的是HSSF接口,处理MS Excel(97- ...

  4. Java使用poi包读取Excel文档

    项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org. ...

  5. Java之Poi导出Excel文档

    一.Poi简介 在后台管理系统中,我们经常要做的导出操作,通常导出为Excel文档的形式,而Poi则提供了这种需要的支持. 二.Workbook/HSSFWorkbook/XSSFWorkbook 1 ...

  6. java、ruby、python、php等如何生成excel文档?

    excel在我们日常工作生活中会经常用到,通常我们都是用office软件去编写文档.但是对于格式一致的excel文档,如果还是使用人工完成,那绝不是我们软件工程师的姿态了~ 下面我就介绍一种方法,不需 ...

  7. java生成excel文档

    要做一个后台自动化,要先预先生成一份文档,以下内容生成了文档 首先下载jxl.jar包,下载地址:http://download.csdn.net/detail/prstaxy/4469935 1.生 ...

  8. struts2中利用POI导出Excel文档并下载

    1.项目组负责人让我实现这个接口,因为以前做过类似的,中间并没有遇到什么太困难的事情.其他不说,先上代码: package com.tydic.eshop.action.feedback; impor ...

  9. POI 读取Excel文档中的数据——兼容Excel2003和Excel2007

    Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. HSSF - 提供读写Microsoft Exce ...

随机推荐

  1. 怎样在Spark、Flink应用中使用Protobuf 3的包

    如果在在Spark.Flink应用中使用Protobuf 3的包,因为Spark默认使用的是2.5版本的包,提交任务时,可能会报如下异常: com.google.protobuf.CodedInput ...

  2. Struts2学习---result结果集

    这一章节主要介绍如何配置结果集,分为以下几个知识点: 结果集类型(result type) 全局结果集(global types) 动态结果集(dynamic type) 带有参数的结果集(type ...

  3. ABAP中的枚举对象

    枚举对象是枚举类型的数据对象.枚举对象只能包含类型为枚举类型的枚举值.ABAP从版本7.51开始支持它们. 这是一种常见的模式.在ABAP 7.51之前,人们通常用如下方式实现类似的功能: CLASS ...

  4. ABP .Net Core Entity Framework迁移使用MySql数据库

    一.迁移说明 ABP模板项目Entity Framework Core默认使用的是Sql Server,也很容易将数据库迁移到MySQL,步骤如下. 二.迁移MySQL步骤 1. 下载项目 请到 ht ...

  5. Akka Serialization

    Akka本身使用了Protocol Buffers来序列化内部消息(比如gossip message).Akka系统还可以配置自定义序列化机制. 配置conf akka { actor { ## 在a ...

  6. bzoj 2427: [HAOI2010]软件安装

    Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...

  7. 海外ubuntu,lamp,ftp,phpmyadmin配置

    海外ubuntu,lamp,ftp,phpmyadmin配置 1. 更换源 1.1 clean /etc/apt/sources.list file 1.2 Ubuntu Sources List G ...

  8. 初识JavaScript(一)

    初识JavaScript(一) 最近由于工作的需要的原因,我从一个写后台的现在让我转到写前端,再加上我的js部分特别的差,所以我现在开始学习js部分的知识. 我的第一篇博文就这样开始写了.俗话说,千里 ...

  9. js获取手机屏幕宽度、高度

    网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...

  10. [编织消息框架][消息服务]rmi

    RMI(即Remote Method Invoke 远程方法调用) 远程对象: 用于远程客户端调用 必需继承java.rmi.Remote,每个调用方法必须添加java.rmi.RemoteExcep ...