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

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

先上效果图:


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

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

此部分包含几个方面:

  1. 获取三级下拉框各列的数据;
  2. 创建每个下拉功能的名称管理器
  3. 在隐藏的sheet中生成下拉菜单所需要的row
代码如下:
  1. /**
  2. * 第一部分
  3. * 将三个列表所有字段从数据库查询出,并生成名称管理器,存放至隐藏的sheet中
  4. */
  5. private static HSSFWorkbook writePorpData() {
  6. int index = 1;
  7. HSSFWorkbook wb = new HSSFWorkbook(); //Excel工作簿创建
  8. wb.createSheet(DICT_SHEET_TEST); //创建主工作表sheet
  9. Sheet dictDataSheet = wb.createSheet(DICT_SHEET_DATA); //创建数据源字段sheet
  10. List<Province> provinceList = GetData.getProvinces(); //获取所有省份 --测试数据,不影响功能
  11. List<String> provinceNames = new ArrayList<String>(); //1.存放所有省份的名称
  12. provinceNames.add(" "); //使下拉框有置空的选择
  13. //遍历每个省份
  14. for (Province province : provinceList) {
  15. String proName = province.getProvinceName(); //获取每个省份名称
  16. provinceNames.add(proName);
  17. String provinceId = province.getProvinceId(); //获取每个省份Id
  18. List<Area> areaList = GetData.getAreas(provinceId); //获取每个地区 --测试数据,不影响功能
  19. List<String> areaNames = new ArrayList<String>(); //2.存放所有地区名称
  20. areaNames.add(" "); //使下拉框有置空的选择
  21. //遍历每个地区
  22. for (Area area : areaList) {
  23. String areaName = area.getAreaName();
  24. areaNames.add(areaName);
  25. String areaId = area.getAreaId();
  26. List<City> cityList = GetData.getCities(areaId); //获取每个城市 --测试数据,不影响功能
  27. List<String> cityNames = new ArrayList<String>(); //3.存放所有城市名称
  28. cityNames.add(" "); //使下拉框有置空的选择
  29. //遍历每个城市
  30. for (City city : cityList) {
  31. String cityName = city.getCityName();
  32. cityNames.add(cityName);
  33. }
  34. cityNames.add(0, areaName);
  35. createRowData(dictDataSheet.createRow(index++),cityNames);// 3.创建城市row
  36. int i2 = 0;
  37. createExcelName(wb,cityNames.get(i2++),index,cityNames.size()-1,true); //3.城市row,指定名称管理
  38. }
  39. areaNames.add(0, proName);
  40. createRowData(dictDataSheet.createRow(index++),areaNames);// 2.创建地区row
  41. int i1 = 0;
  42. createExcelName(wb,areaNames.get(i1++),index,areaNames.size()-1,true); //2.地区row,指定名称管理
  43. }
  44. createRowData(dictDataSheet.createRow(0),provinceNames); // 1.创建省份row,写入数据
  45. createExcelName(wb,DICT_MNGNAME,1,provinceNames.size()-1, false); //1.省份row,指定名称管理
  46. wb.setSheetHidden(wb.getSheetIndex(DICT_SHEET_DATA), true); //设置隐藏的sheet
  47. return wb;
  48. }

第二部分:

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

  1. 创建隐藏sheet数据行的函数
  2. 创建名称管理器的函数
  3. 创建名称管理器所需要的:计算列的表达式的函数
  4. 设置数据有效性的函数
  5. 数据验证的函数
