PhpSpreadsheet指定工作表另存为CSV失败,求解决方法
问题描述
尝试将XLSX中的指定工作表保存为CSV,使用setActiveSheetIndexByName()设置活动工作表后调用PhpSpreadsheet的CSV写入方法,但无论按名称还是索引切换,始终只保存第一个工作表。
测试代码如下:
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $reader->setReadDataOnly(true); $spreadsheet = $reader->load('infile.xlsx'); foreach($spreadsheet->getAllSheets() as $sheet) { $spreadsheet->setActiveSheetIndexByName($sheet->getTitle()); $activeSheet = $spreadsheet->getActiveSheet(); $title = $activeSheet->getTitle(); // 修正原代码笔误 echo $title . PHP_EOL; $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); $writer->save($title . '.csv', 2); }
控制台输出的工作表名称符合预期,生成的CSV文件名正确,但所有文件内容均与第一个工作表完全一致;临时调整工作表顺序可得到正确CSV,但这并非通用解决方案。
解决方案
PhpSpreadsheet的CSV Writer默认只会写入第一个工作表,切换活动工作表无法覆盖这个默认逻辑,以下是两种可靠的解决方式:
方法1:为目标工作表创建独立工作簿导出
在循环中,将当前工作表复制到新的空工作簿,仅保留该表进行导出:
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $reader->setReadDataOnly(true); $spreadsheet = $reader->load('infile.xlsx'); foreach($spreadsheet->getAllSheets() as $sheet) { $title = $sheet->getTitle(); echo $title . PHP_EOL; // 创建新工作簿并复制目标工作表 $newSpreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $newSpreadsheet->addSheet($sheet->copy()); // 删除新工作簿默认生成的空工作表 $newSpreadsheet->removeSheetByIndex(0); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($newSpreadsheet); $writer->save($title . '.csv'); // 释放内存 $newSpreadsheet->disconnectWorksheets(); unset($newSpreadsheet); } // 清理原工作簿内存 $spreadsheet->disconnectWorksheets(); unset($spreadsheet);
方法2:用setSheetIndex()指定导出工作表
CSV Writer提供了setSheetIndex()方法,可直接指定要导出的工作表索引,无需切换活动工作表:
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $reader->setReadDataOnly(true); $spreadsheet = $reader->load('infile.xlsx'); $allSheets = $spreadsheet->getAllSheets(); foreach($allSheets as $index => $sheet) { $title = $sheet->getTitle(); echo $title . PHP_EOL; $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); // 指定要导出的工作表索引 $writer->setSheetIndex($index); $writer->save($title . '.csv'); } $spreadsheet->disconnectWorksheets(); unset($spreadsheet);
注意事项
- 原代码中
$activeSheetgetTitle()属于语法错误,需修正为$activeSheet->getTitle(); - 处理完工作簿后调用
disconnectWorksheets()并unset,可避免内存泄漏,尤其适用于大型Excel文件场景。
内容的提问来源于stack exchange,提问作者user28698937
相关产品推荐
相关产品推荐

