使用PhpSpreadsheet导入Excel到MySQL时补全缺失日期的实现问题
解决方案
实现逻辑如下:
- 先收集Excel中已存在的所有日期,存入去重数组方便快速校验
- 动态获取导入数据覆盖的月份起止范围,遍历该范围内的每一天
- 判定当日为周日且不存在于已存在日期集合时,插入自定义的补全数据
- 原有Excel数据的入库逻辑保持不变
修改后可直接运行的完整代码:
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $spreadsheet = $reader->load("uploads/temp.xlsx"); $worksheet = $spreadsheet->getActiveSheet(); $spreadSheetAry = $worksheet->toArray(); $sheetCount = count($spreadSheetAry); $sql = "INSERT INTO tbl_tour (user_email,date,day,school_name,visit_status,reason) VALUES (?,?,?,?,?,?)"; $stmt=$mysqli->prepare($sql); // 第一步:收集Excel中已存在的所有日期,同时处理原有数据入库 $existingDates = []; // 原代码循环条件<=存在数组越界风险,已调整为< for ($i = 1; $i < $sheetCount; $i ++) { $date =""; $day =""; $school_name =""; $visit_status = ""; $reason = ""; if (isset($spreadSheetAry[$i][1])) { $date = $spreadSheetAry[$i][1]; // 存入已存在日期集合,自动去重 if (!in_array($date, $existingDates)) { $existingDates[] = $date; } } if (isset($spreadSheetAry[$i][2])) { $day = $spreadSheetAry[$i][2]; } if (isset($spreadSheetAry[$i][3])) { $school_name = $spreadSheetAry[$i][3]; } if (isset($spreadSheetAry[$i][4])) { $visit_status = $spreadSheetAry[$i][4]; } if (isset($spreadSheetAry[$i][5])) { $reason = $spreadSheetAry[$i][5]; } $stmt->bind_param('ssssss',$email,$date,$day,$school_name,$visit_status,$reason); $stmt->execute(); } // 第二步:补全缺失的周日数据 if (!empty($existingDates)) { // 从现有日期中获取月份范围 $firstDate = DateTime::createFromFormat('d-m-Y', min($existingDates)); $lastDate = DateTime::createFromFormat('d-m-Y', max($existingDates)); // 重置到当月第一天和最后一天,覆盖整月所有日期 $firstDate->modify('first day of this month'); $lastDate->modify('last day of this month'); $currentDate = clone $firstDate; while ($currentDate <= $lastDate) { $formattedDate = $currentDate->format('d-m-Y'); // format('w')返回0代表周日 if ($currentDate->format('w') == 0 && !in_array($formattedDate, $existingDates)) { // 以下补全字段内容可按需自行修改 $fillDay = $currentDate->format('l'); $fillSchool = ''; $fillStatus = '公休'; $fillReason = '周日休息'; $stmt->bind_param('ssssss',$email,$formattedDate,$fillDay,$fillSchool,$fillStatus,$fillReason); $stmt->execute(); } $currentDate->modify('+1 day'); } } $stmt->close();
补充说明
- 补全的字段值可以根据业务需求随意调整,包括day字段的输出格式、visit_status和reason的自定义内容
- 如果需要固定处理指定月份,可直接手动赋值
$firstDate和$lastDate,不需要从已有日期动态获取 - 如果每个周日需要插入2条和其他日期格式一致的重复数据,在补全逻辑中重复执行一次bind_param和execute即可
内容的提问来源于stack exchange,提问作者Nidhi
相关产品推荐
相关产品推荐

