[2024/07/02] 【PHP】「stdClass」は「foreach」での処理ができる (No.358)
[2024/07/02] 【PHP】連想配列の様な「stdClass」の使い方について (No.357)
[2024/07/02] 【PHP】「select」タグが入力不可でも値をPOSTするには「option」タグを「disabled」に設定する (No.356)
[2023/11/22] PHP PhpSpreadsheet ワークシート上にチャート(グラフ)を作成する方法のバグについて(displayBlanksAs) (No.330)
[2023/04/20] PHP Spoutを使用してエクセル出力・ワークシートの処理の方法について・その3(あるセルに値追加) (No.326)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
以前 stdClass について以下の記事を書きましたが、 このクラスですが、連想配列的に使えるので当然 foreach の処理が行えます。
⇒【PHP】連想配列の様な「stdClass」の使い方について<?php // [stdClass]の生成 $stdObj = new stdClass; $stdObj->Val1 = 1111; $stdObj->Val2 = "2222"; $stdObj->Val3 = "CCC"; echo "<pre>"; var_dump($stdObj); // [stdClass]を[foreach]で順次取得 foreach ($stdObj as $key => $val) { echo "stdObj[$key] => ".$val."<br />"; } echo "</pre>"; ?>
これを動作させると以下の様な表示になります。object(stdClass)#1 (3) { ["Val1"]=> int(1111) ["Val2"]=> string(4) "2222" ["Val3"]=> string(3) "CCC" } stdObj[Val1] => 1111 stdObj[Val2] => 2222 stdObj[Val3] => CCC
連想配列の様にキーとその値が取得できています。
stdClass 使いようによってはいろいろできそうに思います。
PR -
最近他の人が作ったプログラムの改修作業が在ったのですが、その中で stdClass を使っていて 私は使ったことが無かったので少し調べてみたところ、連想配列の様な使い方ができることを知りました。
クラスを使う場合、普通は別のクラス宣言でクラス名を付けますが stdClass は無名クラスとして クラスオブジェクトを生成する様です。
以下のソースは stdClass を生成し2個のプロパティへの代入を行う簡単な例です。
stdClass で生成されたオブジェクトに対して、プロパティを指定する時点で、 内部的にそのプロパティが生成されるようです。<?php //[stdClass]の生成 $stdObj = new stdClass; $stdObj->stdVal1 = 1111; $stdObj->stdVal2 = "2222"; //[stdClass]の参照 echo "stdVal1=[$stdObj->stdVal1]
"; echo "stdVal2=[$stdObj->stdVal2]
"; ?>
結果は以下の表示になります。stdVal1=[1111] stdVal2=[2222]
2個のプロパティに値が設定されていることが確認できます。
尚、このソースに stdVal3 というプロパティを参照する様にしてみます。<?php //[stdClass]の生成 $stdObj = new stdClass; $stdObj->stdVal1 = 1111; $stdObj->stdVal2 = "2222"; //[stdClass]の参照 echo "stdVal1=[$stdObj->stdVal1]
"; echo "stdVal2=[$stdObj->stdVal2]
"; echo "stdVal3=[$stdObj->stdVal3]
"; ?>
この結果は以下の様に、Notice エラーが発生します。
代入設定されていないプロパティを参照することはできない様です。stdVal1=[1111] stdVal2=[2222] Notice: Undefined property: stdClass::$stdVal3 in C:\xampp\htdocs\__test\test-stdclass.php on line 9 stdVal3=[]
この stdClass ですが配列に変換することができます。 以下のソースでは stdClass オブジェクトを array オブジェクトに代入し変換しています。<?php //[stdClass]の生成 $stdObj = new stdClass; $stdObj->stdVal1 = 1111; $stdObj->stdVal2 = "2222"; //[stdClass]から[array]への変換 $arrObj = (array)$stdObj; echo "stdVal1=[".$arrObj["stdVal1"]."]
"; echo "stdVal2=[".$arrObj["stdVal2"]."]
"; ?>
上のソースから stdClass は連想配列的であることが分かります。
尚、 stdVal1 とソース上固定の記述のみしか扱えないわけでは無く、 次の例では stdVal1 の参照を変数を用いて行う方法を示します。<?php //[stdClass]の生成 $stdObj = new stdClass; $stdObj->stdVal1 = 1111; $stdObj->stdVal2 = "2222"; //[stdClass]の参照を変数で行う $key1 = "stdVal1"; $key2 = "stdVal2"; echo "stdVal1=[".$stdObj->$key1."]
"; echo "stdVal2=[".$stdObj->$key2."]
"; //中括弧で囲っても同じ echo "stdVal1=[".$stdObj->{$key1}."]
"; echo "stdVal2=[".$stdObj->{$key2}."]
"; ?>
オブジェクトのプロパティを変数で扱えると応用がいろいろ利くと思います。
PHP でシステムを組んでいると、データの中の区分値などを select タグを用いて入力します。 この区分値を入力不可にしようとして select タグの部分に disabled="disabled" とすることが多いです。
ただこの方法ですと、画面上は select ボックスは表示されるのですが POST 処理で値が渡ってきません。 以下のソースをブラウザで表示して OK を押下すると「select value = 」の所には何も表示されません。
-
PHP でシステムを組んでいると、データの中の区分値などを select タグを用いて入力します。 この区分値を入力不可にしようとして select タグの部分に disabled="disabled" とすることが多いです。
ただこの方法ですと、画面上は select ボックスは表示されるのですが POST 処理で値が渡ってきません。 以下のソースをブラウザで表示して OK を押下すると「select value = 」の所には何も表示されません。
<?php $strTestSel = isset($_POST['testsel']) ? $_POST['testsel'] : ''; ?> <!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> <h2>selcet test</h2> <span> select value = <?php echo($strTestSel); ?> </span> <form method="post" > <select name="testsel" disabled="disabled"> <option value=""></option> <option value="1">TEST1</option> <option value="2" selected="selected">TEST2</option> <option value="3">TEST3</option> </select> <br /> <input type="submit" value="OK"> </form> </body> </html>
select タグに disabled="disabled" とするのではなく option タグに選択されていないところを disabled="disabled" とし 選択されたいるところに selected="selected" とします。 上記のソースを以下の様に変更しました。
<?php $strTestSel = isset($_POST['testsel']) ? $_POST['testsel'] : ''; ?> <!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> </head> <body> <h2>selcet test</h2> <span> select value = <?php echo($strTestSel); ?> </span> <form method="post" > <select name="testsel"> <option value="" disabled="disabled"></option> <option value="1" disabled="disabled">TEST1</option> <option value="2" selected="selected">TEST2</option> <option value="3" disabled="disabled">TEST3</option> </select> <br /> <input type="submit" value="OK"> </form> </body> </html>
この様にするとドロップダウン表示をした時に selected="selected" とした option タグが通常の表示となり disabled="disabled" としたタグは選択できない灰色の表示になります。
-
以前、以下の記事などで紹介した内容ですが、PHPのバージョンを「7.4」にアップした時についでにPhpSpreadsheetを「1.25」のバージョンにしたのですが、 下のプログラムを実行するとエクセルファイルは作成されますが、チャートはエラーが出て表示されません。
⇒PHP PhpSpreadsheet ワークシート上にチャート(グラフ)を作成する方法について(PhpSpreadsheet\Chart)該当エクセルファイルを開くとエラーが表示される。
■チャートが表示されないソース
<?php // ライブラリ読込 require '../vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; use PhpOffice\PhpSpreadsheet\IOFactory; // Spreadsheetオブジェクト生成 $objSpreadsheet = new Spreadsheet(); // ワークシートオブジェクト取得 $objWorksheet = $objSpreadsheet->getActiveSheet(); // チャート用テストデータ生成 $objWorksheet->fromArray( array( array('売上' , 2016, 2017, 2018, 2019, 2020), array('商品1', 12, 15, 21, 18, 20), array('商品2', 18, 19, 23, 14, 21), //追加 array('商品3', 15, 10, 20, 12, 23), //追加 ) ); // X軸ラベルの指定 $arrCategorysDataSeries = array( new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1:$F$1', NULL, 5), // 2016 to 2020 ); // 描画データの指定 $arrDataSeriesValues = array( new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$F$2', NULL, 5), //商品1 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$3:$F$3', NULL, 5), //商品2 追加 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$4:$F$4', NULL, 5), //商品3 追加 ); // チャート・データシリーズの生成 $objSeries = new DataSeries( DataSeries::TYPE_LINECHART, // plotType NULL, // plotGrouping(DataSeries::GROUPING_STANDARD) range(0, count($arrDataSeriesValues) - 1), // plotOrder array(), // plotLabel $arrCategorysDataSeries, // plotCategory $arrDataSeriesValues // plotValues ); // プロットエリアにチャート・データシリーズに設定 $objPlotArea = new PlotArea(NULL, array($objSeries)); // チャート・タイトル生成 $objTitle = new Title('売上データ'); // チャート生成 $objChart = new Chart( 'chart1', // name $objTitle, // title NULL, // legend $objPlotArea, // plotArea TRUE, // plotVisibleOnly 0, // displayBlanksAs NULL, // xAxisLabel NULL // yAxisLabel ); // ワークシート内のチャート位置設定 $objChart->setTopLeftPosition('A6'); // 左上 $objChart->setBottomRightPosition('G18'); // 右下 // ワークシートにチャート追加 $objWorksheet->addChart($objChart); // [test-g-1-2.xlsx]:Excel2007形式で保存する $objWriter = IOFactory::createWriter($objSpreadsheet, 'Xlsx'); $objWriter->setIncludeCharts(TRUE); $objWriter->save('test-g-1-2.xlsx'); exit(); ?>
このソースでチャートを表示させるには「チャート生成:new Chart」の引数の中の「displayBlanksAs」を「0」ではなく以下のどれかを指定する必要があります。
■PhpOffice\PhpSpreadsheet\Chart\DataSeries.php 内の宣言
const EMPTY_AS_GAP = 'gap'; const EMPTY_AS_ZERO = 'zero'; const EMPTY_AS_SPAN = 'span';
よって「チャート生成:new Chart」部分のソースは以下の様にします。
// チャート生成 $objChart = new Chart( 'chart1', // name $objTitle, // title NULL, // legend $objPlotArea, // plotArea TRUE, // plotVisibleOnly DataSeries::EMPTY_AS_GAP, // displayBlanksAs NULL, // xAxisLabel NULL // yAxisLabel );
PhpSpreadsheetの記事の中え「チャート生成:new Chart」の引数の中の「displayBlanksAs」を「0」にしているものがほとんどですので、 上記の様に読み替えて下さい。
関連する記事
⇒PhpSpreadsheet ワークシート上にチャート(グラフ)を作成する方法について(PhpSpreadsheet\Chart)
⇒PhpSpreadsheet\Chart ワークシート上にチャート(Bar Chart:棒グラフ)を作成する方法について
⇒PhpSpreadsheet\Chart ワークシート上にチャート(Bar Chart:棒グラフ、複数レベルの項目軸ラベル)を作成する方法について
⇒PhpSpreadsheet\Chart 1個のチャート上に異なるタイプのグラフ(Bar Chart:棒グラフ、Line Chart:線グラフ、Area Chart:面グラフ)を作成する方法について
⇒PhpSpreadsheet\Chart エクセルシート上に複数のチャートで異なるタイプのグラフ(Bar Chart:棒グラフ、Line Chart:線グラフ、Area Chart:面グラフ)を作成する方法について
⇒PhpSpreadsheet\Chart ワークシート上に円グラフ・チャート(Pie Chart)とドーナツグラフ・チャート(Donut Chart)、及びレーダーチャート(Radar Chart)を作成する方法について
⇒PhpSpreadsheet\Chart ワークシートにチャートが存在するエクセルファイル(テンプレート)の系列データ部分を変更し別のファイルとして登録する方法について
-
今回はある「ワークシート」から行データを順次読み込み、別の「ワークシート」にあるセルにセルデータを追加し、行データ追加を行う方法について説明したいと思います。
■XLSXの読込・書込クラスを使用したワークシートのコピー・セルデータを追加
今回の処理では「XLSX読込クラス」の内部に持っているワークシートを順次取得する getSheetIterator() 関数(イテレータ)を使用します。 この関数を foreach 文で呼出すことでワークシートのオブジェクトが取得できます。
そのワークシートのオブジェクトの内部に持っている行データを順次取得する getRowIterator() 関数(イテレータ)を使用します。 この関数を foreach 文で呼出すことで行データのオブジェクトが取得できます。
その後、行データのオブジェクトがNULLの場合には、空の行データを生成し、XLSX書込クラスへの行追加を行います。 NULLではない場合にはそのままXLSX書込クラスへの行追加を行います。
その行データからセルデータオブジェクト配列を取得し、その配列からを順次カラムデータとして取り出すために array_map() 関数で行います。 結果としてデータの配列が生成されます。
生成されたデータの配列から新規の追加用行データオブジェクトを作成します。 行データオブジェクトの setCellAtIndex($cell, $Index) 関数でセルデータの設定(置き換え)ができます。
<?php require '../vendor/autoload.php'; use Box\Spout\Writer\Common\Creator\WriterEntityFactory; use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; // XLSX読込クラス生成 $strReadFile = 'test7-1.xlsx'; $reader = ReaderEntityFactory::createReaderFromFile($strReadFile); // 空行の読み込み許可 $reader->setShouldPreserveEmptyRows(true); // 読み込み $reader->open($strReadFile); // XLSX書込クラス生成 $writer = WriterEntityFactory::createXLSXWriter(); $writer->openToFile('test7-1-New.xlsx'); // 全てのワークシートを取得 foreach($reader->getSheetIterator() as $sheet) { // ワークシートの全行を取得 foreach($sheet->getRowIterator() as $row) { // [$row]がNULLの場合を考慮し、セル値の配列生成 $cellValues = array_map(function($cell) { return $cell->getValue(); }, $row->getCells()); // セル値の配列から行データ生成 $newRow = WriterEntityFactory::createRowFromArray($cellValues); // 新規追加するセルデータ生成 $newCell = WriterEntityFactory::createCell('A001'); // セルデータ設定 $newRow->setCellAtIndex($newCell, 5); // 書込みへの追加 $writer->addRow($newRow); } } // XLSX読込・書込クラスクローズ $reader->close(); $writer->close(); ?>
出力されたエクセルファイルを見てみると以下の様になります。
左側が読込んだエクセルで、右側が新たに書込んだエクセルです。 6番目のセルに「'A001'」が設定されたことが分かります。
■XLSXの読込・書込クラスを使用したワークシートのコピー・データ行を指定してセルデータを追加
ワークシートのオブジェクトの内部に持っている行データを順次取得する getRowIterator() 関数(イテレータ)ではキーとして、行Indexを返すことができます。 この行Indexを判定すれば、意図した行にのみ処理が可能となります。<?php require '../vendor/autoload.php'; use Box\Spout\Writer\Common\Creator\WriterEntityFactory; use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; // XLSX読込クラス生成 $strReadFile = 'test7-1.xlsx'; $reader = ReaderEntityFactory::createReaderFromFile($strReadFile); // 空行の読み込み許可 $reader->setShouldPreserveEmptyRows(true); // 読み込み $reader->open($strReadFile); // XLSX書込クラス生成 $writer = WriterEntityFactory::createXLSXWriter(); $writer->openToFile('test7-2-New.xlsx'); // 全てのワークシートを取得 foreach($reader->getSheetIterator() as $sheet) { // ワークシートの全行を取得 foreach ($sheet->getRowIterator() as $rowIndex => $row) { // [$row]がNULLの場合を考慮し、セル値の配列生成 $cellValues = array_map(function($cell) { return $cell->getValue(); }, $row->getCells()); // セル値の配列から行データ生成 $newRow = WriterEntityFactory::createRowFromArray($cellValues); // 行が2行目と5行目のみ処理 if ($rowIndex == 2 || $rowIndex == 5) { $cell = WriterEntityFactory::createCell('A001'); $newRow->setCellAtIndex($cell, 5); } // 書込みへの追加 $writer->addRow($newRow); } } // XLSX読込・書込クラスクローズ $reader->close(); $writer->close(); ?>
出力されたエクセルファイルを見てみると以下の様になります。 2行目と5行目のみにセルデータが設定されています。