忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

PHP PhpSpreadsheet エクセルファイルの書き込み時のエラー(fopen: failed to open stream)


今回はさらに小ネタですが、XAMPP でのデバッグ時によく遭遇するエラーなのですが PhpSpreadsheet で出力されたエクセルファイルを MS-EXCEL で開いたままで 同じプログラムを実行した時には以下の様な WARNINGERROR が表示されます。

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 を投げています。 この Exceptionsave 関数に実行で 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 関数の直前で PHPerror_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();
?>











PR

コメント

コメントを書く