PHP Excel按SO NUMBER与Item Code分组实现Sales Order扣减Delivery Order数量
实现SO数量按分组扣减的PHP解决方案
你原先使用的双层嵌套循环时间复杂度为O(n²),数据量大时性能损耗严重,且存在数组下标越界的风险,更推荐使用单次遍历预聚合的方案,时间复杂度仅为O(n),实现逻辑如下:
方案1:输出分组汇总行(每个SO号+ITEM编码组合仅保留一行)
该方案和你目标格式的汇总逻辑匹配,先统计每个组合的总SO数量、总DO数量,再统一扣减计算剩余量:
// 第一步:预聚合统计每个分组的总数量 $groupStats = []; foreach ($data as $item) { // 拼接分组唯一key,分隔符可按需替换为不会出现在SO号/ITEM编码里的字符 $groupKey = $item['SONUMBER'] . '|' . $item['ITEMCODE']; if (!isset($groupStats[$groupKey])) { $groupStats[$groupKey] = [ 'SONUMBER' => $item['SONUMBER'], 'ITEMCODE' => $item['ITEMCODE'], 'totalSO' => 0, 'totalDO' => 0 ]; } $groupStats[$groupKey]['totalSO'] += $item['SOQTY']; $groupStats[$groupKey]['totalDO'] += $item['DOQTY']; } // 第二步:写入Excel $rowCount = 2; $activeSheet = $spreadsheet->setActiveSheetIndex(0); foreach ($groupStats as $stat) { // 计算剩余可发量,负数统一取0,可按需调整规则 $remainingQty = max(0, $stat['totalSO'] - $stat['totalDO']); $activeSheet ->setCellValue('A' . $rowCount, $stat['SONUMBER']) ->setCellValue('B' . $rowCount, $stat['ITEMCODE']) ->setCellValue('C' . $rowCount, $stat['totalSO']) ->setCellValue('D' . $rowCount, $stat['totalDO']) ->setCellValue('E' . $rowCount, $remainingQty); $rowCount++; }
方案2:保留原始明细行
如果需要保留所有原始明细,仅在每行追加对应分组的剩余量,可使用以下写法:
// 第一步:预统计每个分组的总DO数量 $groupDoTotal = []; foreach ($data as $item) { $groupKey = $item['SONUMBER'] . '|' . $item['ITEMCODE']; $groupDoTotal[$groupKey] = ($groupDoTotal[$groupKey] ?? 0) + $item['DOQTY']; } // 第二步:遍历明细写入Excel $rowCount = 2; $activeSheet = $spreadsheet->setActiveSheetIndex(0); foreach ($data as $item) { $groupKey = $item['SONUMBER'] . '|' . $item['ITEMCODE']; $remainingQty = max(0, $item['SOQTY'] - $groupDoTotal[$groupKey]); $activeSheet ->setCellValue('A' . $rowCount, $item['SONUMBER']) ->setCellValue('B' . $rowCount, $item['ITEMCODE']) ->setCellValue('C' . $rowCount, $item['SOQTY']) ->setCellValue('D' . $rowCount, $item['DOQTY']) ->setCellValue('E' . $rowCount, $remainingQty); $rowCount++; }
内容的提问来源于stack exchange,提问作者Erix Syaiful Rohman
相关产品推荐
相关产品推荐

