poi实现生成下拉选联动

来源:互联网 发布:朱雀网络和小米的关系 编辑:程序博客网 时间:2024/06/14 16:12

在我们实际的程序开发中,经常需要用到从excel导入数据中系统中,而为了防止用户在excel中乱输入文字,有些需要用到下拉选的地方,就需要从程序中动态生成模板。本例子简单的讲解一下,如何生成级联下拉选。

 

效果图:(选择汽车这个下拉选、后面水果下拉选的值动态改变)


 

级联下拉选的实现步骤:

1.在excel中的另外一个sheet页中,保存着下拉选的值

2.给下拉中的数据创建一个名字( 类似于在excel中操作命名管理器 )

3.使用INDIRECT()函数获取到级联下拉选的值。

4.poi官网上创建级联下拉选的说明



  本例子中,动态excel模板的生成的一个简单思路。

注意:每一个模板字段,都是一个ExportDefinition对象,如果是下拉选的类型,则mainDict字段有值,根据它的值从DictData中加载下拉选的值,如果选择它存在一个级联操作,那么subDictsubField字段有值。subDict也是从DictData中加载数据,subField表示级联的字段

思路:

1.根据一组ExportDefinition定义对象,生成excel的导出模板,此时导出的模板中只有一行到出头数据。

2.创建数据字典页,这个里面保存下拉选需要用到的数据。

3.如果是主下拉选,则给主下拉选创建一个名称管理。

4.如果是主下拉选,并且关联了级联下拉选,则此时需要加载子下拉选的数据,且根据主下拉选中的每一项创建一个名称管理,值为关联的子下拉选的值

5.使用INDIRECT函数、设置数据的有效性等。

 

步骤:

下载点击

1.创建下拉选的值

Java代码  收藏代码
  1. public class DictData {  
  2.     public static Map<String, Object> dict = null;  
  3.     static {  
  4.         dict = new HashMap<>();  
  5.         List<String> list = new ArrayList<>();  
  6.         list.add("汽车");  
  7.         list.add("水果");  
  8.         dict.put("car-dict", list);  
  9.         Map<String, List<String>> subMap = new HashMap<>();  
  10.         list = new ArrayList<>();  
  11.         list.add("宝马");  
  12.         list.add("大众");  
  13.         subMap.put("汽车", list);  
  14.         list = new ArrayList<>();  
  15.         list.add("苹果");  
  16.         list.add("梨子");  
  17.         subMap.put("水果", list);  
  18.         dict.put("fruit-dict", subMap);  
  19.         list = new ArrayList<>();  
  20.         list.add("汽车-1");  
  21.         list.add("水果-1");  
  22.         dict.put("t-dict", list);  
  23.     }  
  24.   
  25.     /** 获取数据字典中的值 */  
  26.     public static Object getDict(String dict) {  
  27.         return DictData.dict.get(dict);  
  28.     }  
  29. }  

 2.创建一个RowCellIndex对象,用于维护,当前创建了下拉选的第几行第几列

Java代码  收藏代码
  1. public class RowCellIndex {  
  2.     /** 单元格的行索引 */  
  3.     private int rowIndex;  
  4.     /** 单元格的列索引 */  
  5.     private int cellIndex;  
  6.     public RowCellIndex(int rowIndex, int cellIndex) {  
  7.         this.rowIndex = rowIndex;  
  8.         this.cellIndex = cellIndex;  
  9.     }  
  10.     public int getRowIndex() {  
  11.         return rowIndex;  
  12.     }  
  13.     public void setRowIndex(int rowIndex) {  
  14.         this.rowIndex = rowIndex;  
  15.     }  
  16.     public int getCellIndex() {  
  17.         return cellIndex;  
  18.     }  
  19.     public void setCellIndex(int cellIndex) {  
  20.         this.cellIndex = cellIndex;  
  21.     }  
  22.     public int incrementRowIndexAndGet() {  
  23.         this.rowIndex++;  
  24.         return this.getRowIndex();  
  25.     }  
  26.     public int incrementCellIndexAndGet() {  
  27.         this.cellIndex++;  
  28.         return this.getCellIndex();  
  29.     }  
  30. }  

 3.创建一个excel列的导出定义对象,省略部分getter和setter方法

