diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/controller/PayAttendanceController.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/controller/PayAttendanceController.java index 56aecef..2f84436 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/controller/PayAttendanceController.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/controller/PayAttendanceController.java @@ -1,9 +1,10 @@ package com.ruoyi.pay.controller; +import java.util.ArrayList; import java.util.List; import java.util.Arrays; -import java.util.concurrent.TimeUnit; - +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.pay.util.AttendanceExcelUtil; import lombok.RequiredArgsConstructor; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.*; @@ -17,13 +18,13 @@ import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; -import com.ruoyi.common.core.validate.QueryGroup; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.pay.domain.vo.PayAttendanceVo; import com.ruoyi.pay.domain.bo.PayAttendanceBo; import com.ruoyi.pay.service.IPayAttendanceService; import com.ruoyi.common.core.page.TableDataInfo; +import org.springframework.web.multipart.MultipartFile; /** * 考勤 @@ -58,6 +59,39 @@ public class PayAttendanceController extends BaseController { List list = iPayAttendanceService.queryList(bo); ExcelUtil.exportExcel(list, "考勤", PayAttendanceVo.class, response); } + /** + * 导入考勤列表 + */ + @SaCheckPermission("pay:attendance:import") + @Log(title = "考勤", businessType = BusinessType.IMPORT) + @PostMapping("/import") + public R importData(MultipartFile file, boolean updateSupport,String date,String kaoqinType,Long tenantId) throws Exception { + PayAttendanceBo attendance = new PayAttendanceBo(); + attendance.setKaoqinjiNum(kaoqinType); + attendance.setKaoqinYearMonth(date); + List occupaAttendance= iPayAttendanceService.queryList(attendance); + if(occupaAttendance!=null&&occupaAttendance.size()>0){ + if(!updateSupport){ //判断是否为更新 + return R.fail("已有当月考勤信息,如需更新请勾选更新考勤"); + }else{ //选择是更新数据时根据年月和考勤机删除原来记录的当月数据 + List ids = new ArrayList<>(); + for(PayAttendanceVo attendance1:occupaAttendance){ + ids.add(attendance1.getId()) ; + } + iPayAttendanceService.deleteWithValidByIds(ids,true); + } + } + + List attendanceList; + //判断考勤机(综合办与网机用一个模板,围栏一个模板) + if(!kaoqinType.equals("2")){ + attendanceList = new AttendanceExcelUtil().importKaoQinExcel(StringUtils.EMPTY,file.getInputStream(),3,date,kaoqinType,tenantId); + }else{ + attendanceList = new AttendanceExcelUtil().importKaoQinExcel2(StringUtils.EMPTY,file.getInputStream(),2,date,kaoqinType,tenantId); + } + String message = iPayAttendanceService.importAttendance(attendanceList, updateSupport, date); + return R.ok(message); + } /** * 获取考勤详细信息 @@ -79,7 +113,15 @@ public class PayAttendanceController extends BaseController { @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody PayAttendanceBo bo) { - return toAjax(iPayAttendanceService.insertByBo(bo)); + // 验证本人当日的考勤是否存在 + PayAttendanceBo query = new PayAttendanceBo(); + query.setEmpName(bo.getEmpName()); + query.setKaoqinDate(bo.getKaoqinDate()); + List attendances=iPayAttendanceService.queryList(query); + if (attendances==null||attendances.size()==0){ + return toAjax(iPayAttendanceService.insertByBo(bo)); + } + return R.fail("已存在"+bo.getEmpName()+"的考勤"); } /** diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/PayAttendance.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/PayAttendance.java index df5538e..721f5de 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/PayAttendance.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/PayAttendance.java @@ -52,22 +52,27 @@ public class PayAttendance extends BaseEntity { /** * 上午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date amStartTime; /** * 上午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date amEndTime; /** * 下午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date pmStartTime; /** * 下午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date pmEndTime; /** * 考勤日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") private Date kaoqinDate; /** * 考勤年份月份 (yyyy-MM) diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/bo/PayAttendanceBo.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/bo/PayAttendanceBo.java index c61ec19..cfa2c64 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/bo/PayAttendanceBo.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/bo/PayAttendanceBo.java @@ -62,30 +62,35 @@ public class PayAttendanceBo extends BaseEntity { /** * 上午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @NotNull(message = "上午开始时间不能为空", groups = { AddGroup.class, EditGroup.class }) private Date amStartTime; /** * 上午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @NotNull(message = "上午结束时间不能为空", groups = { AddGroup.class, EditGroup.class }) private Date amEndTime; /** * 下午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @NotNull(message = "下午开始时间不能为空", groups = { AddGroup.class, EditGroup.class }) private Date pmStartTime; /** * 下午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @NotNull(message = "下午结束时间不能为空", groups = { AddGroup.class, EditGroup.class }) private Date pmEndTime; /** * 考勤日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") @NotNull(message = "考勤日期不能为空", groups = { AddGroup.class, EditGroup.class }) private Date kaoqinDate; diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/vo/PayAttendanceVo.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/vo/PayAttendanceVo.java index a9ef272..20e8493 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/vo/PayAttendanceVo.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/domain/vo/PayAttendanceVo.java @@ -62,30 +62,35 @@ public class PayAttendanceVo { /** * 上午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "上午开始时间") private Date amStartTime; /** * 上午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "上午结束时间") private Date amEndTime; /** * 下午开始时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "下午开始时间") private Date pmStartTime; /** * 下午结束时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "下午结束时间") private Date pmEndTime; /** * 考勤日期 */ + @JsonFormat(pattern = "yyyy-MM-dd") @ExcelProperty(value = "考勤日期") private Date kaoqinDate; diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/mapper/PayAttendanceMapper.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/mapper/PayAttendanceMapper.java index 0fd6257..4026733 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/mapper/PayAttendanceMapper.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/mapper/PayAttendanceMapper.java @@ -3,6 +3,7 @@ package com.ruoyi.pay.mapper; import com.ruoyi.pay.domain.PayAttendance; import com.ruoyi.pay.domain.vo.PayAttendanceVo; import com.ruoyi.common.core.mapper.BaseMapperPlus; +import org.apache.ibatis.annotations.Select; /** * 考勤Mapper接口 @@ -11,5 +12,7 @@ import com.ruoyi.common.core.mapper.BaseMapperPlus; * @date 2025-05-12 */ public interface PayAttendanceMapper extends BaseMapperPlus { - + @Select({" select e.id employeeId,d.dept_id deptId,d.dept_name deptName from pay_employee_info e join sys_dept d on e.dept_id=d.dept_id " + + " where e.name=#{name} and e.deleted=0"} ) + PayAttendance selectEmpInfoByName(String empName); } diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/service/IPayAttendanceService.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/service/IPayAttendanceService.java index c592815..5a29841 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/service/IPayAttendanceService.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/service/IPayAttendanceService.java @@ -46,4 +46,8 @@ public interface IPayAttendanceService { * 校验并批量删除考勤信息 */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + PayAttendance selectEmpInfoByName(String empName); + + String importAttendance(List attendanceList, boolean updateSupport, String date); } diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/service/impl/PayAttendanceServiceImpl.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/service/impl/PayAttendanceServiceImpl.java index dc129f3..4057e0d 100644 --- a/ruoyi-pay/src/main/java/com/ruoyi/pay/service/impl/PayAttendanceServiceImpl.java +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/service/impl/PayAttendanceServiceImpl.java @@ -1,6 +1,7 @@ package com.ruoyi.pay.service.impl; import cn.hutool.core.bean.BeanUtil; +import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.domain.PageQuery; @@ -15,6 +16,7 @@ import com.ruoyi.pay.domain.PayAttendance; import com.ruoyi.pay.mapper.PayAttendanceMapper; import com.ruoyi.pay.service.IPayAttendanceService; +import java.text.SimpleDateFormat; import java.util.List; import java.util.Map; import java.util.Collection; @@ -117,4 +119,90 @@ public class PayAttendanceServiceImpl implements IPayAttendanceService { } return baseMapper.deleteBatchIds(ids) > 0; } + + @Override + public PayAttendance selectEmpInfoByName(String empName) { + return baseMapper.selectEmpInfoByName(empName); + } + + @Override + public String importAttendance(List attendanceList, boolean updateSupport, String date) { + if (null==attendanceList || attendanceList.size() == 0) + { + throw new ServiceException("导入考勤数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + for (PayAttendanceBo attendance : attendanceList) + { + try + { + // 验证本人当日的考勤是否存在(注意:在controller中更新数据时 以根据年月和考勤机删除原来记录数据) + PayAttendanceBo query = new PayAttendanceBo(); + query.setKaoqinDate(attendance.getKaoqinDate()); + query.setEmpName(attendance.getEmpName()); + List attendances=this.queryList(query); + if (null==attendances||attendances.size()==0) + { + this.insertByBo(attendance); + successNum++; + if(!updateSupport) { + successMsg.append("
" + successNum +": "+attendance.getEmpName()+new SimpleDateFormat("yyyy-MM-dd").format(attendance.getKaoqinDate())+ "考勤导入成功"); + }else{ + successMsg.append("
" + successNum +": "+attendance.getEmpName()+new SimpleDateFormat("yyyy-MM-dd").format(attendance.getKaoqinDate())+"考勤更新成功"); + } + } else { //员工在多个考勤机录入考勤 时进入 (注意:要求员工上午或下午打卡必须在同一个考勤机) + if(updateSupport){ + if(attendance.getAmStartTime()==null&&attendance.getAmEndTime()==null){ + attendance.setAmStartTime(attendances.get(0).getAmStartTime()); + attendance.setAmEndTime(attendances.get(0).getAmEndTime()); + } + if(attendance.getPmStartTime()==null&&attendance.getPmEndTime()==null){ + attendance.setPmStartTime(attendances.get(0).getPmStartTime()); + attendance.setPmEndTime(attendances.get(0).getPmEndTime()); + } + this.updateByBo(attendance); + successNum++; + successMsg.append("
" + successNum +": "+attendance.getEmpName()+new SimpleDateFormat("yyyy-MM-dd").format(attendance.getKaoqinDate())+ "考勤更新成功"); + }else{ + String kaoqinji=""; + switch (attendances.get(0).getKaoqinjiNum()){ + case "0": + kaoqinji ="综合办"; + break; + case "1": + kaoqinji ="网机"; + break; + case "2": + kaoqinji ="围栏"; + break; + case "3": + kaoqinji ="手动添加"; + break; + } + failureNum++; + failureMsg.append("
" + failureNum +": "+attendance.getEmpName()+new SimpleDateFormat("yyyy-MM-dd").format(attendance.getKaoqinDate())+" "+kaoqinji+"考勤机已存在"); + + } + } + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum+ ": "+attendance.getEmpName() +" "+attendance.getEmpName()+new SimpleDateFormat("yyyy-MM-dd").format(attendance.getKaoqinDate()) + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + System.err.println(msg+e); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "导入成功"+successNum+"条,导入失败" + failureNum + " 条,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } } diff --git a/ruoyi-pay/src/main/java/com/ruoyi/pay/util/AttendanceExcelUtil.java b/ruoyi-pay/src/main/java/com/ruoyi/pay/util/AttendanceExcelUtil.java new file mode 100644 index 0000000..4b8b3b7 --- /dev/null +++ b/ruoyi-pay/src/main/java/com/ruoyi/pay/util/AttendanceExcelUtil.java @@ -0,0 +1,531 @@ +package com.ruoyi.pay.util; + +import cn.hutool.core.lang.Dict; +import com.ruoyi.common.core.service.DictService; +import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.pay.domain.PayAttendance; +import com.ruoyi.pay.domain.bo.PayAttendanceBo; +import com.ruoyi.pay.service.IPayAttendanceService; +import org.springframework.stereotype.Component; + +import cn.hutool.core.date.DateTime; + +import org.apache.poi.ss.usermodel.Row; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; + +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +@Component +public class AttendanceExcelUtil { + + private final IPayAttendanceService iPayAttendanceService; + private final DictService dictService; + + public AttendanceExcelUtil() { + this.iPayAttendanceService = SpringUtils.getBean(IPayAttendanceService.class); + this.dictService = SpringUtils.getBean(DictService.class); + } + + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; + + public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + //private Excel.Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 当前行号 + */ + private int rownum; + + /** + * 标题 + */ + private String title; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 + * @param is 输入流 + * @return 转换后集合 + */ + public List importKaoQinExcel(String sheetName, InputStream is, int titleNum, String date,String kaoqinType,Long tenantId) throws Exception { + List attendances = new ArrayList<>(); + //this.type = Excel.Type.IMPORT; + this.wb = WorkbookFactory.create(is); + + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(2); + if (sheet == null) { + throw new IOException("文件sheet不存在"); + } + /* boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); + Map pictures; + if (isXSSFWorkbook) { + pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); + } else { + pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); + }*/ + + // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + //把日期存放到list中 + List days = new ArrayList<>(); + if (rows > 0) { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + /* Row heard = sheet.getRow(titleNum); + String[] yearAndMonth =date.split("-"); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) { + String value = this.getCellValue(heard, i).toString(); + if(value!=null&&!value.trim().equals("")){ + if(i<9){ + value=0+value; + } + days.add(value); + } + } + }*/ + int dayNumOfMonth = getDaysOfMonth(date); + for (Integer i = 1; i <= dayNumOfMonth; i++) { + if(i<=9){ + days.add("0"+i); + }else { + days.add(i.toString()); + } + } + //每2行是一条员工数据,除第titlenum行外,一次循环2行 + for (int i = titleNum + 1; i <= rows; i += 2) { + // 从第2行开始取数据,默认第一行是表头. + Row row1 = sheet.getRow(i); + Row row2 = sheet.getRow(i + 1); + // 判断当前行是否是空行 + if (isRowEmpty(row1)) { + continue; + } + String wid = this.getCellValue(row1, 2).toString();//考勤机工号 + String wname = this.getCellValue(row1, 10).toString(); + //根据员工name查询员工id、部门id、部门名称 + PayAttendance info = iPayAttendanceService.selectEmpInfoByName(wname); + if(info==null){ + throw new IOException("请先在员工表中添加员工:"+wname+" 或者考勤机选择错误"); + } + for (int j = 0; j < row2.getPhysicalNumberOfCells(); j++) { + if((j+1)>days.size()){ + break; + } + PayAttendanceBo attendance = new PayAttendanceBo(); + //attendance.setTenantId(LoginHelper.getTenantId()); + attendance.setTenantId(tenantId); + attendance.setKaoqinYearMonth(date); + attendance.setEmpName(wname); + attendance.setKaoqinjiNum(kaoqinType); + attendance.setEmployeeId(info.getEmployeeId()); + attendance.setDeptId(info.getDeptId()); + attendance.setDeptName(info.getDeptName()); + //得到年月日 + + String strday = date+"-"+days.get(j); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Date day = sdf.parse(strday); + attendance.setKaoqinDate(day); + + Cell cell = row2.getCell(j); + if (!(null==cell)) { + String value = this.getCellValue(row2, j).toString(); + // System.out.println("*************************************:" + value); + if (value != null && !value.trim().equals("")) { //判断非空或者非空串单元格 + String[] times = value.split("\n"); + /* Date standard = new DateTime(strday + " 13:00:00");//以13点为分界线,改为去字典配置分界时间,去字典中去值*/ + Date standard = new DateTime(strday + " " +dictService.getDictValue("time_divid","noon_time"));//以字典值为分界线 + List ams = new ArrayList<>();//上午时间段内 + List pms = new ArrayList<>();//下午时间短内 + SimpleDateFormat punchTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (String t : times) { + Date time = punchTime.parse(strday + " " + t + ":00"); + if (time.before(standard)) { + ams.add(time); + } else { + pms.add(time); + } + } + //判断上下午时间段有几个值,对应存储 + switch (ams.size()) { + case 0: + break; + case 1: + if(ams.get(0).before(punchTime.parse(strday+" 10:30:00"))){ //上午只打了一次卡 过了上午10点半算下班卡 + attendance.setAmStartTime(ams.get(0)); + }else{ + attendance.setAmEndTime(ams.get(0)); + } + break; + default: + List amtimes = getDates(ams); + attendance.setAmStartTime(amtimes.get(0)); + attendance.setAmEndTime(amtimes.get(1)); + break; + } + switch (pms.size()) { + case 0: + break; + case 1: + if(pms.get(0).before(punchTime.parse(strday+" 16:30:00"))){ //下午只打了一次卡 过了下午四点半算下班卡 + attendance.setPmStartTime(pms.get(0)); + }else{ + attendance.setPmEndTime(pms.get(0)); + } + break; + default: + List pmtimes = getDates(pms); + attendance.setPmStartTime(pmtimes.get(0)); + attendance.setPmEndTime(pmtimes.get(1)); + break; + } + } + } + attendances.add(attendance); + } + } + } + return attendances; + } + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (!(null==cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } + + /** + * 判断是否是空行 + * + * @param row 判断的行 + * @return + */ + private boolean isRowEmpty(Row row) + { + if (row == null) + { + return true; + } + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) + { + Cell cell = row.getCell(i); + if (cell != null && cell.getCellType() != CellType.BLANK) + { + return false; + } + } + return true; + } + /** + * 返回日期中的最大值 最小值 + */ + private List getDates(List dates){ + List times = new ArrayList<>(); + Date max = dates.get(0); + Date min = dates.get(0); + for(Date time:dates){ + if(time.before(max)){ + min = time; + }else{ + max = time; + } + } + times.add(min); + times.add(max); + return times; + } + + public List importKaoQinExcel2(String empty, InputStream inputStream, int titleNum, String date,String kaoqinType,Long tenantId) throws Exception{ + List attendances = new ArrayList<>(); + // this.type = Excel.Type.IMPORT; + this.wb = WorkbookFactory.create(inputStream); + + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第3个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(2); + if (sheet == null) { + throw new IOException("文件sheet不存在"); + } + boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); + /*Map pictures; + if (isXSSFWorkbook) { + pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); + } else { + pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); + }*/ + // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + //把日期存放到list中 + List days = new ArrayList<>(); + if (rows > 0) { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + /*Row heard = sheet.getRow(titleNum); + + for (int i = 3; i < heard.getPhysicalNumberOfCells(); i++) { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) { + String value = this.getCellValue(heard, i).toString(); + if(value!=null&&!value.trim().equals("")){ + if(i<9){ + value=0+value; + } + days.add(value); + } + } + }*/ + int dayNumOfMonth = getDaysOfMonth(date); + for (Integer i = 1; i <= dayNumOfMonth; i++) { + if(i<=9){ + days.add("0"+i); + }else { + days.add(i.toString()); + } + } + + + //每1行是一条员工数据,除第titlenum+2行外,一次循环1行 + for (int i = titleNum + 2; i <= rows; i++) { + // 从第2行开始取数据,默认第一行是表头. + Row row1 = sheet.getRow(i); + // 判断当前行是否是空行 + if (isRowEmpty(row1)) { + continue; + } + String wid = this.getCellValue(row1, 0).toString();//考勤机工号 + String wname = this.getCellValue(row1, 1).toString();//姓名 + //根据员工name查询员工id、部门id、部门名称 + PayAttendance info = iPayAttendanceService.selectEmpInfoByName(wname); + if(info==null){ + throw new IOException("请先在员工表中添加员工:"+wname+" 或者考勤机选择错误"); + } + for (int j = 3; j < row1.getPhysicalNumberOfCells(); j++) { + if((j-2)>days.size()){ + break; + } + PayAttendanceBo attendance = new PayAttendanceBo(); + //attendance.setTenantId(LoginHelper.getTenantId()); + attendance.setTenantId(tenantId); + attendance.setKaoqinYearMonth(date); + attendance.setEmpName(wname); + attendance.setKaoqinjiNum(kaoqinType); + + attendance.setEmployeeId(info.getEmployeeId()); + attendance.setDeptId(info.getDeptId()); + attendance.setDeptName(info.getDeptName()); + + String strday = date+"-"+days.get(j-3); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Date day = sdf.parse(strday); + attendance.setKaoqinDate(day); + + Cell cell = row1.getCell(j); + if (!(null==cell)){ + String value = this.getCellValue(row1, j).toString(); + // System.out.println("*************************************:"+value); + if(value!=null&&!value.trim().equals("")) {//判断非空或者非空串单元格 + String[] times = value.split("\n"); + /* Date standard = new DateTime(strday + " 13:00:00");//以13点为分界线,改为去字典配置分界时间,去字典中去值*/ + Date standard = new DateTime(strday + " " + dictService.getDictValue("pay_time_divid","noon_time"));//以13点为分界线 + List ams = new ArrayList<>();//上午时间段内 + List pms = new ArrayList<>();//下午时间短内 + SimpleDateFormat punchTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for(String t:times){ + Date time= punchTime.parse(strday+" "+t+":00"); + if(time.before(standard)){ + ams.add(time); + }else{ + pms.add(time); + } + } + //判断上下午时间段有几个值,对应存储 + switch (ams.size()){ + case 0: + break; + case 1: + if(ams.get(0).before(punchTime.parse(strday+" 10:30:00"))){ //上午只打了一次卡 过了上午10点半算下班卡 + attendance.setAmStartTime(ams.get(0)); + }else{ + attendance.setAmEndTime(ams.get(0)); + } + break; + default: + List amtimes = getDates(ams); + attendance.setAmStartTime(amtimes.get(0)); + attendance.setAmEndTime(amtimes.get(1)); + break; + } + switch (pms.size()){ + case 0: + break; + case 1: + if(pms.get(0).before(punchTime.parse(strday+" 16:30:00"))){ //下午只打了一次卡 过了下午四点半算下班卡 + attendance.setPmStartTime(pms.get(0)); + }else{ + attendance.setPmEndTime(pms.get(0)); + } + break; + default: + List pmtimes = getDates(pms); + attendance.setPmStartTime(pmtimes.get(0)); + attendance.setPmEndTime(pmtimes.get(1)); + break; + } + + } + } + attendances.add(attendance); + } + } + } + return attendances; + } + //获取一个月天数 + public static int getDaysOfMonth(String datestr) throws ParseException { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM"); + Date date = format.parse(datestr); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + } + + + +} +