1、首先来整理excel模板,新建一个xqsite页,这里用来存下拉框数据源,然后隐藏起来,这里的数据源可以是动态的查数据获得
2、设置所A列的数据有效性,来源的表达式代表取xsqsite的A列的数据
3、设置B列的数据有效性,来源的表达式代表取一级下拉框的值在名称空间里面对应的值(这时候可能设置不了有效性 ,你在xqsite 写一点数据 然后在A2随便选一条数据就行再设置B列的数据有效性就可以了)
4、用代码查数据库获取下拉框的数据源,填数据到xqsite页,然后设置excel的名称空间即可
(1) 怎么往数据源sheet页里面填数据请随意,这里我把数据存成List<List> 形式 里面的一层list 就代表一行一行的数据,用poi写进隐藏的数据源sheet页
(2)然后是设置名称空间,就是把xqsite 里面的数据 A列变成key 从B列开始到后面就是value,有了名称空间之后,加上我们之前设置的数据有效性,当选择校区过后,再选择教学楼,就会去找校区对应的名称空间的值,就可以实现级联效果
5、相关代码如下
/**
* 下载导入模板
*
* @param response response
* @param templatePath templatePath
* @param fileName fileName
* @param constraintMap 下拉框约束条件
* @param isCashcade 是否是级联选择下拉框
*/
public static void downloadTemplate(HttpServletResponse response, String templatePath, String fileName, Map<String, List<List<String>>> constraintMap, boolean isCashcade)
{
//导出2007版本的
org.springframework.core.io.Resource resource = new ClassPathResource(templatePath);
ServletOutputStream os = null;
InputStream is = null;
try
{
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setContentType("application/octet-stream");
is = resource.getInputStream();
os = response.getOutputStream();
Workbook book = new XSSFWorkbook(is);
if (Objects.nonNull(constraintMap))
{
constraintMap.entrySet().stream().forEach(x -> {
String key = x.getKey();
List<List<String>> value = x.getValue();
//获取key对应的隐藏sheet页
Sheet hideSheet = book.getSheet(key);
//写入约束数据
addDataToSheet(value, hideSheet);
//设置名称空间
if (isCashcade)
{
for (int i = 0; i < value.size(); i++)
{
// 添加名称管理器
List<String> children = value.get(i);
String range = getRange(1, i+1, children.size());
Name name = book.createName();
//todo 特殊字符会报错
name.setNameName(children.get(0));
String formula = key + "!" + range;
name.setRefersToFormula(formula);
}
}
});
}
book.write(os);
} catch (IOException e)
{
log.info(e.getMessage());
}
}
/**
* 往隐藏sheet里面添加数据
*
* @param dataList dataList
* @param sheet sheet
*/
public static void addDataToSheet(List<List<String>> dataList, Sheet sheet)
{
//一行一行的添加
for (int i = 0; i < dataList.size(); i++)
{
List<String> x = dataList.get(i);
Row row = sheet.createRow(i);
for (int j = 0; j < x.size(); j++)
{
Cell cell = row.createCell(j);
cell.setCellValue(x.get(j));
}
}
}
/**
* 做级联下拉框要设置名称空间 需要偏移量
*
* @param offset 偏移量,如果给0,表示从A列开始,1,就是从B列
* @param rowId 第几行
* @param colCount 一共多少列
* @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1
* @author denggonghai 2016年8月31日 下午5:17:49
*/
public static String getRange(int offset, int rowId, int colCount)
{
char start = (char) ('A' + offset);
if (colCount <= 25)
{
char end = (char) (start + colCount - 1);
return "$" + start + "$" + rowId + ":$" + end + "$" + rowId;
} else
{
char endPrefix = 'A';
char endSuffix = 'A';
if ((colCount - 25) / 26 == 0 || colCount == 51)
{// 26-51之间,包括边界(仅两次字母表计算)
if ((colCount - 25) % 26 == 0)
{// 边界值
endSuffix = (char) ('A' + 25);
} else
{
endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
}
} else
{// 51以上
if ((colCount - 25) % 26 == 0)
{
endSuffix = (char) ('A' + 25);
endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1);
} else
{
endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
endPrefix = (char) (endPrefix + (colCount - 25) / 26);
}
}
String rang = "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId;
log.info("级联选择范围是:" + rang);
return rang;
}
}
6、最后效果