phpspreadsheet 插件
之前PHP操作Excel数据时都是使用PHPExcel库,但是phpoffice已经官方宣布PHPExcel已经被废弃不在维护,所以改用PHPExcel插件了。
安装
composer require phpoffice/phpspreadsheet
使用
因为一般业务给的Excel表格都比较大,所以需要分页处理,项目使用的是laravel框架。
首先创建一个分页的函数:
class ChunkReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter
{
private $startRow = 0;
private $endRow = 0;
/** Set the list of rows that we want to read */
public function setRows($startRow, $chunkSize) {
$this->startRow = $startRow;
$this->endRow = $startRow + $chunkSize;
}
public function readCell($column, $row, $worksheetName = '') {
// Only read the heading row, and the configured rows
if (($row == 1) || ($row >= $this->startRow && $row < $this->endRow)) {
return true;
}
return false;
}
}
分页读出Excel表格内容:
try {
$inputFileType = self::getFileType($filePath);
if (!$inputFileType) {
Log::error(sprintf('获取文件类型失败%s', $filePath));
return null;
}
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$chunkFilter = new ChunkReadFilter();
$reader->setReadFilter($chunkFilter);
while (true) {
$startRow = 2 + $perpage * $page;
$chunkFilter->setRows($startRow, $perpage);
$spreadsheet = $reader->load($filePath);
$sheet = $spreadsheet->getActiveSheet();
$sheetData = $sheet->toArray(null, true, true, true);
$sheetData = array_slice($sheetData, $startRow - 1, $perpage);
if (empty($sheetData)) {
break;
}
$this->importDatas($sheetData, $total, $success); //业务处理函数
Log::info('第'.$i.'页导入'.$i);
$i++;
$page++;
usleep(300000);
}
} catch (\Exception $e) {
Log::error(
sprintf(
'getFileContent error, file:%s, error: %s',
$filePath,
$e->getMessage()
)
);
return null;
}
//获取文件类型函数
private static function getFileType($file)
{
$fileExtentsion = pathinfo($file, PATHINFO_EXTENSION);
if ($fileExtentsion == "xlsx") {
return "Xlsx";
}
if ($fileExtentsion == "xls") {
return "Xls";
}
if ($fileExtentsion == "csv") {
return "Csv";
}
return null;
}
这样就能分页处理Excel表格了。
此方法及其容易引起内存溢出,因为这种分页的实现是先将分页数据前的数据读入内存,再从你要的数据开始返回你的分页数,当page越大时,需要load进内存的记录越多,当达到一定的数量就会发生溢出。
phpspreadsheet官网针对内存溢出给出了解决方案。。。