POI导出级联下拉框不用限制行数

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、最后效果

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值