PHPExcelを使用してマルチページのxls / xslxをcsvに変換する

私のプロジェクトでは、多くの場合、さまざまなソースからデータをCSV形式で収集する必要があり、xlsテーブルのいくつかのページからデータを取得する必要はありませんでしたが、fgetcsv()/ fputcsv()だけが必要でした。 しかし、それでも「ドキュメントのすべてのページからデータを受信する」というタスクが設定された日が来ました。 そして、いつものように、私は自分の「自転車」を作らないように既製の解決策を探し始めました。 しかし、残念ながら、私は必要なものを正確に見つけることができませんでした。画面に複数ページのドキュメントを表示する同様のソリューションがありましたが、別のライブラリが使用されていましたが、それはxslx形式(Excel 2007 +)をサポートしていませんでした。 他のオプションをもう少し探した後、私はそれが悪いことに気付き、自分でライブラリを扱うことにしました。 PHPExcelライブラリを操作するためのいくつかのヒントを1つに組み合わせて、次のスクリプトを入手しました。 それでは始めましょう。



まず、 PHPExcel自体が必要です 。 すぐに、ライブラリはcomposerを介して適切にインストールされますが、明示的に完全なバージョンのライブラリはどこにも指定されていません。 選択方法として、バージョン1.8に「不正確」属性を追加して示しました。



require-devブロック{}に追加したcomposer.jsonで、次のレコードを取得しました。



"require-dev": {

"phpoffice/phpexcel": "~1.8"

},









現在インストールされているバージョン1.8.1。 PHPExcelライブラリは、バージョン5.3以降のPHPのSPLを継承しているため、foreach()を使用して行とドキュメントセルの配列の標準トラバーサルの代わりにイテレータを使用することにしました。



ライブラリを接続し、ドキュメントをロードして、初期データを決定します。



 /** Include PHPExcel */ include_once '../Classes/PHPExcel.php'; $callStartTime = microtime(true); $tmpFileName = microtime(true); $format = 'Ym-d'; // Load PHPExcel object $objPHPExcel = PHPExcel_IOFactory::load('multipage.xls');
      
      





次に、ページ数を知る必要のないページのイテレータを取得します。



 $sheetsIterator = $objPHPExcel->getWorksheetIterator();
      
      





イテレータは、次の単純な構造を使用してバイパスされます。



 while( $sheetsIterator->valid()) { $pageNumber = $sheetsIterator->key(); $pageContent = $sheetsIterator->current(); $sheetsIterator->next();
      
      





同様に、ドキュメントの行とセルが受信され、バイパスされました。 Habrの記事「 PHPExcelでのセルのユニバーサル読み取り」で 、セルからデータを取得するのがどれほど美しいかを知りました 。 欲望のあるすべてのチェックについては詳しく説明しません。この記事で読むことができます。



CSVファイルに書き込み、この方法でこのライブラリを使用して同じことを行います。



 // Create new object to write converted data and separate documents sheets $csvPagePhpExcel = new PHPExcel(); // HERE Add Data to Object // Creating CSV writer Object and save data to file $objWriter = PHPExcel_IOFactory::createWriter($csvPagePhpExcel, 'CSV'); $objWriter->save($currentTmpFileName);
      
      





スクリプトのフルバージョンで、以下のファイルに書き込むためのオブジェクトの塗りつぶしを示します。 私が追加できる唯一のもの:xls / xlsxドキュメントに再度日付を記述し、 明示的なフォーマットを指定する必要がある場合、PHPExcelオブジェクトを準備するときに、次の構成を使用できます。



  if ($isDate) { $csvPagePhpExcel->getActiveSheet()->getStyle($cellIterator->key().$rowIterator->key())->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2); $csvPagePhpExcel->getActiveSheet()->setCellValue($cellIterator->key().$rowIterator->key(), $cellValue); } else { $csvPagePhpExcel->getActiveSheet()->setCellValue($cellIterator->key().$rowIterator->key(), $cellValue); }
      
      





PHPExcel_Style_NumberFormat :: FORMAT_DATE_YYYYMMDD2定数を使用して形式を指定する場所。 この場合、これはyyyy-mm-dd形式で、MySqlクエリですぐに使用できます。



