You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 16:06:22