-
今回は日付処理のライブラリである Carbon の使い方について説明したいと思います。
Carbon は Laravel でも使用されていますので、割と認知されていると思います。
では先ずインストールについて説明していきます。 ここでのインストールは Composer というパッケージ管理ソフトを使いますので、 以前 PhpSpreadsheet のインストールで説明していますので、以下の記事を参照して下さい。
⇒PHP PhpSpreadsheet のインストールについて(XAMPPでのPhpSpreadsheetのインストールその1:composer)
⇒PHP PhpSpreadsheet のインストールについて(XAMPPでのPhpSpreadsheetのインストールその2:composerでPhpSpreadsheet)
■Composer によるインストール
XAMPP でのインストールを想定していますので「Windwosコマンドプロンプト(管理者権限)」を起動して以下のコマンドを実行します。
>composer require nesbot/carbon
このコマンドの後で以下の様な表示になります。
C:\xampp\htdocs>composer require nesbot/carbon Info from https://repo.packagist.org: #StandWithUkraine Using version ^2.62 for nesbot/carbon ./composer.json has been updated Running composer update nesbot/carbon Loading composer repositories with package information Updating dependencies Lock file operations: 5 installs, 0 updates, 0 removals - Locking nesbot/carbon (2.62.1) - Locking symfony/deprecation-contracts (v2.5.2) - Locking symfony/polyfill-php80 (v1.26.0) - Locking symfony/translation (v5.4.14) - Locking symfony/translation-contracts (v2.5.2) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 5 installs, 0 updates, 0 removals - Downloading symfony/translation (v5.4.14) 0/1 [>---------------------------] 0% 1/1 [============================] 100% - Installing symfony/translation-contracts (v2.5.2): Extracting archive - Installing symfony/polyfill-php80 (v1.26.0): Extracting archive - Installing symfony/deprecation-contracts (v2.5.2): Extracting archive - Installing symfony/translation (v5.4.14): Extracting archive - Installing nesbot/carbon (2.62.1): Extracting archive 0/5 [>---------------------------] 0% 2/5 [===========>----------------] 40% 3/5 [================>-----------] 60% 4/5 [======================>-----] 80% 5/5 [============================] 100% 3 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating autoload files 8 packages you are using are looking for funding. Use the `composer fund` command to find out more! No security vulnerability advisories found
■Carbon のインストール確認
Carbon のインストールは XAMPP のドキュメントフォルダの中の「composer.json」内容を確認すれば分かります。
私のPCの中の設定値の例ですが Carbon のバージョン2.62がインストールされたことが分かります。
(phpspreadsheet は既にインストール済みのため存在しています){ "require": { "phpoffice/phpspreadsheet": "^1.25", "nesbot/carbon": "^2.62" }, "config": { "platform": { "php": "7.4.32" } } }
■Carbon による簡単な例
以下に簡単な例を示します。
このソースは XAMPP のドキュメントフォルダ直下に置きますので、 Carbon ライブラリ読込は vendor/autoload.php となります。
あとはライブラリ使用宣言をして、Carbon の現在日付の関数をコールします。<?php // ライブラリ読込 require 'vendor/autoload.php'; // ライブラリ使用宣言 use Carbon\Carbon; echo "Now: ".Carbon::now(); ?>
ブラウザの結果は以下の様に表示されます。
Now: 2022-11-07 08:44:04
PR -
今回はさらに小ネタですが、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(); ?>
-
今回はさらに小ネタですが、以下の記事では、セルに PHP のUNIT-TIMEデータを日付型データとして設定し、日付の書式で表示させる方法について説明しました。
この時のセルの書込み位置指定で従来の方法で "A2" としていましたが、最近のバージョンの PhpSpreadsheet では「列No, 行No」と配列での指定が可能になった様です。
⇒PHP PhpSpreadsheet エクセルのワークシートのセルに日付型データの設定と、日付スタイル設定について(PHPToExcel, setFormatCode)
そこで、XAMPP のPHPバージョンを「7.4.32」にアップしたのに伴って、PhpSpreadsheet のバージョンアップを行います。
まずはWindowsのコマンドプロンプトから以下のコマンドを実行します。C:\xampp\htdocs>composer config platform.php 7.4.32
「C:\xampp\htdocs\composer.json」ファイルの内容が以下の様になります。 phpspreadsheet のバージョンはそのままです。
{ "require": { "phpoffice/phpspreadsheet": "^1.8" }, "config": { "platform": { "php": "7.4.32" } } }
composer require phpoffice/phpspreadsheet
このコマンドで実行したのですが、いろいろエラーが表示されたので、「C:\xampp\htdocs\vendor」フォルダを別のものにして 「vendor」が存在しない状態で再度、上記のコマンドを実行しました。
(ちょっと強引な感じですが、更新方法が良くわからなかったので。)
「7-ZIP」という圧縮・解凍ツールがインストールされている場合は、取り敢えずアンインストールします。
(phpspreadsheet 取込の composer でファイル解凍時?にエラーになります。)
再度、コマンドを実行したら、新しく「vendor」以下が構築された様です。C:\xampp\htdocs>composer require phpoffice/phpspreadsheet Info from https://repo.packagist.org: #StandWithUkraine Using version ^1.25 for phpoffice/phpspreadsheet ./composer.json has been updated Running composer update phpoffice/phpspreadsheet Loading composer repositories with package information Updating dependencies Nothing to modify in lock file Installing dependencies from lock file (including require-dev) Package operations: 11 installs, 0 updates, 0 removals 0 [>---------------------------] 0 [->--------------------------] - Installing myclabs/php-enum (1.8.4): Extracting archive - Installing psr/simple-cache (1.0.1): Extracting archive - Installing psr/http-message (1.0.1): Extracting archive - Installing psr/http-factory (1.0.1): Extracting archive - Installing psr/http-client (1.0.1): Extracting archive - Installing markbaker/matrix (3.0.0): Extracting archive - Installing markbaker/complex (3.0.1): Extracting archive - Installing symfony/polyfill-mbstring (v1.26.0): Extracting archive - Installing maennchen/zipstream-php (2.2.1): Extracting archive - Installing ezyang/htmlpurifier (v4.16.0): Extracting archive - Installing phpoffice/phpspreadsheet (1.25.2): Extracting archive 0/11 [>---------------------------] 0% 9/11 [======================>-----] 81% 10/11 [=========================>--] 90% 11/11 [============================] 100% Generating autoload files 3 packages you are using are looking for funding. Use the `composer fund` command to find out more! No security vulnerability advisories found
■「setCellValue、getStyle」のセル指定に配列を使用
セルに座標を設定する場合、従来は "A2" の様に列のアルファベットと行Noで指定していましたが、 ここに [1, 2] の様に [列No, 行No] の指定が出来る様になりました。
なお、スタイルオブジェクトを取得する getStyle の場合は [左上列No, 左上行No, 右下列No, 右下行No] の範囲指定で行います。
以下に簡単な例を示します。 [A2] および [A3] セルに現在時刻を設定し、そのセルの書式スタイルを日付表示の設定で行っています。
<?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(); ?>
出力されたエクセルファイルを見てみると以下の様になります。[A]列の幅は便宜上広くして表示しました。
-
今回は小ネタですが、セルに PHP のUNIT-TIMEデータを日付型データとして設定し、日付の書式で表示させる方法について説明したいと思います。■「PHPToExcel」を使ったセルへの日付型データの設定
セルに日付型データを設定するには Date クラスの PHPToExcel メソッドで PHP の日付データ(UNIX-TIME) をエクセルの date/time 値に変換したものを設定します。 PHPToExcel メソッドは static な関数なので Date::PHPToExcel と直接書くことができます。
以下に簡単な例を示します。 [A2] セルに現在時刻を設定し、そのセルの書式スタイルを日付表示の設定で行っています。
<?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())); // スタイルオブジェクト取得([A2]セル) $objStyle = $objSheet->getStyle('A2')->getNumberFormat()->setFormatCode('yyyy"年"m"月"d"日";@'); // [test6-a2.xlsx]:Excel2007形式で保存する $objWriter = new Xlsx($objSpreadsheet); $objWriter->save('test6-a2.xlsx'); exit(); ?>
出力されたエクセルファイルを見てみると以下の様になります。[A]列の幅は便宜上広くして表示しました。
-
エクセルのワークシートのセルにスタイルを設定する説明は以下の記事で行いましたが、今回は複数セルに対するスタイル設定について説明したいと思います。
PHP PhpSpreadsheet エクセルのワークシートのセルのスタイル設定について
■「applyFromArray」を使ったセルのスタイル設定
ワークシートオブジェクト から取得した スタイルオブジェクト の applyFromArray() メソッドで設定するスタイルを array() で与えることが出来ます。
以下に簡単な例を示します。 [A1:D3] のセル範囲の周りに赤色のボーダーで囲む設定を行っています。
<?php // ライブラリ読込 require '../vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\Style; use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Spreadsheetオブジェクト生成 $objSpreadsheet = new Spreadsheet(); // ワークシートオブジェクト $objSheet = $objSpreadsheet->getActiveSheet(); // スタイル設定値array $styleArray = [ 'borders' => [ 'outline' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK, 'color' => ['argb' => 'FFFF0000'], ], ], ]; // [A1:D3]のスタイル設定 $objSheet->getStyle('A1:D3')->applyFromArray($styleArray); // [test6-a0.xlsx]:Excel2007形式で保存する $objWriter = new Xlsx($objSpreadsheet); $objWriter->save('test6-a0.xlsx'); exit(); ?>
出力されたエクセルファイルを見てみると以下の様になります。
■「applyFromArray」と「duplicateStyle」を使ったセルのスタイル設定
上記は スタイルオブジェクト の applyFromArray() メソッドでスタイルを設定する処理でしたが、 指定したセル範囲を一つのセルと考えてのスタイルを設定していました。
今度は、指定したセル範囲の全てのセルに対して同じスタイルを設定する方法を示します。
以下の例は スタイルクラス:Style() を生成しその スタイルオブジェクト に applyFromArray() メソッドでスタイルを設定しておきます。
この スタイルオブジェクト を ワークシートオブジェクト の duplicateStyle() メソッドで指定範囲の各セルへのスタイル設定が一括で行えます。
各セルには「文字フォント」「アライメント(水平位置)」「ボーダー(全周枠)」「書式設定(数値)」「ぬりつぶし(色)」のスタイルを設定します。
<?php // ライブラリ読込 require '../vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\Style; use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Style\Font; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Spreadsheetオブジェクト生成 $objSpreadsheet = new Spreadsheet(); // ワークシートオブジェクト $objSheet = $objSpreadsheet->getActiveSheet(); // 配列データ $arrData = array( array(100, -1100, 12000, 130000), // マイナス値もいれる array(200, 2100, 22000, -230000), array(300, 3100, -32000, 330000), ); // [A1:D3]セルに配列データ設定 $objSheet->fromArray( $arrData, // 配列データ NULL, // 配列データの中でセルに設定しないNULL値の指定 'A1' // 左上座標(デフォルト:"A1") ); // 全部のスタイルの定義 $objStyle = new Style(); $objStyle->applyFromArray( array( 'font' => array( 'name' => 'Arial', 'bold' => TRUE, 'italic' => FALSE, 'underline' => Font::UNDERLINE_DOUBLE, 'strikethrough' => FALSE, ), 'alignment' => array( 'horizontal' => Alignment::HORIZONTAL_RIGHT ), 'borders' => array( 'top' => array( 'borderStyle' => Border::BORDER_THIN, ), 'bottom' => array( 'borderStyle' => Border::BORDER_THIN, ), 'left' => array( 'borderStyle' => Border::BORDER_THIN, ), 'right' => array( 'borderStyle' => Border::BORDER_THIN, ) ), 'numberFormat' => array( 'formatCode' => '#,##0;[Red]#,##0', // マイナスは赤色 ), 'fill' => array( 'fillType' => Fill::FILL_SOLID, 'startColor' => array( 'argb' => '00FFFF80' ) ) ) ); // セル範囲指定でのスタイル設定 $objSheet->duplicateStyle($objStyle, 'A1:D3'); // [test6-a1.xlsx]:Excel2007形式で保存する $objWriter = new Xlsx($objSpreadsheet); $objWriter->save('test6-a1.xlsx'); exit(); ?>
出力されたエクセルファイルを見てみると以下の様になります。