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

前言

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


一、场景描述

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

二、使用步骤

1.引入库

        主要就是引入poi相关包

<dependency>
	<groupId>org.apache.poigroupId>
	<artifactId>poiartifactId>
	<version>4.1.0version>
dependency>
<dependency>
	<groupId>org.apache.poigroupId>
	<artifactId>poi-ooxmlartifactId>
	<version>4.1.0version>
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          泛型
     * @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          泛型
     * @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

@Override
    public 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());
        }
    }

总结

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

你可能感兴趣的:(工具,高效开发分享,excel,设置下拉框,单元格设置下拉框,Excel设置下拉框)