package org.dromara.demo.service.impl; import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.Data; import lombok.RequiredArgsConstructor; import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.excel.core.DropDownOptions; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.demo.domain.vo.ExportDemoVo; import org.dromara.demo.service.IExportExcelService; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 导出下拉框Excel示例 * * @author Emil.Zhang */ @Service @RequiredArgsConstructor public class ExportExcelServiceImpl implements IExportExcelService { @Override public void exportWithOptions(HttpServletResponse response) { // 创建表格数据,业务中一般通过数据库查询 List excelDataList = new ArrayList<>(); for (int i = 0; i < 3; i++) { // 模拟数据库中的一条数据 ExportDemoVo everyRowData = new ExportDemoVo(); everyRowData.setNickName("用户-" + i); everyRowData.setUserStatus(UserStatus.OK.getCode()); everyRowData.setGender("1"); everyRowData.setPhoneNumber(String.format("175%08d", i)); everyRowData.setEmail(String.format("175%08d", i) + "@163.com"); everyRowData.setProvinceId(i); everyRowData.setCityId(i); everyRowData.setAreaId(i); excelDataList.add(everyRowData); } // 通过@ExcelIgnoreUnannotated配合@ExcelProperty合理显示需要的列 // 并通过@DropDown注解指定下拉值,或者通过创建ExcelOptions来指定下拉框 // 使用ExcelOptions时建议指定列index,防止出现下拉列解析不对齐 // 首先从数据库中查询下拉框内的可选项 // 这里模拟查询结果 List provinceList = getProvinceList(), cityList = getCityList(provinceList), areaList = getAreaList(cityList); int provinceIndex = 5, cityIndex = 6, areaIndex = 7; DropDownOptions provinceToCity = DropDownOptions.buildLinkedOptions( provinceList, provinceIndex, cityList, cityIndex, DemoCityData::getId, DemoCityData::getPid, everyOptions -> DropDownOptions.createOptionValue( everyOptions.getName(), everyOptions.getId() ) ); DropDownOptions cityToArea = DropDownOptions.buildLinkedOptions( cityList, cityIndex, areaList, areaIndex, DemoCityData::getId, DemoCityData::getPid, everyOptions -> DropDownOptions.createOptionValue( everyOptions.getName(), everyOptions.getId() ) ); // 把所有的下拉框存储 List options = new ArrayList<>(); options.add(provinceToCity); options.add(cityToArea); // 到此为止所有的下拉框可选项已全部配置完毕 // 接下来需要将Excel中的展示数据转换为对应的下拉选 List outList = StreamUtils.toList(excelDataList, everyRowData -> { // 只需要处理没有使用@ExcelDictFormat注解的下拉框 // 一般来说,可以直接在数据库查询即查询出省市县信息,这里通过模拟操作赋值 everyRowData.setProvince(buildOptions(provinceList, everyRowData.getProvinceId())); everyRowData.setCity(buildOptions(cityList, everyRowData.getCityId())); everyRowData.setArea(buildOptions(areaList, everyRowData.getAreaId())); return everyRowData; }); ExcelUtil.exportExcel(outList, "下拉框示例", ExportDemoVo.class, response, options); } private String buildOptions(List cityDataList, Integer id) { Map> groupByIdMap = cityDataList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); if (groupByIdMap.containsKey(id)) { DemoCityData demoCityData = groupByIdMap.get(id).get(0); return DropDownOptions.createOptionValue(demoCityData.getName(), demoCityData.getId()); } else { return StrUtil.EMPTY; } } /** * 模拟查询数据库操作 * * @return / */ private List getProvinceList() { List provinceList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 provinceList.add(new DemoCityData(0, null, "安徽省")); provinceList.add(new DemoCityData(1, null, "江苏省")); return provinceList; } /** * 模拟查找数据库操作,需要连带查询出省的数据 * * @param provinceList 模拟的父省数据 * @return / */ private List getCityList(List provinceList) { List cityList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 cityList.add(new DemoCityData(0, 0, "合肥市")); cityList.add(new DemoCityData(1, 0, "芜湖市")); cityList.add(new DemoCityData(2, 1, "南京市")); cityList.add(new DemoCityData(3, 1, "无锡市")); cityList.add(new DemoCityData(4, 1, "徐州市")); selectParentData(provinceList, cityList); return cityList; } /** * 模拟查找数据库操作,需要连带查询出市的数据 * * @param cityList 模拟的父市数据 * @return / */ private List getAreaList(List cityList) { List areaList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 areaList.add(new DemoCityData(0, 0, "瑶海区")); areaList.add(new DemoCityData(1, 0, "庐江区")); areaList.add(new DemoCityData(2, 1, "南宁县")); areaList.add(new DemoCityData(3, 1, "镜湖区")); areaList.add(new DemoCityData(4, 2, "玄武区")); areaList.add(new DemoCityData(5, 2, "秦淮区")); areaList.add(new DemoCityData(6, 3, "宜兴市")); areaList.add(new DemoCityData(7, 3, "新吴区")); areaList.add(new DemoCityData(8, 4, "鼓楼区")); areaList.add(new DemoCityData(9, 4, "丰县")); selectParentData(cityList, areaList); return areaList; } /** * 模拟数据库的查询父数据操作 * * @param parentList / * @param sonList / */ private void selectParentData(List parentList, List sonList) { Map> parentGroupByIdMap = parentList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); sonList.forEach(everySon -> { if (parentGroupByIdMap.containsKey(everySon.getPid())) { everySon.setPData(parentGroupByIdMap.get(everySon.getPid()).get(0)); } }); } /** * 模拟的数据库省市县 */ @Data private static class DemoCityData { /** * 数据库id字段 */ private Integer id; /** * 数据库pid字段 */ private Integer pid; /** * 数据库name字段 */ private String name; /** * MyBatisPlus连带查询父数据 */ private DemoCityData pData; public DemoCityData(Integer id, Integer pid, String name) { this.id = id; this.pid = pid; this.name = name; } } }