Excel导出级联下拉功能实现-Java专区论坛-技术-SpringForAll社区

Excel导出级联下拉功能实现

 

效果如下:

bf1995f6e5354066b3c608efc70768e6

直接上代码,自己看

工具类:

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.hj.chain.platform.vo.check.CheckFactorInfoVo;
import org.hj.chain.platform.vo.check.CheckFactorSubsetVo;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;


@Slf4j
public class PoiUtil<T> {
    private static final String MAIN_SHEET = "信息";
    private static final String SHEET_MAP = "仪器";


    /**
     * 计算formula
     *
     * @param offset   偏移量,如果给0,表示从A列开始,1,就是从B列
     * @param rowId    第几行
     * @param colCount 一共多少列
     * @return 如果给入参 1,1,10. 表示从B1-K1。最终返回 $B$1:$K$1
     */
    private static String getRange(int offset, int rowId, int colCount) {
        char start = (char) ('A' + offset);
        if (colCount <= 25) {
            char end = (char) (start + colCount - 1);
            return "$" + start + "$" + rowId + ":$" + end + "$" + rowId;
        } else {
            char endPrefix = 'A';
            char endSuffix = 'A';
            if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之间,包括边界(仅两次字母表计算)
                if ((colCount - 25) % 26 == 0) {// 边界值
                    endSuffix = (char) ('A' + 25);
                } else {
                    endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
                }
            } else {// 51以上
                if ((colCount - 25) % 26 == 0) {
                    endSuffix = (char) ('A' + 25);
                    endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1);
                } else {
                    endSuffix = (char) ('A' + (colCount - 25) % 26 - 1);
                    endPrefix = (char) (endPrefix + (colCount - 25) / 26);
                }
            }
            return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId;
        }
    }

    //-----------------------------------------------------------

    /**
     * 导出三级联动and单个下拉框的excel
     *
     * @param name       文件名称
     * @param headers    表头
     * @param mapOneList 一级所有内容
     * @param map        三级联动对应内容
     * @param list       导出数据
     */
    public static <T> void export(HttpServletResponse response, String name, List<String> headers, List<String> mapOneList, Map<String, LinkedList<String>> map, List<T> list) {
        // 1.创建Excel
        // 1)创建workbook
        HSSFWorkbook hssfWorkBook = new HSSFWorkbook();
        // 2)创建sheet
        HSSFSheet mainSheet = hssfWorkBook.createSheet(MAIN_SHEET);// 主sheet
        AtomicInteger add = new AtomicInteger();
        //获取行数
        for (int i = 0; i < list.size(); i++) {
            CheckFactorInfoVo checkFactorInfoVo = (CheckFactorInfoVo) list.get(i);
            if ("1".equals(checkFactorInfoVo.getIsFactor())) {
                if (ObjectUtil.isNotEmpty(checkFactorInfoVo.getFactorSubsetVos())) {
                    add.addAndGet(checkFactorInfoVo.getFactorSubsetVos().size());
                } else {
                    add.addAndGet(1);
                }
            } else {
                add.addAndGet(1);
            }
        }
        // 用于展示
        //2 创建表头,供用户输入
        initHeaders(hssfWorkBook, mainSheet, headers);
        //导出数据到主sheet
        setMainSheet(mainSheet, list);
        //三级联动 sheet
        HSSFSheet mapSheet = hssfWorkBook.createSheet(SHEET_MAP);
        // true:隐藏/false:显示
        //仪器关系sheet
        hssfWorkBook.setSheetHidden(hssfWorkBook.getSheetIndex(mapSheet), true);// 设置sheet是否隐藏
        // 3.写入数据
        writeData(hssfWorkBook, mapSheet, mapOneList, map);// 将数据写入隐藏的sheet中并做好关联关系
        // 4.设置数据有效性
        setDataValid(hssfWorkBook, mainSheet, mapOneList, map, add.get());


        response.reset();

        try (OutputStream output = response.getOutputStream()) {
            response.setContentType("application/octet-stream;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + name);
            output.flush();
            hssfWorkBook.write(output);
        } catch (IOException e) {
            log.error("导出失败!");
            e.printStackTrace();
        }
        response.setCharacterEncoding("UTF-8");


    }

    /**
     * 生成主页面表头
     *
     * @param wb
     * @param mainSheet
     * @param headers
     */
    private static void initHeaders(HSSFWorkbook wb, HSSFSheet mainSheet, List<String> headers) {
        //表头样式
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
        //字体样式
        HSSFFont fontStyle = wb.createFont();
        fontStyle.setFontName("微软雅黑");
        fontStyle.setFontHeightInPoints((short) 12);
        fontStyle.setBold(true);
        style.setFont(fontStyle);
        //生成主内容
        HSSFRow rowFirst = mainSheet.createRow(0);//第一个sheet的第一行为标题
        mainSheet.createFreezePane(0, 1, 0, 1); //冻结第一行

        CellRangeAddress region1 = new CellRangeAddress(0, 0, 5, 6);
        CellRangeAddress region2 = new CellRangeAddress(0, 0, 9, 11);
        mainSheet.addMergedRegion(region1);
        mainSheet.addMergedRegion(region2);

        //写标题
        for (int i = 0; i < headers.size(); i++) {
            HSSFCell cell;
            if (i < 6) {
                cell = rowFirst.createCell(i); //获取第一行的每个单元格
            } else if (i >= headers.size() - 3) {
                cell = rowFirst.createCell(i + 3);
            } else {
                cell = rowFirst.createCell(i + 1);
            }

            mainSheet.setColumnWidth(i, 4000); //设置每列的列宽
            if (i == 3) {
                mainSheet.setColumnWidth(i, 6000);
            }
            cell.setCellStyle(style); //加样式
            cell.setCellValue(headers.get(i)); //往单元格里写数据
        }
    }

    private static <T> void setMainSheet(HSSFSheet mainSheet, List<T> list) {

        HSSFCellStyle style = mainSheet.getWorkbook().createCellStyle();
        style.setVerticalAlignment(VerticalAlignment.CENTER); // 创建一个居中格式
        HSSFFont font = mainSheet.getWorkbook().createFont();
        font.setFontName("宋体");
        style.setFont(font);

        //同系套餐因子占用的总行数
        AtomicInteger add = new AtomicInteger();
        for (int j = 0; j < list.size(); j++) {
            //行
            Row row = mainSheet.createRow(j + 1 + add.get());
            CheckFactorInfoVo obj = (CheckFactorInfoVo) list.get(j);

            if (obj != null) {
                //因子数据填充
                if (!"1".equals(obj.getIsFactor())) {
                    for (int i = 0; i <= 13; i++) {
                        Cell cell = row.createCell(i);
                        cell.setCellStyle(style);
                        switch (i) {
                            case 0:
                                cell.setCellValue(obj.getSampleNo());
                                break;
                            case 1:
                            case 5:
                                cell.setCellValue(obj.getFactorName());
                                break;
                            case 2:
                                cell.setCellValue(obj.getStandardNo());
                                break;
                            case 3:
                                cell.setCellValue(obj.getStandardName());
                                break;
                            case 4:
                                cell.setCellValue(obj.getFactorRemark());
                                break;
                            case 6:
                                if (ObjectUtil.isNotNull(obj.getCheckRes())) {
                                    JSONObject jsonObject = JSONObject.parseObject(obj.getCheckRes());
                                    String v1 = jsonObject.getString("v1");
                                    String v2 = jsonObject.getString("v2");
                                    if (ObjectUtil.isNull(v2)|| "".equals(v2)) {
                                        cell.setCellValue(v1);
                                    } else {
                                        String initial = getInitial(v1, v2);
                                        cell.setCellValue(initial);
                                    }
                                }
                                break;
                            case 7:
                                cell.setCellValue(obj.getUnitName());
                                break;
                            case 8:
                                if (ObjectUtil.isNotNull(obj.getRemark())) {
                                    cell.setCellValue(obj.getRemark());
                                }
                                break;
                            case 9:
                                if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {
                                    JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());
                                    cell.setCellValue(jsonObject.getString("equipmentName"));
                                }
                                break;
                            case 10:
                                if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {
                                    JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());
                                    cell.setCellValue(jsonObject.getString("equipmentModel"));
                                }
                                break;
                            case 11:
                                if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {
                                    JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());
                                    cell.setCellValue(jsonObject.getString("equipmentNumber"));
                                }
                                break;
                            case 12:
                                cell.setCellValue(obj.getCheckFactorId());
                                break;
                            case 13:
                                cell.setCellValue("1".equals(obj.getIsFactor()) ? "是" : "否");
                                break;
                        }

                    }
                } else {

                    //套餐内容填充
                    for (int i = 0; i < 5; i++) {
                        Cell cell = row.createCell(i);
                        cell.setCellStyle(style);
                        switch (i) {
                            case 0:
                                cell.setCellValue(obj.getSampleNo());
                                break;
                            case 1:
                                cell.setCellValue(obj.getFactorName());
                                break;
                            case 2:
                                cell.setCellValue(obj.getStandardNo());
                                break;
                            case 3:
                                cell.setCellValue(obj.getStandardName());
                                break;
                            case 4:
                                cell.setCellValue(obj.getFactorRemark());
                                break;
                        }
                    }

                    List<CheckFactorSubsetVo> factorSubsetVos = obj.getFactorSubsetVos();
                    row.createCell(12).setCellValue(obj.getCheckFactorId());

                    //套餐因子填充
                    if (ObjectUtil.isNotEmpty(factorSubsetVos)) {
                        for (int i = 0; i < factorSubsetVos.size(); i++) {
                            if (i != 0) {
                                row = mainSheet.createRow(j + 1 + add.get() + i);
                            }
                            //填充因子名称
                            Cell cell5 = row.createCell(5);
                            cell5.setCellValue(factorSubsetVos.get(i).getFactorName());
                            cell5.setCellStyle(style);

                            Cell cell7 = row.createCell(7);
                            cell7.setCellValue(factorSubsetVos.get(i).getUnitName());
                            cell7.setCellStyle(style);

                            Cell cell12 = row.createCell(12);
                            cell12.setCellValue(obj.getCheckFactorId());
                            cell12.setCellStyle(style);

                            Cell cell13 = row.createCell(13);
                            cell13.setCellValue("1".equals(obj.getIsFactor()) ? "是" : "否");
                            cell13.setCellStyle(style);

                            Cell cell14 = row.createCell(14);
                            cell14.setCellValue(factorSubsetVos.get(i).getId());
                            cell14.setCellStyle(style);

                            if (ObjectUtil.isNotNull(factorSubsetVos.get(i).getCheckSubRes())) {
                                JSONObject jsonObject = JSONObject.parseObject(factorSubsetVos.get(i).getCheckSubRes());
                                String v1 = jsonObject.getString("v1");
                                String v2 = jsonObject.getString("v2");
                                Cell cell6 = row.createCell(6);
                                if (ObjectUtil.isNull(v2)|| "".equals(v2)) {
                                    cell6.setCellValue(v1);
                                } else {
                                    String initial = getInitial(v1, v2);
                                    cell6.setCellValue(initial);
                                }
                                cell6.setCellStyle(style);
                            }

                            if (ObjectUtil.isNotNull(obj.getRemark())) {
                                Cell cell8 = row.createCell(8);
                                cell8.setCellStyle(style);
                                cell8.setCellValue(obj.getRemark());
                            }

                            if (ObjectUtil.isNotNull(obj.getCheckEquipment())) {
                                JSONObject jsonObject = JSONObject.parseObject(obj.getCheckEquipment());

                                Cell cell9 = row.createCell(9);
                                cell9.setCellStyle(style);
                                cell9.setCellValue(jsonObject.getString("equipmentName"));

                                Cell cell10 = row.createCell(10);
                                cell10.setCellStyle(style);
                                cell10.setCellValue(jsonObject.getString("equipmentModel"));

                                Cell cell11 = row.createCell(11);
                                cell11.setCellStyle(style);
                                cell11.setCellValue(jsonObject.getString("equipmentNumber"));
                            }
                        }

                    }

                    //累加套餐因子所占行数
                    int oldAdd = add.getAndAdd(factorSubsetVos.size() - 1);

                    // 四个参数分别是:起始行、终止行、起始列、终止列.
                    CellRangeAddress region1 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 0, 0);
                    CellRangeAddress region2 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 1, 1);
                    CellRangeAddress region3 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 2, 2);
                    CellRangeAddress region4 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 3, 3);
                    CellRangeAddress region5 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 4, 4);
                    CellRangeAddress region6 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 8, 8);
                    CellRangeAddress region7 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 9, 9);
                    CellRangeAddress region8 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 10, 10);
                    CellRangeAddress region9 = new CellRangeAddress(j + oldAdd + 1, j + add.get() + 1, 11, 11);
                    mainSheet.addMergedRegion(region1);
                    mainSheet.addMergedRegion(region2);
                    mainSheet.addMergedRegion(region3);
                    mainSheet.addMergedRegion(region4);
                    mainSheet.addMergedRegion(region5);
                    mainSheet.addMergedRegion(region6);
                    mainSheet.addMergedRegion(region7);
                    mainSheet.addMergedRegion(region8);
                    mainSheet.addMergedRegion(region9);
                }

            }
            mainSheet.setColumnHidden(12, true);
            mainSheet.setColumnHidden(13, true);
            mainSheet.setColumnHidden(14, true);
        }
    }


    private static void setDataValid(HSSFWorkbook HSSFWorkBook, HSSFSheet mainSheet, List<String> firstList, Map<String, LinkedList<String>> siteMap, Integer line) {
        //设置一级下拉
        HSSFDataValidationHelper dvHelper = new HSSFDataValidationHelper((HSSFSheet) mainSheet);
        String[] dataArray = firstList.toArray(new String[0]);
        HSSFSheet hidden = HSSFWorkBook.createSheet("hidden");
        HSSFCell cell = null;
        for (int i = 0, length = dataArray.length; i < length; i++) {
            String name = dataArray[i];
            HSSFRow row = hidden.createRow(i);
            cell = row.createCell(0);
            cell.setCellValue(name);
        }

        Name namedCell = HSSFWorkBook.createName();
        namedCell.setNameName("hidden");
        namedCell.setRefersToFormula("hidden!$A$1:$A$" + dataArray.length);
        //加载数据,将名称为hidden的
        DVConstraint constraint = DVConstraint.createFormulaListConstraint("hidden");
        // 四个参数分别是:起始行、终止行、起始列、终止列.
        // 1 (一级下拉框代表从excel第1+1行开始) line(一级下拉框代表从excel第1+10行结束) 9(代表第几列开始,0是第一列,1是第二列) 1(代表第几列结束,0是第一列,1是第二列)
        CellRangeAddressList firstRangeAddressList = new CellRangeAddressList(1, line, 9, 9);
        DataValidation firstDataValidation = dvHelper.createValidation(constraint, firstRangeAddressList);
        firstDataValidation.createErrorBox("error", "请选择正确");
        firstDataValidation.setShowErrorBox(true);
        // firstDataValidation.setSuppressDropDownArrow(true);
        //将第二个sheet设置为隐藏
        // true:隐藏/false:显示
        HSSFWorkBook.setSheetHidden(HSSFWorkBook.getSheetIndex(hidden), true);// 设置sheet是否隐藏
//        HSSFWorkBook.setSheetHidden(1, true);
        mainSheet.addValidationData(firstDataValidation);

        // 设置第二级、第三级下拉
        // i <= 10 ,10代表第二级、第三级下拉框到10+1行结束
        for (int i = 0; i <= 10; i++) {
            setDataValidation('J', mainSheet, i + 1, 10);// "J"是指父类所在的列,i+1初始值为1代表从第2行开始,10要与“J”对应,为J的列号加1,假如第一个参数为“C”,那么最后一个参数就3
        }

    }

    /**
     * 设置有效性
     *
     * @param offset 主影响单元格所在列,即此单元格由哪个单元格影响联动
     * @param sheet
     * @param rowNum 行数
     * @param colNum 列数
     */
    private static void setDataValidation(char offset, HSSFSheet sheet, int rowNum, int colNum) {
        HSSFDataValidationHelper dvHelper = new HSSFDataValidationHelper(sheet);
        DataValidation dataValidationList1;
        DataValidation dataValidationList2;
        dataValidationList1 = getDataValidationByFormula("INDIRECT($" + offset + (rowNum) + ")", rowNum, colNum, dvHelper);
        dataValidationList2 = getDataValidationByFormula("INDIRECT($" + (char) (offset + 1) + (rowNum) + ")", rowNum, colNum + 1, dvHelper);
        sheet.addValidationData(dataValidationList1);
        sheet.addValidationData(dataValidationList2);
    }


    private static DataValidation getDataValidationByFormula(String formulaString, int naturalRowIndex, int naturalColumnIndex, HSSFDataValidationHelper dvHelper) {
        DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint(formulaString);
        CellRangeAddressList regions = new CellRangeAddressList(naturalRowIndex, 65535, naturalColumnIndex, naturalColumnIndex);
        HSSFDataValidation data_validation_list = (HSSFDataValidation) dvHelper.createValidation(dvConstraint, regions);
        data_validation_list.setEmptyCellAllowed(false);
        if (data_validation_list instanceof HSSFDataValidation) {
            // data_validation_list.setSuppressDropDownArrow(true);
            data_validation_list.setShowErrorBox(true);
        } else {
            // data_validation_list.setSuppressDropDownArrow(false);
        }
        // 设置输入信息提示信息
        data_validation_list.createPromptBox("下拉选择提示", "请使用下拉方式选择合适的值!");
        return data_validation_list;
    }


    private static void writeData(HSSFWorkbook hssfWorkBook, HSSFSheet mapSheet, List<String> firstList, Map<String, LinkedList<String>> subMap) {

        //循环将父数据写入siteSheet的第1行中
        int siteRowId = 0;
        HSSFRow firstRow = mapSheet.createRow(siteRowId++);
        firstRow.createCell(0).setCellValue("父列表");
        for (int i = 0; i < firstList.size(); i++) {
            firstRow.createCell(i + 1).setCellValue(firstList.get(i));
        }
        // 将具体的数据写入到每一行中,行开头为父级区域,后面是子区域。
        Iterator<String> keyIterator = subMap.keySet().iterator();
        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            List<String> son = subMap.get(key);
            HSSFRow siteRow = mapSheet.createRow(siteRowId++);
            siteRow.createCell(0).setCellValue(key);
            for (int i = 0; i < son.size(); i++) {
                siteRow.createCell(i + 1).setCellValue(son.get(i));
            }

            // 添加名称管理器
            String range = getRange(1, siteRowId, son.size());
            Name name = hssfWorkBook.createName();
            name.setNameName(key);
            String formula = mapSheet.getSheetName() + "!" + range;
            name.setRefersToFormula(formula);
        }
    }

    private static String getInitial(String a, String b) {

        if (ObjectUtil.isNull(b)|| "".equals(b)) {
            return a;
        } else {
            StringBuffer sb = new StringBuffer();
            return sb.append(a).append("*").append("10^").append(b).toString();
        }

    }

}