Java代码  收藏代码
  1. public class ExportDefinition {  
  2.     private String title; // 标题  
  3.     private String field; // 字段  
  4.     private int rowIndex; // 所在的行  
  5.     private int cellIndex; // 所在的列  
  6.     private String mainDict; // 主字典-用于加载主字典的数据  
  7.     private String subDict; // 子字典-用于加载subField的数据  
  8.     private String subField; // 即需要级联的字典  
  9.     private String refName; // 主字段所在的位置  
  10.     private String point; // 标题的坐标  
  11.     private boolean validate;// 是否设置数据的有限性  
  12.     public ExportDefinition(String title, String field, String mainDict, String subDict, String subField) {  
  13.         this.title = title;  
  14.         this.field = field;  
  15.         this.mainDict = mainDict;  
  16.         this.subDict = subDict;  
  17.         this.subField = subField;  
  18.     }  

 4.实现导出

下载点击

Java代码  收藏代码
  1. package com.huan.excel.ex2;  
  2.   
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.OutputStream;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.Map.Entry;  
  10. import java.util.Objects;  
  11.   
  12. import org.apache.poi.hssf.usermodel.DVConstraint;  
  13. import org.apache.poi.hssf.usermodel.HSSFDataValidation;  
  14. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  15. import org.apache.poi.hssf.util.CellReference;  
  16. import org.apache.poi.ss.usermodel.DataValidation;  
  17. import org.apache.poi.ss.usermodel.Name;  
  18. import org.apache.poi.ss.usermodel.Row;  
  19. import org.apache.poi.ss.usermodel.Sheet;  
  20. import org.apache.poi.ss.usermodel.Workbook;  
  21. import org.apache.poi.ss.util.CellRangeAddressList;  
  22.   
  23. /** 
  24.  * 生成级联下拉选 
  25.  *  
  26.  * @描述 
  27.  * @作者 huan 
  28.  * @时间 2017年3月31日 - 下午9:14:43 
  29.  */  
  30. public class DropDownListTest {  
  31.   
  32.     private static final String DICT_SHEET = "DICT_SHEET";  
  33.   
  34.     public static void main(String[] args) throws IOException {  
  35.         // 1.准备需要生成excel模板的数据  
  36.         List<ExportDefinition> edList = new ArrayList<>(2);  
  37.         edList.add(new ExportDefinition("生活用品""xx"nullnullnull));  
  38.         edList.add(new ExportDefinition("汽车""cat""car-dict""fruit-dict""fruit"));  
  39.         edList.add(new ExportDefinition("水果""fruit""fruit-dict"""""));  
  40.         edList.add(new ExportDefinition("测试""yy""t-dict"nullnull));  
  41.   
  42.         // 2.生成导出模板  
  43.         Workbook wb = new HSSFWorkbook();  
  44.         Sheet sheet = createExportSheet(edList, wb);  
  45.   
  46.         // 3.创建数据字典sheet页  
  47.         createDictSheet(edList, wb);  
  48.   
  49.         // 4.设置数据有效性  
  50.         setDataValidation(edList, sheet);  
  51.   
  52.         // 5.保存excel到本地  
  53.         OutputStream os = new FileOutputStream("d:/4.xls");  
  54.         wb.write(os);  
  55.   
  56.         System.out.println("模板生成成功.");  
  57.     }  
  58.   
  59.     /** 
  60.      * @param edList 
  61.      * @param sheet 
  62.      */  
  63.     private static void setDataValidation(List<ExportDefinition> edList, Sheet sheet) {  
  64.         for (ExportDefinition ed : edList) {  
  65.             if (ed.isValidate()) {// 说明是下拉选  
  66.                 DVConstraint constraint = DVConstraint.createFormulaListConstraint(ed.getField());  
  67.                 if (null == ed.getRefName()) {// 说明是一级下拉选  
  68.                     createDataValidate(sheet, ed, constraint);  
  69.                 } else {// 说明是二级下拉选  
  70.                     constraint = DVConstraint.createFormulaListConstraint("INDIRECT(" + ed.getRefName() + ")");  
  71.                     createDataValidate(sheet, ed, constraint);  
  72.                 }  
  73.             }  
  74.         }  
  75.     }  
  76.   
  77.     /** 
  78.      * @param sheet 
  79.      * @param ed 
  80.      * @param constraint 
  81.      */  
  82.     private static void createDataValidate(Sheet sheet, ExportDefinition ed, DVConstraint constraint) {  
  83.         CellRangeAddressList regions = new CellRangeAddressList(ed.getRowIndex() + 1, ed.getRowIndex() + 100, ed.getCellIndex(), ed.getCellIndex());  
  84.         DataValidation dataValidation = new HSSFDataValidation(regions, constraint);  
  85.         dataValidation.setSuppressDropDownArrow(false);  
  86.         // 设置提示信息  
  87.         dataValidation.createPromptBox("操作提示""请选择下拉选中的值");  
  88.         // 设置输入错误信息  
  89.         dataValidation.createErrorBox("错误提示""请从下拉选中选择,不要随便输入");  
  90.         sheet.addValidationData(dataValidation);  
  91.     }  
  92.   
  93.     /** 
  94.      * @param edList 
  95.      * @param wb 
  96.      */  
  97.     private static void createDictSheet(List<ExportDefinition> edList, Workbook wb) {  
  98.         Sheet sheet = wb.createSheet(DICT_SHEET);  
  99.         RowCellIndex rci = new RowCellIndex(00);  
  100.         for (ExportDefinition ed : edList) {  
  101.             String mainDict = ed.getMainDict();  
  102.             if (null != mainDict && null == ed.getRefName()) {// 是第一个下拉选  
  103.                 List<String> mainDictList = (List<String>) DictData.getDict(mainDict);  
  104.                 String refersToFormula = createDictAndReturnRefFormula(sheet, rci, mainDictList);  
  105.                 // 创建 命名管理  
  106.                 createName(wb, ed.getField(), refersToFormula);  
  107.                 ed.setValidate(true);  
  108.             }  
  109.             if (null != mainDict && null != ed.getSubDict() && null != ed.getSubField()) {// 联动时加载ed.getSubField()的数据  
  110.                 ExportDefinition subEd = fiterByField(edList, ed.getSubField());// 获取需要级联的那个字段  
  111.                 if (null == subEd) {  
  112.                     continue;  
  113.                 }  
  114.                 subEd.setRefName(ed.getPoint());// 保存主下拉选的位置  
  115.                 subEd.setValidate(true);  
  116.                 Map<String, List<String>> subDictListMap = (Map<String, List<String>>) DictData.getDict(ed.getSubDict());  
  117.                 for (Entry<String, List<String>> entry : subDictListMap.entrySet()) {  
  118.                     String refersToFormula = createDictAndReturnRefFormula(sheet, rci, entry.getValue());  
  119.                     // 创建 命名管理  
  120.                     createName(wb, entry.getKey(), refersToFormula);  
  121.                 }  
  122.             }  
  123.         }  
  124.     }  
  125.   
  126.     /** 
  127.      * @param sheet 
  128.      * @param rci 
  129.      * @param mainDict 
  130.      * @return 
  131.      */  
  132.     private static String createDictAndReturnRefFormula(Sheet sheet, RowCellIndex rci, List<String> datas) {  
  133.         Row row = sheet.createRow(rci.incrementRowIndexAndGet());  
  134.         rci.setCellIndex(0);  
  135.         int startRow = rci.getRowIndex();  
  136.         int startCell = rci.getCellIndex();  
  137.         for (String dict : datas) {  
  138.             row.createCell(rci.incrementCellIndexAndGet()).setCellValue(dict);  
  139.         }  
  140.         int endRow = rci.getRowIndex();  
  141.         int endCell = rci.getCellIndex();  
  142.         String startName = new CellReference(DICT_SHEET, startRow, startCell, truetrue).formatAsString();  
  143.         String endName = new CellReference(endRow, endCell, truetrue).formatAsString();  
  144.         String refersToFormula = startName + ":" + endName;  
  145.         System.out.println(refersToFormula);  
  146.         return refersToFormula;  
  147.     }  
  148.   
  149.     /** 
  150.      * @param wb 
  151.      * @param nameName 
  152.      *            表示命名管理的名字 
  153.      * @param refersToFormula 
  154.      */  
  155.     private static void createName(Workbook wb, String nameName, String refersToFormula) {  
  156.         Name name = wb.createName();  
  157.         name.setNameName(nameName);  
  158.         name.setRefersToFormula(refersToFormula);  
  159.     }  
  160.   
  161.     private static ExportDefinition fiterByField(List<ExportDefinition> edList, String field) {  
  162.         for (ExportDefinition ed : edList) {  
  163.             if (Objects.equals(ed.getField(), field)) {  
  164.                 return ed;  
  165.             }  
  166.         }  
  167.         return null;  
  168.     }  
  169.   
  170.     /** 
  171.      * @param edList 
  172.      * @param wb 
  173.      */  
  174.     private static Sheet createExportSheet(List<ExportDefinition> edList, Workbook wb) {  
  175.         Sheet sheet = wb.createSheet("导出模板");  
  176.         RowCellIndex rci = new RowCellIndex(00);  
  177.         Row row = sheet.createRow(rci.getRowIndex());  
  178.         CellReference cr = null;  
  179.         for (ExportDefinition ed : edList) {  
  180.             row.createCell(rci.incrementCellIndexAndGet()).setCellValue(ed.getTitle());  
  181.             ed.setRowIndex(rci.getRowIndex());  
  182.             ed.setCellIndex(rci.getCellIndex());  
  183.             cr = new CellReference(ed.getRowIndex() + 1, ed.getCellIndex(), truetrue);  
  184.             ed.setPoint(cr.formatAsString());  
  185.         }  
  186.         return sheet;  
  187.     }  
  188.   
  189. }  
0 0
原创粉丝点击