ちなみに、利用可能なすべてのライブラリ定数は次のとおりです。



 /* Pre-defined formats */ const FORMAT_GENERAL = 'General'; const FORMAT_TEXT = '@'; const FORMAT_NUMBER = '0'; const FORMAT_NUMBER_00 = '0.00'; const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00'; const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-'; const FORMAT_PERCENTAGE = '0%'; const FORMAT_PERCENTAGE_00 = '0.00%'; const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd'; const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd'; const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy'; const FORMAT_DATE_DMYSLASH = 'd/m/y'; const FORMAT_DATE_DMYMINUS = 'dm-y'; const FORMAT_DATE_DMMINUS = 'd-m'; const FORMAT_DATE_MYMINUS = 'm-y'; const FORMAT_DATE_XLSX14 = 'mm-dd-yy'; const FORMAT_DATE_XLSX15 = 'd-mmm-yy'; const FORMAT_DATE_XLSX16 = 'd-mmm'; const FORMAT_DATE_XLSX17 = 'mmm-yy'; const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm'; const FORMAT_DATE_DATETIME = 'd/m/yh:mm'; const FORMAT_DATE_TIME1 = 'h:mm AM/PM'; const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM'; const FORMAT_DATE_TIME3 = 'h:mm'; const FORMAT_DATE_TIME4 = 'h:mm:ss'; const FORMAT_DATE_TIME5 = 'mm:ss'; const FORMAT_DATE_TIME6 = 'h:mm:ss'; const FORMAT_DATE_TIME7 = 'i:s.S'; const FORMAT_DATE_TIME8 = 'h:mm:ss;@'; const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@'; const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-'; const FORMAT_CURRENCY_USD = '$#,##0_-'; const FORMAT_CURRENCY_EUR_SIMPLE = '[$EUR ]#,##0.00_-';
      
      





その結果、ドキュメントの各ページを個別のcsvファイルに書き込み、外部データの可用性に関係なく正しいセル値を受け取り、日付を適切な形式にフォーマットするスクリプトを取得しました。



ここに完全にあります:



 <?php /** Include PHPExcel */ include_once '../Classes/PHPExcel.php'; $callStartTime = microtime(true); // Load PHPExcel object $objPHPExcel = PHPExcel_IOFactory::load('multipage.xls'); // Get all document sheets $sheetsIterator = $objPHPExcel->getWorksheetIterator(); $tmpFileName = microtime(true); // Date format ready to import in SQL database $format = 'Ym-d'; while( $sheetsIterator->valid()) { $currentTmpFileName = "/tmp/{$tmpFileName}_sheet_{$sheetsIterator->key()}.csv"; echo $sheetsIterator->key() . '<hr />'; // Get current sheet rows $rowIterator = $sheetsIterator->current()->getRowIterator(); // Create new object to write converted data and separate documents sheets $csvPagePhpExcel = new PHPExcel(); while ($rowIterator->valid()) { // Get Cells from current Rows $cellIterator = $rowIterator->current()->getCellIterator(); echo '<br />' . $rowIterator->key() .'-'; while ($cellIterator->valid()) { $cellValue = $cellIterator->current()->getCalculatedValue(); //check is date if(PHPExcel_Shared_Date::isDateTime($cellIterator->current())) { $cellValue = date($format, PHPExcel_Shared_Date::ExcelToPHP($cellValue)); } //for incorrect formulas take old value if((substr($cellValue,0,1) === '=' ) && (strlen($cellValue) > 1)){ $cellValue = $cellIterator->current()->getOldCalculatedValue(); } $currentCellNum = PHPExcel_Cell::columnIndexFromString($cellIterator->key()); echo $cellIterator->key() . '(' . $currentCellNum . ') => ' . $cellValue; $csvPagePhpExcel->getActiveSheet()->setCellValue($cellIterator->key().$rowIterator->key(), $cellValue); $cellIterator->next(); } $rowIterator->next(); } // Creating CSV writer Object and save data to file $objWriter = PHPExcel_IOFactory::createWriter($csvPagePhpExcel, 'CSV'); $objWriter->save($currentTmpFileName); // clearing trash $csvPagePhpExcel->__destruct(); unset($csvPagePhpExcel); $objWriter = ''; unset($objWriter); $sheetsIterator->next(); } $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; echo $callTime;
      
      





テスト段階では、すべての値が画面に表示されるため、自然に出力を削除する必要がない人は誰でも削除できます。



批判、追加、訂正を歓迎します。 皆さんに感謝します。私の記事が誰かを助けて、数時間の仕事を減らしてくれたらとても嬉しいです。



All Articles