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

如何用Laravel Excel读取并修改含150+工作表的Excel文件?

问题说明

需要导入一个包含150+工作表的Excel文件,根据工作表名称替换表内数据或添加新行。原本考虑手动设计样式后导出,但效率太低。目前已实现获取指定工作表数据的功能,但不确定后续操作方向,也想确认当前方案是否合理。

环境:PHP 7.3.33,Laravel Framework 8.75.0

当前代码

控制器代码

<?php

namespace App\Http\Controllers;

use App\Imports\FirstSheetImport;
use App\Imports\WorkingPaperImport;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

class WorkingPaperExportController extends Controller
{
    public function getExcelAndRewrite(Request $request)
    {
        $import = new FirstSheetImport('EA1');

        $modifiedData = $import->getModifiedData();

        return $modifiedData;
    }
}

导入类代码

<?php

namespace App\Imports;

use App\Exports\TestExportEA1;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Events\AfterImport;
use PhpOffice\PhpSpreadsheet\IOFactory;

class FirstSheetImport implements ToCollection, WithHeadingRow
{
    protected $sheetName;
    protected $sheetIndex;
    protected $modifiedData = [];

    public function __construct($sheetName)
    {
        $this->sheetName = $sheetName;
    }

    public function collection(Collection $collection)
    {
        //
    }

    protected function getFilePath()
    {
        // Provide the path to your Excel file
        return storage_path('/import/uptodateworkingpaper.xlsx');
    }

    protected function hasHeadingRow()
    {
        // Return true or false based on your needs
        return true;
    }

    public function getModifiedData()
    {
        $spreadsheet = IOFactory::load($this->getFilePath());
        $sheetNames = $spreadsheet->getSheetNames();

        $sheetIndex = array_search($this->sheetName, $sheetNames);

        $this->sheetIndex = $sheetIndex;
        if ($sheetIndex !== false) {
            $worksheet = $spreadsheet->getSheet($sheetIndex);
            $rows = $worksheet->toArray();

            return $rows;
        }
        // return $this->sheetIndex;
    }
}

方案评估与后续操作建议

方案合理性判断

当前直接通过PhpOffice\PhpSpreadsheet\IOFactory加载文件并定位指定工作表的方式是可行的,但需注意:

  • 无需一次性加载所有150+工作表,按需处理单个目标表即可,避免内存溢出
  • 你的FirstSheetImport实现了Maatwebsite的ToCollection和WithHeadingRow接口,但collection方法未实际使用,若仅需操作指定表,可简化接口实现(或直接去掉不必要的接口)

后续操作步骤

  1. 修改/添加数据
    不要将工作表转为数组(会丢失样式信息),直接操作$worksheet对象:

    • 替换单元格数据:$worksheet->setCellValue('B3', '新内容');
    • 添加新行:
      // 在第2行前插入1行
      $worksheet->insertNewRowBefore(2, 1);
      // 填充新行数据
      $worksheet->setCellValue('A2', '新增行内容1');
      $worksheet->setCellValue('B2', '新增行内容2');
      
  2. 保存修改后的文件
    修改完成后,直接写入Excel文件(保留原样式):

    $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
    // 保存到指定路径,避免覆盖原文件
    $writer->save(storage_path('/export/modified_workingpaper.xlsx'));
    
  3. 返回结果或响应
    可以返回下载链接,或者直接触发文件下载:

    return response()->download(storage_path('/export/modified_workingpaper.xlsx'));
    

优化建议

  • 避免重复加载文件:若需处理多个工作表,可将$spreadsheet对象作为类属性缓存,无需每次调用都重新加载
  • 批量处理逻辑:遍历需要更新的工作表名称列表,逐个执行修改操作
  • 异常处理:添加try-catch块捕获文件加载、表名不存在等异常,结合日志记录错误信息
  • 简化接口实现:如果不需要Maatwebsite的导入集合功能,可去掉ToCollection和WithHeadingRow接口,减少冗余

内容的提问来源于stack exchange,提问作者Peram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:50:20