代码如下:
  1. /**
  2. * 第二部分:2.1 创建隐藏sheet数据行的函数
  3. */
  4. private static void createRowData(Row curRow,List<String> dataList){
  5. if(dataList != null && dataList.size()>0){
  6. int m = 0;
  7. for (String dataValue : dataList) {
  8. Cell dataCell = curRow.createCell(m++);
  9. dataCell.setCellValue(dataValue);
  10. }
  11. }
  12. }
  13. /**
  14. * 第二部分:2.2 创建名称管理器的函数 每一行数据创建一个
  15. */
  16. private static void createExcelName(HSSFWorkbook workbook,String nameCode,int order,int size,boolean cascadeFlag){
  17. Name name;
  18. name = workbook.createName();
  19. name.setNameName(nameCode);
  20. String cellString = DICT_SHEET_DATA + "!" + createExcelNameList(order,size,cascadeFlag);
  21. name.setRefersToFormula(cellString);
  22. }
  23. /**
  24. * 第二部分:2.3 名称数据行列计算表达式
  25. */
  26. private static String createExcelNameList(int order,int size,boolean cascadeFlag){
  27. char start='A';
  28. if(cascadeFlag){
  29. start = 'B';
  30. if(size <= 25){
  31. char end = (char)(start + size -1);
  32. return "$" + start + "$" + order + ":$" + end + "$" + order;
  33. }else{
  34. char endPrefix = 'A';
  35. char endSuffix = 'A';
  36. if((size-25)/26 == 0 || size ==51){ //26-51之间,包括边界
  37. if((size-25)%26 == 0){ //边界值
  38. endSuffix = (char)('A' + 25);
  39. }else{
  40. endSuffix = (char)('A' + (size-25)%26-1);
  41. }
  42. }else{ //51之上
  43. if((size-25)%26 == 0){
  44. endSuffix = (char)('A' + 25);
  45. endPrefix = (char)(endPrefix + (size-25)/26 -1);
  46. }else{
  47. endSuffix = (char)('A' + (size-25)%26-1);
  48. endPrefix = (char)(endPrefix + (size-25)/26);
  49. }
  50. }
  51. return "$" + start + "$" + order + ":$" + endPrefix+endSuffix + "$" + order;
  52. }
  53. }else{
  54. if(size<=26){
  55. char end = (char)(start + size -1);
  56. return "$" + start + "$" + order + ":$" + end + "$" + order;
  57. }else{
  58. char endPrefix = 'A';
  59. char endSuffix = 'A';
  60. if(size%26 == 0){
  61. endSuffix = (char)('A' + 25);
  62. if(size>52 && size/26>0){
  63. endPrefix = (char)(endPrefix + size/26-2);
  64. }
  65. }else{
  66. endSuffix = (char)('A' + size%26-1);
  67. if(size>52 && size/26>0){
  68. endPrefix = (char)(endPrefix + size/26-1);
  69. }
  70. }
  71. return "$" + start + "$" + order + ":$" + endPrefix+endSuffix + "$" + order;
  72. }
  73. }
  74. }
  75. /**
  76. * 第二部分:2.4 设置数据的有效性,即下拉列表的生成
  77. */
  78. public static HSSFWorkbook getWorkbook(HSSFWorkbook wb, int size){
  79. Sheet sheet = wb.getSheet(DICT_SHEET_TEST);
  80. DataValidation dataValidation = null;
  81. for (int x = 1; x <= size+1; x++) {
  82. dataValidation = getDataValidation("IF($B$"+x+"=\" \",\" \",INDIRECT($B$"+x+"))", x, 3);
  83. sheet.addValidationData(dataValidation);
  84. dataValidation = getDataValidation("IF($C$"+x+"=\" \",\" \",INDIRECT($C$"+x+"))", x, 4);
  85. sheet.addValidationData(dataValidation);
  86. }
  87. return wb;
  88. }
  89. /**
  90. * 第二部分:2.5 数据验证
  91. */
  92. @SuppressWarnings("deprecation")
  93. private static DataValidation getDataValidation(String formulaString,int naturalRowIndex,int naturalColIndex){
  94. //设置数据有效性加载在哪个单元格上 四个参数:起始行、终止行、起始列、终止列
  95. int firstRow = naturalRowIndex-1;
  96. int lastRow = naturalRowIndex-1;
  97. int firstCol = naturalColIndex-1;
  98. int lastCol = naturalColIndex-1;
  99. CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
  100. //加载下拉列表
  101. DVConstraint constraint = DVConstraint.createFormulaListConstraint(formulaString);
  102. //数据有效性对象
  103. DataValidation dataValidation = new HSSFDataValidation(regions, constraint);
  104. //设置输入信息提示信息
  105. dataValidation.createPromptBox("下拉提示", "请选择合适的值");
  106. //设置输入错误提示信息
  107. dataValidation.createErrorBox("非法输入", "不允许输入,请选取下拉值!");
  108. return dataValidation;
  109. }

第三部分:

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