使用方法:
根据自身业务进行组装数据

public void export(HttpServletResponse response, CheckFactorSearchVo searchVo) {
	    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
	    String dateString = format.format(new Date());
	    //文件名称
	    String name = dateString+".xls";
	    //excel 表头
	    List<String> headers = Arrays.asList("样品编号","检测因子","标准号", "检测标准", "备注信息", "检测结果","单位","备注","检测设备","检测因子id","因子套餐","套餐因子id");
        JSONArray tree = (JSONArray)equipmentInfoService.laboratoryEquipmentTree().getResult();

        LinkedList<String> firstList = new LinkedList<>();
        HashMap<String, LinkedList<String>> subMap = new HashMap();

        tree.forEach( object->{
             String firstName = ((JSONObject) object).getString("name");
             firstList.add(firstName);
             JSONArray children = ((JSONObject) object).getJSONArray("children");
             LinkedList<String> subList = new LinkedList<>();
             children.forEach( subObject ->{
                 String secondName = ((JSONObject) subObject).getString("name");
                 LinkedList<String> thirdList = new LinkedList<>();
                 subList.add(secondName);

                 JSONArray secondChildren = ((JSONObject) subObject).getJSONArray("children");
                 secondChildren.forEach( thirdObject->{
                      String thirdName = ((EquipmentTreeVo)thirdObject).getEquipmentNumber();
                      thirdList.add(thirdName);
                 });
                 subMap.put(secondName,thirdList);
             });
             subMap.put(firstName,subList);
        });
		PoiUtil.export(response,name,headers,firstList,subMap,factorInfoVos);
    }

导出内容如下:

d7fe75f850764aa5adb98f067dd4710c

有两个隐藏的表格用来实现级联下拉

image

 

image

image

 

 

请登录后发表评论