diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/controller/ESAnnualInitController.java b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/controller/ESAnnualInitController.java index 98e96d23..c8c74885 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/controller/ESAnnualInitController.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/controller/ESAnnualInitController.java @@ -2,6 +2,7 @@ package com.jero.modules.activiti.process.esAnnualInit.controller; import com.jero.common.api.vo.Result; import com.jero.common.aspect.annotation.AutoLog; +import com.jero.common.aspect.annotation.Translation; import com.jero.common.constant.enums.YesOrNoEnum; import com.jero.modules.activiti.process.esAnnualInit.entity.ProcessEsAnnualInit; import com.jero.modules.activiti.process.esAnnualInit.service.ProcessEsAnnualInitService; @@ -67,13 +68,14 @@ public class ESAnnualInitController { @PostMapping("/importExcel") @ApiOperation(value = "企标年度制修订标准化发起流程-导入", notes = "企标年度制修订标准化发起流程-导入") @AutoLog(value = "企标年度制修订标准化发起流程-导入") + @Translation public Result importExcel(@ApiParam(value = "要上传的文件", required = true) @RequestParam("file") MultipartFile file) { Map resultMap = annualInitService.importData(file); Object flag = resultMap.get("flag"); if (flag == YesOrNoEnum.YES.getValue()) { return Result.OK(resultMap.get("dataList")); } else { - return Result.error("导入失败", resultMap.get("msgList")); + return Result.error("导入失败", resultMap.get("msg")); } } diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/EsAnnualInitImportDTO.java b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/EsAnnualInitImportDTO.java new file mode 100644 index 00000000..ed88e832 --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/EsAnnualInitImportDTO.java @@ -0,0 +1,145 @@ +package com.jero.modules.activiti.process.esAnnualInit.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 企标-年度制修订计划-标准化发起 + * @TableName process_es_annual_init + */ +@Data +@Accessors(chain = true) +public class EsAnnualInitImportDTO implements Serializable { + + /** + * 制修订类型 + */ + @Excel(name = "制修订类型", width = 15, orderNum = "1") + @ApiModelProperty(value = "制修订类型") + private String projectType; + + /** + * 原企标编号 + */ + @Excel(name = "原企标编号", width = 15, orderNum = "2") + @ApiModelProperty(value = "原企标编号") + private String originEnStandardNo; + + /** + * 新企标编号 + */ + @Excel(name = "新企标编号", width = 15, orderNum = "3") + @ApiModelProperty(value = "新企标编号") + private String newEnStandardNo; + + /** + * 原企标名称 + */ + @Excel(name = "原企标名称", width = 15, orderNum = "4") + @ApiModelProperty(value = "原企标名称") + private String originEnStandardName; + + /** + * 新企标名称 + */ + @Excel(name = "新企标名称", width = 15, orderNum = "5") + @ApiModelProperty(value = "新企标名称") + private String newEnStandardName; + + /** + * 授权部门 + */ + @Excel(name = "授权部门", width = 15, orderNum = "6") + @ApiModelProperty(value = "授权部门") + private String authDept; + + /** + * 企业标准代号 + */ + @Excel(name = "企业标准代号", width = 15, orderNum = "7") + @ApiModelProperty(value = "企业标准代号") + private String enStandardCode; + + /** + * 配合单位 + */ + @Excel(name = "配合单位", width = 15, orderNum = "8") + @ApiModelProperty(value = "配合单位") + private String cooperationUnit; + + /** + * 主起草人 + */ + @Excel(name = "主起草人", width = 15, orderNum = "9") + @ApiModelProperty(value = "主起草人") + private String mainDraftingUser; + + /** + * 主起草单位 + */ + @Excel(name = "主起草单位", width = 15, orderNum = "10") + @ApiModelProperty(value = "主起草单位") + private String mainDraftingUnit; + + /** + * 主起草单位责任人 + */ + @Excel(name = "主起草单位责任人", width = 20, orderNum = "11") + @ApiModelProperty(value = "主起草单位责任人") + private String mainDraftingUnitResponsiblePerson; + + @Excel(name = "标准推进人", width = 15, orderNum = "12") + @ApiModelProperty(value = "标准推进人") + private String standardPromoter; + + /** + * 草稿计划完成日期 + */ + @Excel(name = "草稿计划完成日期", width = 20, orderNum = "13") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "草稿计划完成日期") + private Date draftPlannedCompleteDate; + + /** + * 征求意见稿计划完成日期 + */ + @Excel(name = "征求意见稿计划完成日期", width = 24, orderNum = "14") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "征求意见稿计划完成日期") + private Date solicitationDraftPlanCompleteDate; + + /** + * 计划报批日期 + */ + @Excel(name = "计划报批日期", width = 15, orderNum = "15") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "计划报批日期") + private Date planApprovalDate; + + /** + * 变更状态 + */ + @Excel(name = "变更状态", width = 15, orderNum = "16") + @ApiModelProperty(value = "变更状态") + private String changeStatus; + + /** + * 联络人 + */ + @Excel(name = "联络人", width = 15, orderNum = "17") + @ApiModelProperty(value = "联络人") + private String contactUser; + + @ApiModelProperty(value = "序号") + private String sort; +} \ No newline at end of file diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/ProcessEsAnnualInit.java b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/ProcessEsAnnualInit.java index d5df881c..0d386f79 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/ProcessEsAnnualInit.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/entity/ProcessEsAnnualInit.java @@ -15,8 +15,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelVerify; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotNull; + /** * 企标-年度制修订计划-标准化发起 * @TableName process_es_annual_init @@ -93,7 +96,7 @@ public class ProcessEsAnnualInit implements Serializable { /** * 制修订类型 */ - @Excel(name = "制修订类型", width = 15, orderNum = "1", dicCode = "esp_revision_type") + @Excel(name = "制修订类型", width = 15, orderNum = "1") @Dict(dicCode = "esp_revision_type") @ApiModelProperty(value = "制修订类型") private String projectType; @@ -108,7 +111,6 @@ public class ProcessEsAnnualInit implements Serializable { /** * 新企标编号 */ - @Excel(name = "新企标编号", width = 15, orderNum = "3") @ApiModelProperty(value = "新企标编号") private String newEnStandardNo; @@ -224,23 +226,25 @@ public class ProcessEsAnnualInit implements Serializable { /** * 主起草人 */ - @Excel(name = "主起草人", width = 15, orderNum = "9", dictTable = "sys_user", dicCode = "id", dicText = "username") + @Excel(name = "主起草人", width = 15, orderNum = "9") @Dict(dictTable = "sys_user", dicCode = "id", dicText = "username") + @NotNull @ApiModelProperty(value = "主起草人") private String mainDraftingUser; /** * 主起草单位 */ - @Excel(name = "主起草单位", width = 15, orderNum = "10", dictTable = "sys_depart", dicCode = "id", dicText = "depart_name") + @Excel(name = "主起草单位", width = 15, orderNum = "10") @Dict(dictTable = "sys_depart", dicCode = "id", dicText = "depart_name") + @NotNull @ApiModelProperty(value = "主起草单位") private String mainDraftingUnit; /** * 主起草单位责任人 */ - @Excel(name = "主起草单位责任人", width = 20, orderNum = "11", dictTable = "sys_user", dicCode = "id", dicText = "username") + @Excel(name = "主起草单位责任人", width = 20, orderNum = "11") @Dict(dicCode = "id", dictTable = "sys_user", dicText = "username") @ApiModelProperty(value = "主起草单位责任人") private String mainDraftingUnitResponsiblePerson; @@ -261,7 +265,6 @@ public class ProcessEsAnnualInit implements Serializable { /** * 变更状态 */ - @Excel(name = "变更状态", width = 15, orderNum = "16", dicCode = "esp_change_status") @Dict(dicCode = "esp_change_status") @ApiModelProperty(value = "变更状态") private String changeStatus; diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/ProcessEsAnnualInitService.java b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/ProcessEsAnnualInitService.java index 5af982f8..f1fd8cde 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/ProcessEsAnnualInitService.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/ProcessEsAnnualInitService.java @@ -2,6 +2,11 @@ package com.jero.modules.activiti.process.esAnnualInit.service; import com.jero.modules.activiti.process.esAnnualInit.entity.ProcessEsAnnualInit; import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; /** * @author ThinkBook @@ -10,4 +15,9 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface ProcessEsAnnualInitService extends IService { + /** + * 导入数据,返回数据列表 + * @return + */ + Map importData(MultipartFile file); } diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/impl/ProcessEsAnnualInitServiceImpl.java b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/impl/ProcessEsAnnualInitServiceImpl.java index 2dbecc8c..821a01c2 100644 --- a/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/impl/ProcessEsAnnualInitServiceImpl.java +++ b/laws-modules/src/main/java/com/jero/modules/activiti/process/esAnnualInit/service/impl/ProcessEsAnnualInitServiceImpl.java @@ -1,19 +1,294 @@ package com.jero.modules.activiti.process.esAnnualInit.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jero.common.api.CommonAPI; +import com.jero.common.constant.enums.YesOrNoEnum; +import com.jero.common.system.vo.SysDictItemCore; import com.jero.modules.activiti.process.esAnnualInit.entity.ProcessEsAnnualInit; import com.jero.modules.activiti.process.esAnnualInit.service.ProcessEsAnnualInitService; import com.jero.modules.activiti.process.esAnnualInit.mapper.ProcessEsAnnualInitMapper; +import com.jero.modules.activiti.process.esInitChange.entity.enums.ESPProjectType; +import com.jero.modules.activiti.util.ExcelUtils; +import com.jero.modules.laws.standard.entity.LawsEnterpriseStandard; +import com.jero.modules.laws.standard.service.ILawsEnterpriseStandardService; +import lombok.extern.slf4j.Slf4j; +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.entity.ImportParams; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; /** -* @author ThinkBook -* @description 针对表【process_es_annual_init(企标立项变更流程)】的数据库操作Service实现 -* @createDate 2023-10-18 10:01:44 -*/ + * @author ThinkBook + * @description 针对表【process_es_annual_init(企标立项变更流程)】的数据库操作Service实现 + * @createDate 2023-10-18 10:01:44 + */ +@Slf4j @Service public class ProcessEsAnnualInitServiceImpl extends ServiceImpl - implements ProcessEsAnnualInitService{ + implements ProcessEsAnnualInitService { + + @Resource + private CommonAPI commonAPI; + + @Resource + private ExcelUtils excelUtils; + + @Resource + private ILawsEnterpriseStandardService enterpriseStandardService; + + @Override + public Map importData(MultipartFile file) { + List listDict = commonAPI.getDictItemAll(); + Map resultMap = new HashMap<>(); + List errorMsgs = new ArrayList<>(); + + // 获取Excel的header + List headers; + try { + headers = ExcelUtils.getHeaderFromExcel(file.getInputStream()); + } catch (Exception e) { + errorMsgs.add("上传模板错误,请检查后重试。"); + resultMap.put("msg", errorMsgs); + resultMap.put("flag", YesOrNoEnum.NO.getValue()); + log.error(e.getMessage(), e); + return resultMap; // 返回错误信息 + } + + // 使用静态方法验证header + boolean isMatched = headers.equals(ExcelUtils.getSortedHeadersFromClass(ProcessEsAnnualInit.class)); + if (!isMatched) { + errorMsgs.add("上传模板错误,请检查后重试。"); + resultMap.put("msg", errorMsgs); + resultMap.put("flag", YesOrNoEnum.NO.getValue()); + return resultMap; // 返回错误信息 + } + + ImportParams params = new ImportParams(); + params.setTitleRows(1); + params.setHeadRows(1); + params.setNeedSave(true); + + try { + List list = ExcelImportUtil.importExcel(file.getInputStream(), ProcessEsAnnualInit.class, params); + if (list.isEmpty()) { + errorMsgs.add("文件暂无数据,请检查后重试。"); + resultMap.put("msg", errorMsgs); + resultMap.put("flag", YesOrNoEnum.NO.getValue()); + return resultMap; // 返回错误信息 + } + // 批量检查数据是否有效 + errorMsgs = this.validationList(list, listDict); + if (errorMsgs.size() > 0) { + resultMap.put("msg", errorMsgs); + resultMap.put("flag", YesOrNoEnum.NO.getValue()); + } else { + resultMap.put("flag", YesOrNoEnum.YES.getValue()); + // 转换为字典值 + this.transToDictValue(list, listDict); + // 清洗 + this.cleanData(list); + resultMap.put("dataList", list); + } + } catch (Exception e) { + errorMsgs.add("文件导入异常:" + e.getMessage()); + resultMap.put("msg", errorMsgs); + resultMap.put("flag", YesOrNoEnum.NO.getValue()); + log.error(e.getMessage(), e); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resultMap; + } + + private void cleanData(List list) { + list.forEach(item-> { + // 如果是制定则去除掉所有的原企标名称 原企标编号 + if (ESPProjectType.ENACT.getValue().equals(item.getProjectType())) { + item.setOriginEnStandardName(null); + item.setOriginEnStandardNo(null); + } + // 设置变更状态 制定是新增 修订是变更 + if (item.getProjectType().equals("制定")) { + item.setChangeStatus("新增"); + } else { + item.setChangeStatus("变更"); + } + }); + } + + private void transToDictValue(List list, List listDict) { + list.forEach(item -> { + item.setProjectType(excelUtils.translateDictValue("esp_revision_type", item.getProjectType(), listDict)); + item.setAuthDept(excelUtils.translateDictValue("depart_name", "id", "sys_depart", item.getAuthDept(), listDict)); + item.setEnStandardCode(excelUtils.translateDictValue("enterprise_standard_code", item.getEnStandardCode(), listDict)); + item.setCooperationUnit(excelUtils.translateDictValue("depart_name", "id", "sys_depart", item.getCooperationUnit(), listDict)); + item.setMainDraftingUser(excelUtils.translateDictValue("username", "id", "sys_user", item.getMainDraftingUser(), listDict)); + item.setMainDraftingUnit(excelUtils.translateDictValue("depart_name", "id", "sys_depart", item.getMainDraftingUnit(), listDict)); + item.setMainDraftingUnitResponsiblePerson(excelUtils.translateDictValue("username", "id", "sys_user", item.getMainDraftingUnitResponsiblePerson(), listDict)); + item.setStandardPromoter(excelUtils.translateDictValue("username", "id", "sys_user", item.getStandardPromoter(), listDict)); + item.setContactUser(excelUtils.translateDictValue("username", "id", "sys_user", item.getContactUser(), listDict)); + }); + } + + private List validationList(List list, List listDict) { + List esList = enterpriseStandardService.list(); + List errorMsgs = new ArrayList<>(); + + int i = 3; + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + ProcessEsAnnualInit plan = iterator.next(); + if (ExcelUtils.isEmptyRow(plan)) { + iterator.remove(); + continue; + } + plan.setSort(String.valueOf(i++)); + String enStandardCode = plan.getProjectType(); + String authDept = plan.getProjectType(); + String cooperationUnit = plan.getCooperationUnit(); + String mainDraftingUnit = plan.getMainDraftingUnit(); + String mainDraftingUser = plan.getProjectType(); + String mainDraftingUnitResponsiblePerson = plan.getMainDraftingUnitResponsiblePerson(); + String standardPromoter = plan.getStandardPromoter(); + String contactUser = plan.getContactUser(); + + StringBuilder errMsgHeader = new StringBuilder(); + StringBuilder errMsg = new StringBuilder(); + errMsgHeader.append("第").append(plan.getSort()).append("行"); + + // 检查制修订类型 编号 名称 + errMsg.append(validProjectType(plan, listDict, esList)); + // 检查所有数据字典校验的字段 + errMsg.append(validAuthDept(authDept, listDict)); + errMsg.append(validStandardCode(enStandardCode, listDict)); + errMsg.append(validCooperateUnit(cooperationUnit, listDict)); + errMsg.append(validMainDraftingUser(mainDraftingUser, listDict)); + errMsg.append(validMainDraftingUnit(mainDraftingUnit, listDict)); + errMsg.append(validMainDraftingUnitResponsiblePerson(mainDraftingUnitResponsiblePerson, listDict)); + errMsg.append(validStandardPromoter(standardPromoter, listDict)); + errMsg.append(validContactUser(contactUser, listDict)); + // 如果数据有问题,则将提示信息添加到 errorMsgs 中 + if (errMsg.length() > 0) { + errorMsgs.add(errMsgHeader.append(errMsg).toString()); + } + } + return errorMsgs; + } + + private String validAuthDept(String value, List listDict) { + // 非空检查 + if (StrUtil.isBlank(value)) { + return "'授权部门'不能为空。"; + } + // 检查授权部门 + if (!excelUtils.validDict("depart_name", value, "sys_depart", "id", false, listDict)) { + return "'授权部门'无效。"; + } + return ""; + } + private String validStandardCode(String value, List listDict) { + // 检查企业标准代号 + if (!excelUtils.validDict("enterprise_standard_code", value, null, null, true, listDict)) { + return "'企业标准代号'无效。"; + } + return ""; + } + private String validCooperateUnit(String value, List listDict) { // 非空检查 + if (StrUtil.isBlank(value)) { + return "'配合单位'不能为空。"; + } + // 检查配合单位 + if (!excelUtils.validDict("depart_name", value, "sys_depart", "id", false, listDict)) { + return "'配合单位'无效。"; + } + return ""; + } + private String validMainDraftingUser(String value, List listDict) { + if (StrUtil.isBlank(value)) { + return "'主起草人'不能为空。"; + } + // 检查主起草人 + if (!excelUtils.validDict("username", value, "sys_user", "id", true, listDict)) { + return "'主起草人'无效。"; + } + return ""; + } + private String validMainDraftingUnit(String value, List listDict) { + if (StrUtil.isBlank(value)) { + return "'主起草单位'不能为空。"; + } + // 检查主起草单位 + if (!excelUtils.validDict("depart_name", value, "sys_depart", "id", true, listDict)) { + return "'主起草单位'无效。"; + } + return ""; + } + private String validMainDraftingUnitResponsiblePerson(String value, List listDict) { + if (StrUtil.isBlank(value)) { + return "'主起草单位负责人'不能为空。"; + } + // 检查主起草单位负责人 + if (!excelUtils.validDict("username", value, "sys_user", "id", true, listDict)) { + return "'主起草单位负责人'无效。"; + } + return ""; + } + private String validStandardPromoter(String value, List listDict) { + if (StrUtil.isBlank(value)) { + return "'标准推进人'不能为空。"; + } + // 检查标准推进人 + if (!excelUtils.validDict("username", value, "sys_user", "id", true, listDict)) { + return "'标准推进人'无效。"; + } + return ""; + } + private String validContactUser(String value, List listDict) { + if (StrUtil.isBlank(value)) { + return "'联络人'不能为空。"; + } + // 检查联络人 + if (!excelUtils.validDict("username", value, "sys_user", "id", true, listDict)) { + return "'联络人'无效。"; + } + return ""; + } + + private String validProjectType(ProcessEsAnnualInit plan, List listDict, List esList) { + String projectType = plan.getProjectType(); + String originEnStandardNo = plan.getProjectType(); + String newEnStandardName = plan.getNewEnStandardName(); + if (StrUtil.isBlank(projectType)) { + return "'制修订类型'不能为空。"; + } + if (!excelUtils.validDict("esp_revision_type", projectType, null, null, true, listDict)) { + return "'制修订类型'无效。"; + } + // 修订 + if (projectType.equals(ESPProjectType.MODIFY.getValue())) { + // 检查企标编号是否有效 + if (StrUtil.isBlank(originEnStandardNo)) { + return "'原企标编号'不能为空。"; + } + if (!esList.stream().map(LawsEnterpriseStandard::getStandardNumber).collect(Collectors.toList()).contains(originEnStandardNo)) { + return "'原企标编号'无效。"; + } + } + if (newEnStandardName.length() > 50) { + return "'新企标名称'过长(最多50字)。"; + } + return ""; + } } diff --git a/laws-modules/src/main/java/com/jero/modules/activiti/util/ExcelUtils.java b/laws-modules/src/main/java/com/jero/modules/activiti/util/ExcelUtils.java new file mode 100644 index 00000000..d36310b3 --- /dev/null +++ b/laws-modules/src/main/java/com/jero/modules/activiti/util/ExcelUtils.java @@ -0,0 +1,209 @@ +package com.jero.modules.activiti.util; + +import com.jero.common.api.CommonAPI; +import com.jero.common.system.vo.SysDictItemCore; +import com.jero.common.util.oConvertUtils; +import com.jero.modules.system.entity.SysDictItem; +import org.apache.poi.ss.usermodel.Cell; +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.xssf.usermodel.XSSFWorkbook; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.annotation.Resource; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author: Mzaxd + * @Date: 2023/8/18 15:50 + */ +@Component +public class ExcelUtils { + + @Resource + private CommonAPI commonAPI; + + public static Date excelSerialDateToJavaDate(double serialDate) { + // 首先,我们定义数据库支持的最早和最晚的日期。 + Calendar minDate = Calendar.getInstance(); + minDate.set(1000, Calendar.JANUARY, 1); // 这是MySQL的最小日期,可以根据需要修改 + + Calendar maxDate = Calendar.getInstance(); + maxDate.set(9999, Calendar.DECEMBER, 31); // 这是MySQL的最大日期,可以根据需要修改 + + Calendar baseDate = Calendar.getInstance(); + baseDate.set(1900, Calendar.JANUARY, 1); // Excel起始日期是1900-01-01 + baseDate.add(Calendar.DATE, (int) serialDate - 2); // 减2是因为Excel中1900年被错误地视为闰年 + + // 现在我们比较日期是否在有效范围内 + if (baseDate.before(minDate) || baseDate.after(maxDate)) { + throw new IllegalArgumentException("日期超出了有效范围: " + baseDate.getTime()); + } + return baseDate.getTime(); + } + + /** + * 获取HeadRow的文本内容 + * + * @param is 文件输入流 + * @return HeadRow的List + * @throws Exception + */ + public static List getHeaderFromExcel(InputStream is) throws Exception { + List headers = new ArrayList<>(); + + Workbook workbook = new XSSFWorkbook(is); + Sheet sheet = workbook.getSheetAt(0); + + // HeadRow在index 1 + for (int rowIndex = 1; rowIndex <= 1; rowIndex++) { + Row row = sheet.getRow(rowIndex); + for (Cell cell : row) { + headers.add(cell.getStringCellValue()); + } + } + return headers; + } + + /** + * 获取一个类的所有带@Excel注解的字段的name属性值,并按照orderNum正序排序。 + * + * @param clazz 要检查的类 + * @return 包含所有带@Excel注解字段的name属性值的列表 + */ + public static List getSortedHeadersFromClass(Class clazz) { + List annotatedFields = new ArrayList<>(); + Field[] fields = clazz.getDeclaredFields(); + + for (Field field : fields) { + if (field.isAnnotationPresent(Excel.class)) { + annotatedFields.add(field); + } + } + + // 根据orderNum正序排序 + annotatedFields.sort(new Comparator() { + @Override + public int compare(Field o1, Field o2) { + Excel excel1 = o1.getAnnotation(Excel.class); + Excel excel2 = o2.getAnnotation(Excel.class); + return Integer.compare(Integer.parseInt(excel1.orderNum()), Integer.parseInt(excel2.orderNum())); + } + }); + + // 提取排序后字段的name属性值 + List sortedHeaders = new ArrayList<>(); + for (Field field : annotatedFields) { + Excel excel = field.getAnnotation(Excel.class); + sortedHeaders.add(excel.name()); + } + return sortedHeaders; + } + + /** + * 检查一个对象的所有带@Excel注解的字段是否为空。 + * + * @param obj 要检查的对象 + * @return 如果所有带@Excel注解的字段都为空,则返回true,否则返回false。 + */ + public static boolean isEmptyRow(Object obj) { + boolean isEmpty = true; // 假设行是空的 + Field[] fields = obj.getClass().getDeclaredFields(); // 获取类的所有字段 + + for (Field field : fields) { + if (field.isAnnotationPresent(Excel.class)) { // 检查字段是否有@Excel注解 + field.setAccessible(true); // 允许访问私有字段 + try { + Object value = field.get(obj); // 获取字段的值 + if (value != null) { // 如果字段不为空 + isEmpty = false; // 行不是空的 + break; + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return isEmpty; + } + + // 校验数据字典 + public boolean validDict(String dictCode, String dictValue, String dicTable, String dicText, boolean isSingle, List listDict) { + if (isSingle && dictValue.contains(",")) { + return false; + } + int count = dictValue.split(",").length; + String value = this.translateDictValue(dictCode, dicText, dicTable, dictValue, listDict); + return value != null && value.split(",").length == count; + } + + /** + * 翻译字典文本 + * + * @param code 编码 + * @param text 值 + * @param listDict 字典集合 + */ + public String translateDictValue(String code, String text, List listDict) { + StringBuilder textValue = new StringBuilder(); + String tmpValue = null; + List listNew = listDict.stream().filter(o -> Objects.equals(o.getDictCode(), code) && Objects.equals(o.getItemText(), text.trim())).collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(listNew)) { + tmpValue = listNew.get(0).getItemValue(); + } + if (tmpValue != null) { + if (!"".contentEquals(textValue)) { + textValue.append(","); + } + textValue.append(tmpValue); + } + return textValue.toString(); + } + + /** + * 翻译字典文本 + * + * @param code 编码 + * @param text 值 + * @param table 表名 + * @param key 键 + * @param listDict 字典集合 + */ + public String translateDictValue(String code, String text, String table, String key, List listDict) { + if (oConvertUtils.isEmpty(key)) { + return null; + } + StringBuilder textValue = new StringBuilder(); + String[] keys = key.split(","); + for (String k : keys) { + String tmpValue = null; + if (k.trim().length() == 0) { + continue; //跳过循环 + } + if (!StringUtils.isEmpty(table)) { + tmpValue = commonAPI.queryTableDictTextByKey(table, text, code, k.trim()); + } else { + List listNew = listDict.stream().filter(o -> Objects.equals(o.getDictCode(), code) && Objects.equals(o.getItemValue(), k.trim())).collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(listNew)) { + tmpValue = listNew.get(0).getItemText(); + } + } + + if (tmpValue != null) { + if (!"".contentEquals(textValue)) { + textValue.append(","); + } + textValue.append(tmpValue); + } + } + return textValue.toString(); + } +}