Laravel使用Maatwebsite导入Excel时如何获取时间值并解决解析报错
问题原因
你遇到的报错是因为Excel中单独存储的时间类型值本质是0~1之间的浮点数,代表该时间在全天24小时中的占比(比如0.5对应12:00:00),你直接使用处理完整日期的方法解析纯时间浮点数时,PhpOffice会自动为浮点数添加@前缀识别为时间戳,最终触发格式解析错误。
另外你现有代码中调用Date::PHPToExcel($row[3])是完全错误的用法:该方法的作用是把PHP时间格式转为Excel序列值,和你需要的解析逻辑完全相反。
解决方法
PhpOffice提供的excelToDateTimeObject方法可以兼容处理时间值,也可以自行实现转换逻辑,两种可行方案如下:
方案1:自定义转换函数(兼容性更好)
直接对Excel时间浮点数做运算,直接转为数据库time类型支持的H:i:s格式:
// 可放在导入类的公共方法位置 private function excelTimeToDbTime($excelTime) { // 匹配Excel纯时间格式 if (is_numeric($excelTime) && $excelTime >= 0 && $excelTime < 1) { $totalSeconds = $excelTime * 86400; // 一天总秒数 $hours = (int)floor($totalSeconds / 3600); $minutes = (int)floor(($totalSeconds % 3600) / 60); $seconds = (int)$totalSeconds % 60; return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); } // 已经是字符串格式的时间直接返回 return $excelTime; }
修改后的业务代码:
public function collection(Collection $collection) { foreach($collection as $key => $row){ if ($key >= 4){ $tanggal = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($row[2]); $jam_masuk = $this->excelTimeToDbTime($row[3]); $jam_pulang = $this->excelTimeToDbTime($row[4]); DB::connection('sqlsrv2')->table('pga_master_absen')->insert([ 'noreg' => $row[0], 'nama' => $row[1], 'tanggal' => $tanggal, 'jam_masuk' => $jam_masuk, 'jam_pulang' => $jam_pulang, ]); } } }
方案2:使用PhpOffice原生方法处理
给时间浮点数拼接任意日期的Excel序列值,即可正常调用excelToDateTimeObject解析:
public function collection(Collection $collection) { foreach($collection as $key => $row){ if ($key >= 4){ $tanggal = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($row[2]); // 给时间值拼接当天日期序列值后解析 $jamMasukObj = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject( $row[3] + \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel(now()->toDateString()) ); $jamPulangObj = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject( $row[4] + \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel(now()->toDateString()) ); $jam_masuk = $jamMasukObj->format('H:i:s'); $jam_pulang = $jamPulangObj->format('H:i:s'); DB::connection('sqlsrv2')->table('pga_master_absen')->insert([ 'noreg' => $row[0], 'nama' => $row[1], 'tanggal' => $tanggal, 'jam_masuk' => $jam_masuk, 'jam_pulang' => $jam_pulang, ]); } } }
两种方案都可以直接适配你数据库的time类型字段存储要求。
内容的提问来源于stack exchange,提问作者andreaniwpi
相关产品推荐
相关产品推荐

