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

原文地址:https://www.cnblogs.com/dcncy/p/8153191.html

时间: 2024-10-12 17:55:42

使用POI生成具有三级下拉菜单的Excel文档的相关文章

Java 使用POI生成带联动下拉框的excel表格

java 小学生一枚 ,学习记录. import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.poi.hssf.usermodel

CSS样式三级下拉菜单

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="

三级下拉菜单 (通用版)

<html><head><title>阿里西西网页特效演示, 三级下拉菜单 (通用版)</title><meta http-equiv="Content-Type" content="text/html; charset=gb2312"> </head><body> <SCRIPT LANGUAGE="JavaScript"><!--functi

CSS打造三级下拉菜单

<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><meta name="keywords" content="站长,网页特效,js特效,广告代码,zzjs,zzjs.net,sky,www.zzjs.net,站长特效 网" /><meta name="d

CSS3实现的一款三级下拉菜单

<html> <head> <title>河北礼品公司</title> <style> body { background:#eee; margin:0; padding:0; } .example { background:#fff url(/imagesforcode/201306/clouds-in-blue-sky.jpg); width:770px; height:570px; border:1px #000 solid; margin

Django分析之三级下拉菜单选择省/市/县

今天遇到了一个一直想做却没有机会去做的功能,今天完成了便记录下来. 那这次是具体是个什么功能呢?其实还是很简单的效果,就是在用户注册的时候可以选择省/市/县,很简单的一个小功能. 那现在就开始了~首先我们要在数据库中先建一个表,用来保存全国的省/市/县信息,下面是表的结构: CREATE TABLE IF NOT EXISTS "china_regionalTable" ( "id" integer NOT NULL, "name" varcha

日期三级下拉菜单

Html 1 <select id="selYear"></select> 2 <select id="selMonth"></select> 3 <select id="selDay"></select> 4 <script src="DateSelector.js"></script> 5 <script type=&qu

三级下拉菜单

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <style type="text/css"> ul li.yiji { list-style-image: url(img/-.gif); } ul li{ cursor: pointer; } </styl

MVC省市区三级下拉菜单联动

控制器端代码(都在同一个表中): using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MvcApplication10.Models; namespace 下拉列表联动显示_中国省市_.Controllers { public class HomeController : Controller { [HttpGet] //刚