代码如下:
  1. /**
  2. * 创建并生成excel文档
  3. */
  4. public static void createExcelFile(){
  5. List<Student> studens = GetData.getStudents(); //测试数据,不影响功能
  6. try {
  7. FileOutputStream fileOutputStream = new FileOutputStream(new File(filePathName));
  8. HSSFWorkbook wb = writePorpData(); // 创建工作簿
  9. HSSFSheet sheet = wb.getSheet(DICT_SHEET_TEST); // 获取主工作表
  10. wb = getWorkbook(wb, studens.size());
  11. HSSFRow row = null;
  12. HSSFCell cell = null;
  13. sheet.setDefaultColumnWidth(28);
  14. row = sheet.createRow(0); // 新增标题行
  15. cell = row.createCell(0);
  16. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  17. cell.setCellValue("学生");
  18. cell = row.createCell(1);
  19. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  20. cell.setCellValue("省份");
  21. cell = row.createCell(2);
  22. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  23. cell.setCellValue("地区");
  24. cell = row.createCell(3);
  25. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  26. cell.setCellValue("城市");
  27. int i = 1;
  28. for (Student stu : studens) {
  29. row = sheet.createRow(i); // 新增一行
  30. cell = row.createCell(0);
  31. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  32. cell.setCellValue(stu.getStudentName()); // 学生姓名
  33. cell = row.createCell(1);
  34. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  35. cell.setCellValue(stu.getProvince()); //省份
  36. cell = row.createCell(2);
  37. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  38. cell.setCellValue(stu.getArea()); // 地区
  39. cell = row.createCell(3);
  40. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  41. cell.setCellValue(stu.getCity()); //城市
  42. i++;
  43. }
  44. sheet.setColumnWidth(0,5000);//设置列宽
  45. sheet.setColumnWidth(1,5000);//设置列宽
  46. sheet.setColumnWidth(2,5000);//设置列宽
  47. sheet.setColumnWidth(3,5000);//设置列宽
  48. wb.write(fileOutputStream); //生成文档
  49. fileOutputStream.close();
  50. } catch (FileNotFoundException e) {
  51. e.printStackTrace();
  52. } catch (IOException e) {
  53. e.printStackTrace();
  54. }
  55. }

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. 关于postgres中的一些宏的tips

    Postgresql作为C语言开发的代码,其中大量的运用了一些宏的操作. 因此理解这些宏很重要,然而有时候这些宏总让人很费解. 作为一个经常翻翻postgresql源码的小白,在这里做一个记录吧,方便 ...

  2. 判断DataTable某一列是否是时间列

    DataTable dt = new DataTable("Table0"); dt.Columns.Add("column0", System.Type.Ge ...

  3. Linux中dos2unix批量转换

    有时候遇到多层目录下的文件格式需要转换,dos2unix 没有-r之类的递归指令,所以需要与find还有管道结合. find -type f | xargs dos2unix -o

  4. 7 Series GTP IP核使用总结 IP核配置篇

    FPGA内嵌收发器相当于以太网中的PHY芯片,但更灵活更高效,线速率也在随着FPGA芯片的发展升级.本文对7系列FPGA内部高速收发器GTP IP核的配置和使用做些简单的总结,以备后续回顾重用.本文是 ...

  5. golang 如何验证struct字段的数据格式

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/125 假设我们有如下结构体: type User struct ...

  6. bzoj 1996: [Hnoi2010]chorus 合唱队

    Description Input Output Sample Input 4 1701 1702 1703 1704 Sample Output 8 HINT Source 因为只会在区间的两端进行 ...

  7. ES6(一) let and const

    1.let 用于变量声明,仅在块级作用域内有效. ES6新增了块级作用域,在ES5中没有块级作用域这个概念. { let a = 10; var b = 1; } console.log(b); // ...

  8. 判断python对象是否可调用的三种方式及其区别

    查找资料,基本上判断python对象是否为可调用的函数,有三种方法 使用内置的callable函数 callable(func) 用于检查对象是否可调用,返回True也可能调用失败,但是返回False ...

  9. Tsung:开源多协议分布式负载&压力测试工具

    Main features High Performance: the load can be distributed on a cluster of client machines Multi-pr ...

  10. 在阿里云 ECS 搭建 nginx https nodejs 环境(二、https)

    在阿里云 ECS 搭建 nginx https nodejs 环境(二) 这次主要内容是 如何在 ubuntu 的nginx 下配置 二级域名. 一. 域名解析 首先你需要去到你的 域名服务商那边 进 ...