- 本文地址: https://www.yangdx.com/2023/07/242.html
- 转载请注明出处
很久以前,还在用 php5.x 的时候,将数据导出为 Excel 文件需要用到 PHPExcel 扩展包。随着 php 版本更新到 7.x,PHPExcel 已过时,官方推出全新版本 PhpSpreadsheet。
但无论是 PHPExcel 还是 PhpSpreadsheet,都有个弊端:内存开销极大!这在操作大文件时及其明显,脚本动不动就内存超标。针对这个问题,PhpSpreadsheet 新增了一个缓存功能,可以在操作表格时,将数据缓冲到 Redis、Memcache 等地方,见官方文档:https://phpspreadsheet.readthedocs.io/en/latest/topics/memory_saving/。
近年来,开发项目一直使用 DcatAdmin 后台框架,记得框架里有个导出 Excel 的功能,但却不需要安装 PhpSpreadsheet,而是需要安装 Easy Excel,这是它的介绍:
Easy Excel
是一个基于 box/spout 封装的Excel读写工具,可以帮助开发者更快速更轻松地读写Excel文件, 并且无论读取多大的文件只需占用极少的内存。
在翻阅 Esay Excel 的 Issues 列表时,发现有人建议将 box/spout 换成 openspout/openspout,它也是基于 box/spout
开发的,而 box/spout
已在2022年5月日27存档停更,openspout/openspout
一直在迭代更新。
试用 OpenSpout v4.15.0 后,发现这个库不仅读写 Excel 超级快,消耗的内存也很小。如果不是有特殊需求,强烈推荐用 OpenSpout 替代 PhpSpreadsheet。
下面是我简单封装的读写 xlsx 文件的2个函数:
/**
* 读取XLSX文件
* @param string $filePath xlsx文件路径
* @param int|string $sheetIndexOrName 工作表下标或名称
* @return array 返回二维数组,第1维key表示第几行,第2维key表示第几列
* @throws \OpenSpout\Common\Exception\IOException
* @throws \OpenSpout\Reader\Exception\ReaderNotOpenedException
*/
function read_xlsx(string $filePath, int|string $sheetIndexOrName = 0): array
{
$options = new \OpenSpout\Reader\XLSX\Options();
// 应保留空行,可确保行号正确,因为我们用行号作为返回结果的下标
$options->SHOULD_PRESERVE_EMPTY_ROWS = true;
// 日期类型返回字面量而不是日期对象
$options->SHOULD_FORMAT_DATES = true;
$reader = new \OpenSpout\Reader\XLSX\Reader($options);
$reader->open($filePath);
$data = [];
$sheetExists = false;
foreach ($reader->getSheetIterator() as $sheet) {
if ($sheet->getIndex() === $sheetIndexOrName || $sheet->getName() === $sheetIndexOrName) {
$sheetExists = true;
foreach ($sheet->getRowIterator() as $rowIndex => $row) {
$data[$rowIndex] = [];
$colIndex = 1;
foreach ($row->getCells() as $cell) {
$data[$rowIndex][$colIndex] = $cell->getValue();
$colIndex++;
}
}
break;
}
}
if (!$sheetExists) {
throw new \Exception("工作表“{$sheetIndexOrName}”不存在");
}
$reader->close();
return $data;
}
/**
* 保存为XLSX文件
* @param array $data 数据,二维数组
* @param string $filePath 文件保存路径
* @return void
* @throws \OpenSpout\Common\Exception\IOException
* @throws \OpenSpout\Writer\Exception\WriterNotOpenedException
*/
function save_xlsx(array &$data, string $filePath): void
{
$writer = new \OpenSpout\Writer\XLSX\Writer();
$writer->openToFile($filePath);
foreach ($data as $row) {
$rowFromValues = \OpenSpout\Common\Entity\Row::fromValues($row);
$writer->addRow($rowFromValues);
}
$writer->close();
}
文章内容不错,是否可以转贴该文章?到 https://commandnotfound.cn 做技术文章收藏使用
博主回复:
可以的