Excel设置单元格下拉框(poi)

前言

        年关在即,还在最后的迭代处理,还分了个其他同事的单,说是导出的Excel模版的2列要修改为下拉选项,过程很曲折,不说,以下其实就是一个笔记而已!
        其实之前分享过阿里的EasyExcel设置单元格下拉框,这里是poi原生设置。


一、场景描述

        其实就是下载一个Excel文件,作为导入的模版,然后有一行示例,2列是字典值,希望给用户的输入做个示例。

二、使用步骤

1.引入库

        主要就是引入poi相关包

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.0</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.0</version>
</dependency>

2.工具类

        这里分享工具类的部分方法,免得看的眼花缭乱。
ExcelTools

/*** 导出带下拉框的Excel** @param outStream   输出流* @param keyValueMap 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性* @param list        数据集合* @param fileType    文件类型* @param title       表头* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值* @param <T>         泛型* @throws Exception 异常* @auther zhengwen*/public static <T> void exportDropDownExcel(OutputStream outStream, Map<String, String> keyValueMap, List<T> list,String fileType, String title, Map<Integer, List<String>> dropDownMap) throws Exception {Workbook wb = createWorkbook(fileType);exportExcel(wb, outStream, keyValueMap, list, fileType, title, dropDownMap);}/*** 根据文件后缀创建对应的 Workbook* @param fileType 文件后缀:xls,xlsx* @return Workbook*/private static Workbook createWorkbook(String fileType){return ExcelConstant.XLS.equals(fileType) ? new HSSFWorkbook() : new XSSFWorkbook();}/*** 创建带下拉选项的Workbook** @param wb          Workbook* @param outStream   输出流* @param keyValueMap 表头和属性的Map集合,其中Map中Key为Excel列的名称,Value为反射类的属性* @param list        数据集合* @param fileType    文件类型* @param title       表头* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值* @param <T>         泛型* @throws Exception 异常* @auther zhengwen*/private static <T> void exportExcel(Workbook wb, OutputStream outStream, Map<String, String> keyValueMap, List<T> list, String fileType, String title, Map<Integer, List<String>> dropDownMap) throws Exception {List<String> keyList = new ArrayList<>(keyValueMap.keySet());// 存储属性信息Map<String, String> attMap = new HashMap<>(CommonConstant.MAP_DEFAULT_INITIAL_CAPACITY);int index = CommonConstant.ZERO;if (ExcelConstant.XLS.equals(fileType)) {// 创建HSSFWorkbook对象(excel的文档对象)CellStyle cellStyle = wb.createCellStyle();cellStyle.setWrapText(true);cellStyle.setAlignment(HorizontalAlignment.CENTER);cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);int lastCol = keyValueMap.size() - 1;CellRangeAddress callRangeAddress = new CellRangeAddress(0, 0, 0, lastCol);// 建立新的sheet对象(excel的表单)HSSFSheet sheet = (HSSFSheet) wb.createSheet(ExcelConstant.SHEET_NAME);// 设置表格默认列宽度为15个字节sheet.setDefaultColumnWidth(20);sheet.addMergedRegion(callRangeAddress);// 声明样式HSSFCellStyle style = (HSSFCellStyle) wb.createCellStyle();hssfCellStyleForXls(wb, style);//表格标题HSSFRow rowTitle = sheet.createRow(CommonConstant.ZERO);HSSFCell titleCell = rowTitle.createCell(0);rowTitle.setHeight((short) 600);//加载单元格样式CellStyle erStyle = createCellStyle(wb, (short) 13, true, true);titleCell.setCellStyle(erStyle);titleCell.setCellValue(title);//标题换行设置erStyle.setWrapText(true);titleCell.setCellValue(new HSSFRichTextString(title));// 在sheet里创建第二行为表头,参数为行索引(excel的行),可以是0~65535之间的任何一个HSSFRow rowHeader = sheet.createRow(CommonConstant.ONE);DataFormat dataFormat = wb.createDataFormat();for (String key : keyList) {HSSFCell cell = rowHeader.createCell(index);style.setWrapText(true);//设置为文本,防止科学计数style.setDataFormat(dataFormat.getFormat("@"));cell.setCellStyle(style);cell.setCellValue(key);attMap.put(Integer.toString(index), keyValueMap.get(key));index++;}// 在sheet里创建表头下的数据for (int i = CommonConstant.ZERO; i < list.size(); i++) {int rowNum = i + CommonConstant.TWO;HSSFRow row = sheet.createRow(rowNum);for (int j = CommonConstant.ZERO; j < keyValueMap.size(); j++) {String key = Integer.toString(j);String att = attMap.get(key);T t = list.get(i);Object value = getAttrVal(t, att);cellStyle.setWrapText(true);Cell cell = row.createCell(j);cell.setCellStyle(cellStyle);if (dropDownMap.containsKey(j)) {setCellDropDownBox(cell, dropDownMap.get(j), sheet, rowNum, rowNum, j, j);} else {cell.setCellValue(getObject(value));}}}} else if (ExcelConstant.XLSX.equals(fileType)) {int lastCol = keyValueMap.size() - 1;CellRangeAddress callRangeAddress = new CellRangeAddress(0, 0, 0, lastCol);// 建立新的sheet对象(excel的表单)XSSFSheet sheet = (XSSFSheet) wb.createSheet(ExcelConstant.SHEET_NAME);// 设置表格默认列宽度为15个字节sheet.setDefaultColumnWidth(20);sheet.addMergedRegion(callRangeAddress);// 声明样式XSSFCellStyle style = (XSSFCellStyle) wb.createCellStyle();xssfCellStyleFor2007(wb, style);//标题XSSFRow rowTitle = sheet.createRow(CommonConstant.ZERO);rowTitle.setHeight((short) 600);//表格标题XSSFCell titleCell = rowTitle.createCell(0);//加载单元格样式CellStyle erStyle = createCellStyle(wb, (short) 13, true, true);titleCell.setCellStyle(erStyle);titleCell.setCellValue(title);//标题换行设置erStyle.setWrapText(true);titleCell.setCellValue(new XSSFRichTextString(title));// 在sheet里创建第一行为表头,参数为行索引(excel的行),可以是0~65535之间的任何一个XSSFRow rowHeader = sheet.createRow(CommonConstant.ONE);// 创建单元格并设置单元格内容for (String key : keyList) {XSSFCell cell = rowHeader.createCell(index);style.setWrapText(true);cell.setCellStyle(style);cell.setCellValue(key);attMap.put(Integer.toString(index), keyValueMap.get(key));index++;}// 在sheet里创建表头下的数据for (int i = CommonConstant.ZERO; i < list.size(); i++) {int rowNum = i + CommonConstant.TWO;XSSFRow row = sheet.createRow(rowNum);for (int j = CommonConstant.ZERO; j < keyValueMap.size(); j++) {String key = Integer.toString(j);T t = list.get(i);Object value = getAttrVal(t, attMap.get(key));CellStyle cellStyle = wb.createCellStyle();cellStyle.setWrapText(true);cellStyle.setAlignment(HorizontalAlignment.CENTER);cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 下边框cellStyle.setBorderBottom(BorderStyle.THIN);// 左边框cellStyle.setBorderLeft(BorderStyle.THIN);// 上边框cellStyle.setBorderTop(BorderStyle.THIN);// 右边框cellStyle.setBorderRight(BorderStyle.THIN);Font cellfont = wb.createFont();cellfont.setFontHeightInPoints((short) 12);cellfont.setFontName("宋体");cellStyle.setFont(cellfont);//row.createCell(j).setCellValue(getObject(value));//row.createCell(j).setCellStyle(cellStyle);//以上2行写的害人的,会导致单元格格式丢失DataFormat format = wb.createDataFormat();cellStyle.setDataFormat(format.getFormat("@"));//sheet.setDefaultColumnStyle(j, cellStyle);Cell cell = row.createCell(j);cell.setCellStyle(cellStyle);if (dropDownMap.containsKey(j)) {setCellDropDownBox(cell, dropDownMap.get(j), sheet, rowNum, rowNum, j, j);} else {cell.setCellValue(getObject(value));}}}}if (null != wb) {wb.write(outStream);}}/*** 设置cell单元格的下拉框** @param cell        单元格* @param dropDownMap 下拉框Map集合,其中Map中Key为Excel列的序号,Value为下拉框的值* @param sheet       sheet* @param startRow    开始行号* @param endRow      结束行号* @param startCol    开始列号* @param endCol      结束列号* @auther zhengwen*/private static void setCellDropDownBox(Cell cell, List<String> dropDownMap, Sheet sheet, int startRow, int endRow, int startCol, int endCol) {if (cell == null || sheet == null) {throw new DreambaseException("单元格或者sheet为空");}// 生成下拉框内容String[] dropDownArray = dropDownMap.toArray(new String[0]);//设置下拉框CellRangeAddressList regions = new CellRangeAddressList(startRow, endRow, startCol, endCol);if (sheet instanceof XSSFSheet){XSSFSheet xssfSheet = (XSSFSheet) sheet;// 生成下拉框DataValidationHelper helper = sheet.getDataValidationHelper();DataValidationConstraint constraint = helper.createExplicitListConstraint(dropDownArray);DataValidation dataValidation = helper.createValidation(constraint, regions);xssfSheet.addValidationData(dataValidation);}if (sheet instanceof HSSFSheet){// 生成下拉框DVConstraint constraint = DVConstraint.createExplicitListConstraint(dropDownArray);// 绑定下拉框和作用区域HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);sheet.addValidationData(dataValidation);}//设置下拉框选中第一个cell.setCellValue(dropDownArray[0]);}

serviceImpl

@Overridepublic void exportExcel(List<StationExcel> excelList, HttpServletRequest request, HttpServletResponse response){try {OutputStream outputStream = OutputStreamUtil.getOutputStream(request, response, StationExcel.FILE_NAME);//下拉框数据Map<Integer,List<String>> dropDownMap = new HashMap<>();//查询站点类型List<Dictionary> stationTypeDictList = dictionaryService.queryDictionaryByCategory(CommonConstant.DICT_STATION_TYPE);if(CollectionUtil.isNotEmpty(stationTypeDictList)){List<String> typeList = new ArrayList<>();stationTypeDictList.forEach((e) -> typeList.add(e.getDesc()));dropDownMap.put(1,typeList);}//查询电压等级List<Dictionary> electricPowerLevelDictList = dictionaryService.queryDictionaryByCategory(CommonConstant.DICT_ELECTRIC_POWER_LEVEL_TYPE);if(CollectionUtil.isNotEmpty(electricPowerLevelDictList)){List<String> electricPowerLevelList = new ArrayList<>();electricPowerLevelDictList.forEach((e) -> electricPowerLevelList.add(e.getDesc()));dropDownMap.put(3,electricPowerLevelList);}ExcelTools.exportDropDownExcel(outputStream, StationExcel.COLUMN_LIST, excelList, ExcelConstant.XLSX, StationExcel.TITLE, dropDownMap);response.flushBuffer();outputStream.close();} catch (IOException e) {log.error("excel导出失败", e);throw new DreambaseException("excel导出失败!IOException异常" + e.getMessage());} catch (Exception e) {log.error("excel导出失败", e);throw new DreambaseException("excel导出失败!" + e.getMessage());}}

总结

        其实没啥好分享的,真的就是个笔记而已,希望可以帮到大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jsp页面,让alert弹出信息换行显示

第一种方式&#xff1a;后端拼接上换行符前端显示 1&#xff0c;java后端将信息封装成字符串时&#xff0c;在需要换行的地方拼接上一个换行符&#xff0c; 显示在HTML中的换行&#xff0c;通常需要用<br>标签替代\n&#xff0c;如下&#xff1a; String javaString &…

【教程】ESP32-CAM使用I2C驱动0.91寸OLED

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 先安装库 1. 打开 Arduino IDE&#xff0c;然后转到 Sketch > Include Library > Manage Libraries。 2. 在搜索框中输入“SSD1306”&#xff0c;然后从 Adafruit 安装 SSD1306 库。 3. 选择“install al…

各种编程语言送祝福:2024龙年大吉

我是码农一枚&#xff0c;在这里用不同编程语言中祝福大家"2024&#xff0c;龙年大吉"~ Python print("2024&#xff0c;龙年大吉")Java public class Main {public static void main(String[] args) {System.out.println("2024&#xff0c;龙年大…

文心一言 VS 讯飞星火 VS chatgpt (195)-- 算法导论14.3 3题

三、用go语言&#xff0c;请给出一个有效的算法&#xff0c;对一个给定的区间i&#xff0c;返回一个与i重叠且具有最小低端点的区间;或者当这样的区间不存在时返回T.nil。 文心一言&#xff0c;去掉math&#xff0c;代码正常运行&#xff1a; 在Go语言中&#xff0c;你可以使…

Opencc4j 开源中文繁简体使用介绍

Opencc4j Opencc4j 支持中文繁简体转换&#xff0c;考虑到词组级别。 Features 特点 严格区分「一简对多繁」和「一简对多异」。 完全兼容异体字&#xff0c;可以实现动态替换。 严格审校一简对多繁词条&#xff0c;原则为「能分则不合」。 词库和函数库完全分离&#xff0c…

【技术预研】StarRocks官方文档浅析(4)

背景说明 基于starRocks官方文档&#xff0c;对其内容进行一定解析&#xff0c;方便大家理解和使用。 若无特殊标注&#xff0c;startRocks版本是3.2。 下面的章节和官方文档保持一致。 参考文档 产品简介 | StarRocks StarRocks StarRocks 是一款高性能分析型数据仓库&…

JenkinsGitLab完成自动化构建部署

关于GitLab安装:GitLab安装-CSDN博客 Docker中安装GitLab:Docker下安装GitLab-CSDN博客 安装JenKins Jenkins官网:Jenkins 中文版:Jenkins 安装时候中文页面的war包下不来 在英文页面 记得装JDK8以上 JenKins使用java写的 运行JenKins需要JDK环境 我这里已经装好了 将下…

python制作恶意软件删除工具

今天&#xff0c;来教大家用python制作一个恶意软件删除工具 查杀流程图 对&#xff0c;就这些&#xff0c;已经具备了杀毒软件的功能 判断文件是否为病毒 要查杀病毒&#xff0c;先要判断文件是不是病毒&#xff08;不然删错了咋办&#xff09;&#xff0c;这里我们用获取文…

【RK3288 Android10 C30 支持sim卡拔掉不弹窗,及热插拔】

文章目录 【RK3288 Android10 C30 支持sim卡拔掉不弹窗&#xff0c;及热插拔】需求方案patchframework 【RK3288 Android10 C30 支持sim卡拔掉不弹窗&#xff0c;及热插拔】 需求 由于3288 硬件上的sim卡座不支持热插拔&#xff0c;是没有顶针来识别sim卡是否被拔掉的。所以在…

云计算市场分析

目录 一、云计算市场概述 1.1 概述 二、国外云计算厂商 2.1 亚马逊AWS 2.2 微软AzureAzure 2.3 Apple iCloud 三、国内云计算厂商 3.1 阿里云 3.2 腾讯云 3.3 华为云 3.4 百度智能云 一、云计算市场概述 1.1 概述 云计算从出现以来&#xff0c;其发展就非常迅速。以…

win10重装Ubuntu22.04安装报错复盘

目录 一&#xff1a;补充启动盘制作 二&#xff1a;错误信息[0xC0030570] The file or directory is corrupted and unreadable. 三&#xff1a;ubuntu重装步骤&#xff1a; 四&#xff1a;磁盘冗余阵列 五&#xff1a;尝试将SCS11(2,0.0), 第1分区(sda)设备的一个vfat文…

大华智慧园区综合管理平台 /ipms/barpay/pay RCE漏洞复现

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

springboot kafka 实现延时队列

好文推荐&#xff1a; 2.5万字详解23种设计模式 基于Netty搭建websocket集群实现服务器消息推送 2.5万字讲解DDD领域驱动设计 文章目录 一、延时队列定义二、应用场景三、技术实现方案&#xff1a;1. Redis2. Kafka3. RabbitMQ4. RocketMQ 四、Kafka延时队列背景五、Kafka延时队…

锐捷VSU和M-LAG介绍

参考网站 堆叠、级联和集群的概念 什么是堆叠&#xff1f; 框式集群典型配置 RG-S6230[RG-S6501-48VS8CQ]系列交换机 RGOS 12.5(4)B1005版本 配置指南 总结 根据以上的几篇文章总结如下&#xff1a; 级联&#xff1a;简单&#xff0c;交换机相连就叫级联&#xff0c;跟搭…

ES6 Proxy详解

文章目录 概述Proxy 实例的方法get(target, propKey, receiver)set(target, propKey, value, receiver)has(target, propKey)deleteProperty(target, propKey)defineProperty(target, propKey, propDesc)getOwnPropertyDescriptor(target, propKey)getPrototypeOf(target)setPr…

鸿蒙 WiFi 打开流程

这里鸿蒙的代码使用的是开源鸿蒙HarmonyOS 4.0的代码基线 这里我们是针对手机平台代码分析&#xff0c;首先界面部分代码都在&#xff1a;applications/standard/settings/product/phone 然后我们只关心WiFi相关的&#xff0c;看界面代码applications/standard/settings/produc…

HCIA--路由优先级实验

要求&#xff1a; 1. pc1访问pc3,4,5走上面&#xff0c;R1-R2实现备份21.1.1.0/24实现备份&#xff1b; 2. pc3,4,5,6访问pc1,2走下面&#xff0c; R3,4之间实现等价路由&#xff0c;尽量减少路由条目&#xff0c;实现全网可达&#xff0c;pc7代表运营商 所有pc均可访问 1…

5.0 ZooKeeper 数据模型 znode 结构详解

数据模型 在 zookeeper 中&#xff0c;可以说 zookeeper 中的所有存储的数据是由 znode 组成的&#xff0c;节点也称为 znode&#xff0c;并以 key/value 形式存储数据。 整体结构类似于 linux 文件系统的模式以树形结构存储。其中根路径以 / 开头。 进入 zookeeper 安装的 …

阅读笔记——《RapidFuzz: Accelerating fuzzing via Generative Adversarial Networks》

【参考文献】Ye A, Wang L, Zhao L, et al. Rapidfuzz: Accelerating fuzzing via generative adversarial networks[J]. Neurocomputing, 2021, 460: 195-204.【注】本文仅为作者个人学习笔记&#xff0c;如有冒犯&#xff0c;请联系作者删除。 目录 摘要 一、介绍 二、相关…

寒假作业-day4

1>请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23}&#xff0c;输入key查找的值&#xff0c;实现查找功能。 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> typedef int datatype; type…