PHPSpreadSheet
PHPからExcelファイルの読み書きをするには、PHPExcelの後継となっているPHPSpreadSheetを使うのが一般的だろうか。https://phpspreadsheet.readthedocs.io/en/develop/
PHPSpreadSheetを使って、Excelファイルを読み込んで、CSVファイルに書き出す簡単な例は以下のようになる。
excel_test.php
<?php require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Reader\Xlsx as Reader; use PhpOffice\PhpSpreadsheet\Shared\Date; $reader = new Reader(); $spreadsheet = $reader->load('test.xlsx'); $sheet = $spreadsheet->getSheetByName('Sheet1'); $highest = $sheet->getHighestRow(); for ($i = 1; $i <= $highest; $i++) { echo $sheet->getCellByColumnAndRow(1, $i)->getValue() . ","; echo $sheet->getCellByColumnAndRow(2, $i)->getValue() . ","; echo $sheet->getCellByColumnAndRow(3, $i)->getValue() . ","; echo (Date::excelToDateTimeObject($sheet->getCellByColumnAndRow(4, $i)->getValue())->format('Y-m-d H:i:s')) . PHP_EOL; }
上記の例では、データが4カラム存在して、1-3カラム目は文字列データで、4カラム目は日付型になっていることを前提としている。
大量データを扱うと
ところが、上記のプログラムを何十万行もある行数の多いExcel(xlsx)ファイルに適用すると、エラーが発生してしまう。$ php excel_test.php Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 18874368 bytes) in /samples/php/spreadsheet/vendor/phpoffice/phpspreadsheet/src /PhpSpreadsheet/Collection/Memory.php on line 66
PHPSpreadSheetはxlsxファイルの内容をすべてメモリ上に展開しようとするのか、ファイルサイズに比べても、かなり多くのメモリを消費してしまう。
https://phpspreadsheet.readthedocs.io/en/develop/topics/memory_saving/
https://phpspreadsheet.readthedocs.io/en/develop/faq/
によると、キャッシュを使う手もあるようだけど、環境のメモリ設定を変えたり、別のキャッシュライブラリを導入するのは少々ハードルが高い。
Spout
そこで、このような用途のライブラリとしては、Spoutがもう一つの候補として出てくる。http://opensource.box.com/spout/
composerを使って、インストール。
$ cat composer.json { "require": { "box/spout": "@stable" } } $ composer install
Spoutを使って、先ほどと同様の例を作ると、こんな感じ。
spout_test.php
<?php require 'vendor/autoload.php'; use Box\Spout\Reader\ReaderFactory; use Box\Spout\Common\Type; $reader = ReaderFactory::create(Type::XLSX); $reader->open('test.xlsx'); $i = 0; foreach ($reader->getSheetIterator() as $sheet) { if ($sheet->getName() == 'Sheet1') { foreach ($sheet->getRowIterator() as $row) { echo $row[0] . "," . $row[1] . "," . $row[2] . "," . $row[3]->format('Y-m-d H:i:s') . PHP_EOL; } } } $reader->close();
$ php spout_test.php
今度はエラーが起らずに処理が完了した。
PHPSpreadSheetは高機能だけど、メモリ消費が大きい。
Spoutは機能はシンプルだけど、大量のデータ処理に向いている、と言ったところだろうか。
0 件のコメント:
コメントを投稿