`

poi实现生成下拉选联动

    博客分类:
  • poi
阅读更多

    在我们实际的程序开发中,经常需要用到从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.创建下拉选的值

public class DictData {
	public static Map<String, Object> dict = null;
	static {
		dict = new HashMap<>();
		List<String> list = new ArrayList<>();
		list.add("汽车");
		list.add("水果");
		dict.put("car-dict", list);
		Map<String, List<String>> subMap = new HashMap<>();
		list = new ArrayList<>();
		list.add("宝马");
		list.add("大众");
		subMap.put("汽车", list);
		list = new ArrayList<>();
		list.add("苹果");
		list.add("梨子");
		subMap.put("水果", list);
		dict.put("fruit-dict", subMap);
		list = new ArrayList<>();
		list.add("汽车-1");
		list.add("水果-1");
		dict.put("t-dict", list);
	}

	/** 获取数据字典中的值 */
	public static Object getDict(String dict) {
		return DictData.dict.get(dict);
	}
}

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

public class RowCellIndex {
	/** 单元格的行索引 */
	private int rowIndex;
	/** 单元格的列索引 */
	private int cellIndex;
	public RowCellIndex(int rowIndex, int cellIndex) {
		this.rowIndex = rowIndex;
		this.cellIndex = cellIndex;
	}
	public int getRowIndex() {
		return rowIndex;
	}
	public void setRowIndex(int rowIndex) {
		this.rowIndex = rowIndex;
	}
	public int getCellIndex() {
		return cellIndex;
	}
	public void setCellIndex(int cellIndex) {
		this.cellIndex = cellIndex;
	}
	public int incrementRowIndexAndGet() {
		this.rowIndex++;
		return this.getRowIndex();
	}
	public int incrementCellIndexAndGet() {
		this.cellIndex++;
		return this.getCellIndex();
	}
}

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

public class ExportDefinition {
	private String title; // 标题
	private String field; // 字段
	private int rowIndex; // 所在的行
	private int cellIndex; // 所在的列
	private String mainDict; // 主字典-用于加载主字典的数据
	private String subDict; // 子字典-用于加载subField的数据
	private String subField; // 即需要级联的字典
	private String refName; // 主字段所在的位置
	private String point; // 标题的坐标
	private boolean validate;// 是否设置数据的有限性
	public ExportDefinition(String title, String field, String mainDict, String subDict, String subField) {
		this.title = title;
		this.field = field;
		this.mainDict = mainDict;
		this.subDict = subDict;
		this.subField = subField;
	}

 4.实现导出

package com.huan.excel.ex2;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddressList;

/**
 * 生成级联下拉选
 * 
 * @描述
 * @作者 huan
 * @时间 2017年3月31日 - 下午9:14:43
 */
public class DropDownListTest {

	private static final String DICT_SHEET = "DICT_SHEET";

	public static void main(String[] args) throws IOException {
		// 1.准备需要生成excel模板的数据
		List<ExportDefinition> edList = new ArrayList<>(2);
		edList.add(new ExportDefinition("生活用品", "xx", null, null, null));
		edList.add(new ExportDefinition("汽车", "cat", "car-dict", "fruit-dict", "fruit"));
		edList.add(new ExportDefinition("水果", "fruit", "fruit-dict", "", ""));
		edList.add(new ExportDefinition("测试", "yy", "t-dict", null, null));

		// 2.生成导出模板
		Workbook wb = new HSSFWorkbook();
		Sheet sheet = createExportSheet(edList, wb);

		// 3.创建数据字典sheet页
		createDictSheet(edList, wb);

		// 4.设置数据有效性
		setDataValidation(edList, sheet);

		// 5.保存excel到本地
		OutputStream os = new FileOutputStream("d:/4.xls");
		wb.write(os);

		System.out.println("模板生成成功.");
	}
   public static void createDataValidateSubList(Sheet sheet, ExportDefinition ed) {
		int rowIndex = ed.getRowIndex();
		CellRangeAddressList cal;
		DVConstraint constraint;
		CellReference cr;
		DataValidation dataValidation;
		System.out.println(ed);
		for (int i = 0; i < 100; i++) {
			int tempRowIndex = ++rowIndex;
			cal = new CellRangeAddressList(tempRowIndex, tempRowIndex, ed.getCellIndex(), ed.getCellIndex());
			cr = new CellReference(rowIndex, ed.getCellIndex() - 1, true, true);
			constraint = DVConstraint.createFormulaListConstraint("INDIRECT(" + cr.formatAsString() + ")");
			dataValidation = new HSSFDataValidation(cal, constraint);
			dataValidation.setSuppressDropDownArrow(false);
			dataValidation.createPromptBox("操作提示", "请选择下拉选中的值");
			dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入");
			sheet.addValidationData(dataValidation);
		}
	}

	/**
	 * @param edList
	 * @param sheet
	 */
	private static void setDataValidation(List<ExportDefinition> edList, Sheet sheet) {
		for (ExportDefinition ed : edList) {
			if (ed.isValidate()) {// 说明是下拉选
				DVConstraint constraint = DVConstraint.createFormulaListConstraint(ed.getField());
				if (null == ed.getRefName()) {// 说明是一级下拉选
					createDataValidate(sheet, ed, constraint);
				} else {// 说明是二级下拉选
					createDataValidateSubList(sheet, ed);
				}
			}
		}
	}

	/**
	 * @param sheet
	 * @param ed
	 * @param constraint
	 */
	private static void createDataValidate(Sheet sheet, ExportDefinition ed, DVConstraint constraint) {
		CellRangeAddressList regions = new CellRangeAddressList(ed.getRowIndex() + 1, ed.getRowIndex() + 100, ed.getCellIndex(), ed.getCellIndex());
		DataValidation dataValidation = new HSSFDataValidation(regions, constraint);
		dataValidation.setSuppressDropDownArrow(false);
		// 设置提示信息
		dataValidation.createPromptBox("操作提示", "请选择下拉选中的值");
		// 设置输入错误信息
		dataValidation.createErrorBox("错误提示", "请从下拉选中选择,不要随便输入");
		sheet.addValidationData(dataValidation);
	}

	/**
	 * @param edList
	 * @param wb
	 */
	private static void createDictSheet(List<ExportDefinition> edList, Workbook wb) {
		Sheet sheet = wb.createSheet(DICT_SHEET);
		RowCellIndex rci = new RowCellIndex(0, 0);
		for (ExportDefinition ed : edList) {
			String mainDict = ed.getMainDict();
			if (null != mainDict && null == ed.getRefName()) {// 是第一个下拉选
				List<String> mainDictList = (List<String>) DictData.getDict(mainDict);
				String refersToFormula = createDictAndReturnRefFormula(sheet, rci, mainDictList);
				// 创建 命名管理
				createName(wb, ed.getField(), refersToFormula);
				ed.setValidate(true);
			}
			if (null != mainDict && null != ed.getSubDict() && null != ed.getSubField()) {// 联动时加载ed.getSubField()的数据
				ExportDefinition subEd = fiterByField(edList, ed.getSubField());// 获取需要级联的那个字段
				if (null == subEd) {
					continue;
				}
				subEd.setRefName(ed.getPoint());// 保存主下拉选的位置
				subEd.setValidate(true);
				Map<String, List<String>> subDictListMap = (Map<String, List<String>>) DictData.getDict(ed.getSubDict());
				for (Entry<String, List<String>> entry : subDictListMap.entrySet()) {
					String refersToFormula = createDictAndReturnRefFormula(sheet, rci, entry.getValue());
					// 创建 命名管理
					createName(wb, entry.getKey(), refersToFormula);
				}
			}
		}
	}

	/**
	 * @param sheet
	 * @param rci
	 * @param mainDict
	 * @return
	 */
	private static String createDictAndReturnRefFormula(Sheet sheet, RowCellIndex rci, List<String> datas) {
		Row row = sheet.createRow(rci.incrementRowIndexAndGet());
		rci.setCellIndex(0);
		int startRow = rci.getRowIndex();
		int startCell = rci.getCellIndex();
		for (String dict : datas) {
			row.createCell(rci.incrementCellIndexAndGet()).setCellValue(dict);
		}
		int endRow = rci.getRowIndex();
		int endCell = rci.getCellIndex();
		String startName = new CellReference(DICT_SHEET, startRow, startCell, true, true).formatAsString();
		String endName = new CellReference(endRow, endCell, true, true).formatAsString();
		String refersToFormula = startName + ":" + endName;
		System.out.println(refersToFormula);
		return refersToFormula;
	}

	/**
	 * @param wb
	 * @param nameName
	 *            表示命名管理的名字
	 * @param refersToFormula
	 */
	private static void createName(Workbook wb, String nameName, String refersToFormula) {
		Name name = wb.createName();
		name.setNameName(nameName);
		name.setRefersToFormula(refersToFormula);
	}

	private static ExportDefinition fiterByField(List<ExportDefinition> edList, String field) {
		for (ExportDefinition ed : edList) {
			if (Objects.equals(ed.getField(), field)) {
				return ed;
			}
		}
		return null;
	}

	/**
	 * @param edList
	 * @param wb
	 */
	private static Sheet createExportSheet(List<ExportDefinition> edList, Workbook wb) {
		Sheet sheet = wb.createSheet("导出模板");
		RowCellIndex rci = new RowCellIndex(0, 0);
		Row row = sheet.createRow(rci.getRowIndex());
		CellReference cr = null;
		for (ExportDefinition ed : edList) {
			row.createCell(rci.incrementCellIndexAndGet()).setCellValue(ed.getTitle());
			ed.setRowIndex(rci.getRowIndex());
			ed.setCellIndex(rci.getCellIndex());
			cr = new CellReference(ed.getRowIndex() + 1, ed.getCellIndex(), true, true);
			ed.setPoint(cr.formatAsString());
		}
		return sheet;
	}

}

 

 

 



 
 

  • 大小: 11.1 KB
  • 大小: 9.5 KB
  • 大小: 7.7 KB
  • 大小: 25.5 KB
0
0
分享到:
评论

相关推荐

    poi导出excel生成下拉列表

    poi作为导出excel常用的工具,方便快捷。对于excel指定下拉列表的列,如何生成呢?本文提供如何生成下拉列表的excel列

    poi动态生成导入模板,动态下拉菜单

    本话题聚焦于使用POI来动态生成带有下拉菜单的Excel导入模板,这在数据处理、报告生成和自动化流程中具有广泛应用。 首先,让我们深入了解Apache POI库。它提供了HSSF(Horrible Spreadsheet Format)和XSSF(XML ...

    poi导出下拉列表

    本主题将深入探讨如何使用Apache POI来创建具有下拉列表功能的Excel文件,以及如何实现数据有效性约束。 首先,我们需要理解什么是数据有效性约束。在Excel中,数据有效性是一种功能,允许用户对单元格输入的数据...

    POI 下拉列POI 下拉列表.rar

    在这些资源中,你可能会找到如何实现上述步骤的详细代码示例,帮助你更好地理解和应用Apache POI创建Excel下拉列表的功能。 总的来说,Apache POI提供了一个强大而灵活的工具,使得在Java应用程序中生成具有下拉...

    poi 生成excel模板,下拉选项,批注。现在有模板中插入下拉信息

    Apache POI 是一个开源库,...通过结合这些类,你可以实现从服务器端动态生成带下拉选项和批注的 Excel 模板,供用户下载。这在数据报告、数据分析或者用户填写信息时非常有用,因为它提供了一种直观且易于操作的界面。

    java实现poi模板生成PPT文件代码

    在这个项目中,我们将会探讨如何使用POI API来生成PPT文件,特别是通过模板的方式。以下是详细的步骤和知识点。 1. **Apache POI介绍**: Apache POI 是一个开源项目,它提供了Java API来处理Microsoft Office格式...

    java poi设置生成的word的图片为上下型环绕以及其位置的实现

    【Java POI 设置 Word 图片为上下型环绕及位置实现详解】 在使用 Java POI 库生成 Word 文档时,有时我们需要对插入的图片进行格式调整,比如设置为上下型环绕,使其在文本中占据独立空间,同时可以调整图片的位置...

    android中poi生成word文档和excel文档

    在标题“android中poi生成word文档和excel文档”中提到的使用POI库生成Word和Excel文档,主要涉及到以下几个关键知识点: 1. **Apache POI 概述**:Apache POI 是一个开源项目,提供了一套API,用于读写Microsoft ...

    java的poi生成excel图表demo

    在本示例中,我们将深入探讨如何利用POI库来生成Excel中的图表曲线,这对于数据可视化和报告生成非常有用。 1. **Apache POI介绍** Apache POI是一个开源项目,提供了API来处理Microsoft Office格式的文件。在Java...

    poi XWPFDocument 生成目录

    对目录样式,布局,标题,位置的修改,目录对应的页码只能手动设置,无法自动获取,详情:https://blog.csdn.net/qq1223739055/article/details/101440864

    poi 生成pdf等

    "poi 生成pdf等" 这个标题指的是使用Apache POI库来创建PDF和其他格式的文档。Apache POI是一个流行的开源Java API,主要用于读取和写入Microsoft Office格式的文件,如Word(.doc, .docx)、Excel(.xls, .xlsx)等...

    生成下拉列表excel模板.rar

    Java作为广泛使用的后端编程语言,通过Apache POI库可以方便地操作Excel文档,实现从数据库中查询数据并填充到下拉列表中。Apache POI是一个开源项目,提供了API来读取、创建和修改Microsoft Office格式的文件,包括...

    POI实现word和excel在线预览

    本项目提供的"POI实现word和excel在线预览"是基于Apache POI的一个实用工具集,它能够帮助开发者实现在Web环境下对这些文件的在线预览功能,无需用户下载文件到本地即可查看内容,提高了用户体验和数据安全性。...

    poi实现生成excel,文件导出(备份)

    本项目采用SpringBoot、MyBatis和Apache POI框架,实现了从MySQL数据库读取数据并生成Excel文件,供用户下载备份的功能。下面将详细解释这些技术及其在该项目中的应用。 首先,SpringBoot是一个基于Spring框架的轻...

    SpringMVC POI Excel 生成导出

    "SpringMVC POI Excel 生成导出" SpringMVC 是一个基于 Java 的 Web 框架,POI 是一个 Java 库,用于操作 Microsoft Office 文件格式,Excel 是一个电子表格软件。今天,我们将在 SpringMVC 中使用 POI 生成 Excel ...

    poi操作ppt生成图表完整工程.zip

    在本“poi操作ppt生成图表完整工程”中,我们将会深入探讨如何使用Apache POI库来创建和编辑PowerPoint文档中的图表。 首先,我们需要了解Apache POI提供的API。`XSLFSlideShow`是用于创建和修改PowerPoint幻灯片的...

    POI生成word文档

    POI库提供了丰富的API,使得开发者能够轻松地创建、修改和读取Word文档,从而实现自动化报告、文档生成等需求。 首先,我们需要理解如何在Java中设置开发环境。下载Apache POI库的最新版本,将对应的JAR包(通常...

    poi生成报表,简单的poi实例

    在提供的压缩包文件“poi生产excel”中,可能包含了上述代码的实现,以及运行所需的最新 POI 包。确保在你的项目中引入相应的依赖,如 Maven 或 Gradle,以避免运行时错误。 对于初学者,理解 POI 的基本用法是至关...

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

    Java 使用POI生成带联动下拉框的excel表格实例代码 Java 是一种广泛使用的编程语言,而 POI(Poor Obfuscation Implementation)则是一个流行的 Java 库,用于读写 Microsoft Office 文件格式,包括 Excel、Word ...

Global site tag (gtag.js) - Google Analytics