PhpExcel生成多列Excel损坏、数据写入错位问题求助
问题原因
两处代码的单元格坐标计算逻辑错误,是导致列显示异常、数据错位的核心原因,和列数多少、是否存在空列无关,类库本身无此类bug。
- 表头写入逻辑错误:PHP字符串递增规则不符合Excel坐标生成预期。初始坐标设为
A1时,执行++$col会优先递增字符串末尾的数字部分,第一次自增结果为A2而非预期的B1,所有表头被依次写入A列的纵向单元格,直接导致列显示错乱。 - 数据写入逻辑错误:行号拼接规则完全错误。初始
$row值设为0,拼接'A1' . $row得到的第一个单元格坐标为A10,后续循环依次生成A11、A12坐标,完全偏离第二行开始逐行写入的预期;此外代码重复对M列赋值两次,后续条件判断还会覆盖已写入的E列内容,进一步加剧数据错位。
修复代码
表头写入修复
固定行号为1,单独对列标识做递增,不要直接对完整的「列+行」坐标做自增操作。纯字母字符串的递增规则和Excel列标规则完全匹配,即使列数超过Z列(AA、AB等多字母列标)也可正常识别:
$spreadsheet = new Spreadsheet(); $spreadsheet->setActiveSheetIndex(0); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle(lang('invoices')); $col = 'A'; // 仅初始化列标识 foreach($columns as $value){ $sheet->setCellValue($col . '1', $value); // 拼接列标识+固定行号1得到坐标 ++$col; }
数据写入修复
行号初始值设为2(第一行已被表头占用),不要将行号硬编码在坐标字符串中再做拼接,同时删除重复赋值的冗余逻辑:
$row = 2; // 从第2行开始写入业务数据 foreach ($data as $data_row) { $sheet->setCellValue('A' . $row, '0'); $sheet->setCellValue('B' . $row, $data_row->id); $sheet->setCellValue('C' . $row, $data_row->customer_id); $sheet->setCellValue('D' . $row, $data_row->invoice_id); // 先写入默认的发票详情,后续满足条件再覆盖 $sheet->setCellValue('E' . $row, $data_row->invoice_details); $sheet->setCellValue('F' . $row, $data_row->account_set); $sheet->setCellValue('G' . $row, $data_row->issue_date); $sheet->setCellValue('H' . $row, 'TAS'); $sheet->setCellValue('I' . $row, $this->sma->formatNo($data_row->currency_rate)); $sheet->setCellValue('J' . $row, $this->sma->formatDecimal($data_row->grand_total)); $sheet->setCellValue('K' . $row, $this->sma->formatDecimal($data_row->invoice_tax)); $sheet->setCellValue('L' . $row, $this->sma->formatDecimal($data_row->grand_total)); $sheet->setCellValue('M' . $row, $this->sma->formatDecimal($data_row->grand_total)); $sheet->setCellValue('N' . $row, $this->sma->formatDecimal($data_row->grand_total)); $sheet->setCellValue('O' . $row, $this->sma->formatDecimal($data_row->grand_total)); $sheet->setCellValue('P' . $row, $this->sma->formatDecimal($data_row->invoice_tax)); if ($data_row->source_type == SHIPMENT) { $sheet->setCellValue('E' . $row, 'Newspaper distribution on ' . $this->sma->hrsd($data_row->issue_date) . ' to ' . $data_row->route_name); } $row++; }
补充说明
未填充数据的空列不会导致文件损坏或数据错位,无需特意为空列写入占位值。如果需要更严谨的列坐标处理,也可以使用PhpSpreadsheet内置的坐标处理方法做转换,避免手动拼接出错。
内容的提问来源于stack exchange,提问作者Nasz Njoka Sr.
相关产品推荐
相关产品推荐

