今回はさらに小ネタですが、XAMPP でのデバッグ時によく遭遇するエラーなのですが PhpSpreadsheet で出力されたエクセルファイルを MS-EXCEL で開いたままで 同じプログラムを実行した時には以下の様な WARNING と ERROR が表示されます。
Warning: fopen(test6-a3.xlsx): failed to open stream: Resource temporarily unavailable in C:\xampp\htdocs\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\BaseWriter.php on line 125 Fatal error: Uncaught PhpOffice\PhpSpreadsheet\Writer\Exception: Could not open file "test6-a3.xlsx" for writing. in C:\xampp\htdocs\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\BaseWriter.php:127 Stack trace: #0 C:\xampp\htdocs\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\Xlsx.php(542): PhpOffice\PhpSpreadsheet\Writer\BaseWriter->openFileHandle() #1 C:\xampp\htdocs\_phpspread\excel6-all-3.php(23): PhpOffice\PhpSpreadsheet\Writer\Xlsx->save() #2 {main} thrown in C:\xampp\htdocs\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\BaseWriter.php on line 127
このエラーが発生したプログラムは以下の記事のものを使用しています。
⇒PHP PhpSpreadsheet エクセルのワークシートのセルに日付型データの設定と、日付スタイル設定について2(setCellValue, getStyle)>
<?php // ライブラリ読込 require '../vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Spreadsheetオブジェクト生成 $objSpreadsheet = new Spreadsheet(); // ワークシートオブジェクト $objSheet = $objSpreadsheet->getActiveSheet(); // セルにシステム時刻(Unix Time)を設定 $objSheet->setCellValue('A2', Date::PHPToExcel(time())); $objSheet->setCellValue([1, 3], Date::PHPToExcel(time())); // スタイルオブジェクト取得([A2]セル) $objStyle = $objSheet->getStyle('A2')->getNumberFormat()->setFormatCode('yyyy"年"m"月"d"日";@'); $objStyle = $objSheet->getStyle([1, 3, 1, 3])->getNumberFormat()->setFormatCode('yyyy"年"m"月"d"日";@'); // [test6-a2.xlsx]:Excel2007形式で保存する $objWriter = new Xlsx($objSpreadsheet); $objWriter->save('test6-a2.xlsx'); exit(); ?>
エラーが発生しているのは 23行目の save の部分です。 MS-EXCEL で開いたままの状態なので、ファイルにロックが掛かっていて上書きができない状況です。
MS-EXCEL を閉じてから再実行すれば問題無く書込みはされるのですが、これではプログラムとしてはまずいので エラーが発生したことを画面に出力してやります。
その前に、PhpSpreadsheet\Writer\BaseWriter.php のソースの 125行目の部分を覗いてみます。
125行目では fopen 関数でファイルオープンを行っていて、ファイルハンドルが取得できない場合には Exception を投げています。 この Exception を save 関数に実行で Catch してやればエラーが時の処理が書けることが分かります。
$fileHandle = $filename ? fopen($filename, $mode) : false; if ($fileHandle === false) { throw new Exception('Could not open file "' . $filename . '" for writing.'); }
それでは save 関数の実行を Try Catch で囲んでやって Catch の中でエラー時の処理を書きます。
(エラー処理といっても、単にエラーメッセージを表示するだけですが。)
なお save 関数の直前で PHP の error_reporting 関数で WARNING のエラー表示をしない様に抑止しています。
これが無いと WARNING が表示されてうるさいので。
<?php // ライブラリ読込 require '../vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Spreadsheetオブジェクト生成 $objSpreadsheet = new Spreadsheet(); // ワークシートオブジェクト $objSheet = $objSpreadsheet->getActiveSheet(); // セルにシステム時刻(Unix Time)を設定 $objSheet->setCellValue('A2', Date::PHPToExcel(time())); $objSheet->setCellValue([1, 3], Date::PHPToExcel(time())); // スタイルオブジェクト取得([A2]セル) $objStyle = $objSheet->getStyle('A2')->getNumberFormat()->setFormatCode('yyyy"年"m"月"d"日";@'); $objStyle = $objSheet->getStyle([1, 3, 1, 3])->getNumberFormat()->setFormatCode('yyyy"年"m"月"d"日";@'); // [test6-a2.xlsx]:Excel2007形式で保存する $objWriter = new Xlsx($objSpreadsheet); try { error_reporting(E_ALL & ~E_WARNING); $objWriter->save('test6-a3.xlsx'); } catch (Exception $e) { echo "ファイル書込みエラーが発生しました。:".$e->getMessage(), "\n"; } exit(); ?>
コメント