PHP生成Allotment Request Form时日期按配额分组问题
解决Excel生成中连续相同配额日期的分组合并问题
核心思路
先对数据库返回的日期数据进行预处理:按日期升序排序后,将连续日期且total_kontenjan、dolu_kontenjan完全一致的记录合并为一个日期范围组,再将分组后的数据写入Excel,而非直接逐条输出原始数据。
步骤1:数据分组预处理代码
假设你从数据库查询到的原始数据已按tarih(日期)升序排序(务必加ORDER BY tarih ASC,否则分组逻辑失效),以下是分组处理的PHP代码:
// 示例原始数据库数据(需确保已按日期升序排序) $data = [ ['tarih' => '2024-05-01', 'total_kontenjan' => 10, 'dolu_kontenjan' => 3], ['tarih' => '2024-05-02', 'total_kontenjan' => 10, 'dolu_kontenjan' => 3], ['tarih' => '2024-05-03', 'total_kontenjan' => 15, 'dolu_kontenjan' => 5], ['tarih' => '2024-05-04', 'total_kontenjan' => 15, 'dolu_kontenjan' => 5], ['tarih' => '2024-05-05', 'total_kontenjan' => 10, 'dolu_kontenjan' => 4], ]; $groupedData = []; if (!empty($data)) { // 初始化第一个分组 $currentGroup = [ 'start_date' => $data[0]['tarih'], 'end_date' => $data[0]['tarih'], 'total' => $data[0]['total_kontenjan'], 'used' => $data[0]['dolu_kontenjan'] ]; foreach (array_slice($data, 1) as $item) { $currentDate = new DateTime($item['tarih']); $prevEndDate = new DateTime($currentGroup['end_date']); $prevEndDate->modify('+1 day'); // 判断:日期连续 + 两个配额值完全一致 if ($currentDate->format('Y-m-d') === $prevEndDate->format('Y-m-d') && $item['total_kontenjan'] === $currentGroup['total'] && $item['dolu_kontenjan'] === $currentGroup['used']) { // 合并到当前分组,更新结束日期 $currentGroup['end_date'] = $item['tarih']; } else { // 保存当前分组,初始化新分组 $groupedData[] = $currentGroup; $currentGroup = [ 'start_date' => $item['tarih'], 'end_date' => $item['tarih'], 'total' => $item['total_kontenjan'], 'used' => $item['dolu_kontenjan'] ]; } } // 保存最后一个分组 $groupedData[] = $currentGroup; }
步骤2:将分组数据写入Excel
以常用的PhpSpreadsheet为例(旧版PHPExcel逻辑完全一致),直接使用分组后的$groupedData生成Excel:
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 设置表头 $sheet->setCellValue('A1', '日期范围'); $sheet->setCellValue('B1', '总配额'); $sheet->setCellValue('C1', '已用配额'); // 填充分组数据 $rowNum = 2; foreach ($groupedData as $group) { // 生成日期范围文本:单日期直接显示,多日期显示"起始至结束"格式 $dateRange = $group['start_date'] === $group['end_date'] ? $group['start_date'] : "{$group['start_date']} 至 {$group['end_date']}"; $sheet->setCellValue("A{$rowNum}", $dateRange); $sheet->setCellValue("B{$rowNum}", $group['total']); $sheet->setCellValue("C{$rowNum}", $group['used']); $rowNum++; } // 输出Excel文件 $writer = new Xlsx($spreadsheet); $writer->save('allotment_request_form.xlsx');
关键注意事项
- 必须排序:数据库查询时必须添加
ORDER BY tarih ASC,否则连续日期的判断会出错; - 日期比较:使用
DateTime类处理日期,避免字符串直接比较导致的格式兼容问题; - 分组条件:必须同时满足「日期连续」「总配额相同」「已用配额相同」三个条件,才会合并为一个日期范围。
内容的提问来源于stack exchange,提问作者Laquire
相关产品推荐
相关产品推荐

