🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

Q&A

解決済

1回答

1223閲覧

laravelのコマンドCSV読込計算

yoheiiii

総合スコア91

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

0グッド

0クリップ

投稿2021/01/28 06:19

編集2021/01/28 10:28

環境:Windows10,XAMPP,HeidiSQL

laravelでapp>Console>Commandsに
CSV読込計算のファイルを作っております。

【対象CSVデータ】
イメージ説明

コマンドプロンプトでphp artisan command:output5
を行うと下記のように出力されます。
【結果】
イメージ説明

2021年の合計が上手くいきません。
いかがすればよいかご教授頂けないでしょうか?

【現状コード】

<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Storage; use File; class Output5 extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'command:output5'; /** * The console command description. * * @var string */ protected $description = '課題05'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return int */ public function handle() { $filename = storage_path('app/public/study05.csv'); $fp = fopen($filename, 'r'); if ($fp === false) { echo "ファイルオープン時に失敗したので処理終了します。".PHP_EOL; exit; } $is_error = false; $break_key_year = ''; $break_key_month = ''; $i=0; $nyukin = 0; // 入金 $syukin = 0; // 出金 while ($line = fgets($fp)) { $i++; // ファイル読込終了判定 if (feof($fp)) { break; } // ファイル読込エラー判定 if ($line === false) { echo "ファイル読込時に失敗したので処理終了します。".PHP_EOL; $is_error = true; break; } // カンマ分割 $work_field = explode(',', $line); // 日付分割 $work_date = explode('/', $work_field[0]); $stock_nyukin[] = $work_field[1]; $total_nyukin = array_sum($stock_nyukin); $stock_syukin[] = $work_field[2]; $total_syukin = array_sum($stock_syukin); if (($break_key_year != $work_date[0]) || ($break_key_month != $work_date[1])) { if ($i != 1) { echo $break_key_year.'年'.$break_key_month.'月'.'入金集計:'.$nyukin.'、出金合計:'.$syukin.PHP_EOL; $stock_year_nyukin[] = $nyukin; $year_nyukin = array_sum($stock_year_nyukin); $stock_year_syukin[] = $syukin; $year_syukin = array_sum($stock_year_syukin); $nyukin = 0; $syukin = 0; if(($break_key_year != $work_date[0])){ echo '---------------------------------------------------'.PHP_EOL; echo $break_key_year.'年:'.'入金合計:'.$year_nyukin.'出金合計:'.$year_syukin.PHP_EOL; echo PHP_EOL; } // $year_nyukin =0; // $year_syukin =0; } $break_key_year = $work_date[0]; $break_key_month = $work_date[1]; } $w_nyukin = trim($work_field[1]); $w_syukin = trim($work_field[2]); if(empty($w_nyukin) && empty($w_syukin)){ echo $i.'行目のデータがありませんのでデータをスキップします。'.PHP_EOL; continue; } //通常処理 if (empty($w_nyukin)) { $syukin += $w_syukin; } else { $nyukin += $w_nyukin; } } echo $break_key_year.'年'.$break_key_month.'月'.'入金集計:'.$nyukin.'、出金合計:'.$syukin.PHP_EOL; echo '---------------------------------------------------'.PHP_EOL; echo $break_key_year.'年:'.'入金合計:'.$year_nyukin.'出金合計:'.$year_syukin.PHP_EOL; echo PHP_EOL; echo '========================================='.PHP_EOL; echo 'トータル:'.'入金合計:'.$total_nyukin.'、出金合計:'.$total_syukin.PHP_EOL; fclose($fp); if ($i == 0) { echo "指定されたファイルは空ファイルでした。".PHP_EOL; } return 0; } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1行づつデバッグすれば気づけると思いますが、
2021/1のデータを読み込み、work_dateに代入した時点での値は以下のようになります。

$work_date[0] = 2021 $work_date[1] = 1 $break_key_year = 2020 $break_key_month = 12

合計出力は、月の入出金情報を出力してから行うとうまくいくと思います。

PHP

1 // カンマ分割 2 $work_field = explode(',', $line); 3 4 // 日付分割 5 $work_date = explode('/', $work_field[0]); 6 7 $a[] = $work_field[1]; 8 $b = array_sum($a); 9 10 $c[] = $work_field[2]; 11 $d = array_sum($c); 12 13 // 月か年が違う場合、月の入出金情報を出力する 14 if (($break_key_year != $work_date[0]) || ($break_key_month != $work_date[1]) 15 { 16 // ただし1行目の場合は出力しない 17 if ($i != 1) { 18 echo $break_key_year.'年'.$break_key_month.'月'.'入金集計:'.$nyukin.'、出金合計:'.$syukin.PHP_EOL; 19 $nyukin = 0; 20 $syukin = 0; 21 22 // 2020 != 2021など、年が変わっていたらさらに合計を出力する 23 if(($break_key_year != $work_date[0])){ 24 echo '---------------------------------------------------'.PHP_EOL; 25 echo $break_key_year.'年:'.'入金合計:'.$b.'出金合計:'.$d.PHP_EOL; 26 echo PHP_EOL; 27 $b = 0; 28 $d = 0; 29 } 30 } 31 $break_key_year = $work_date[0]; 32 $break_key_month = $work_date[1]; 33 } 34
追記

ただ合計が駄目です。

$bと$dはただの合計なので別で年別の合計作る感じでしょうか?

そうですね、yoheiiiiさんのプログラムの方針のまま直すのであれば
全体の合計と、年次の合計は別で変数を持ったほうがわかりやすいと思います。
それと$a,$b,$dはもっとわかりやすい名前にしたほうが良いです。

ただし、これはあくまでもyoheiiiiさんのプログラムを直すならという話なので、
「入出金計を出力するプログラム」の正解ではありません。

追記2

元のプログラムのわかりにくいところは、
いろんな箇所で合計の追加処理をしているところです。
処理の流れはシンプルに以下の通りで、それをプログラムに置き換えるだけで
結果は求まります。
プログラムを書くための技術は元のプログラムで満たせているので、
CSVから入出金情報を出力するために何をするべきかが整理できればすぐできる内容だと思います。

while(ファイルの最後まで) 1行読む ↓ 読み込み済み月が違っていたら月入金、月出金を出力して月入金、月出金を初期化 ↓ 読み込み済み年が違っていたら年入金、年出金を出力して年入金、年出金を初期化 ↓ 読み込み済み年、読み込み済み月を更新 月入金、月出金、年入金、年出金、総入金、総出金を加算 end while 変数に残っている月入金、月出金を出力 変数に残っている年入金、年出金を出力 総入金、総出金を出力

学校かプログラミングスクールかはわかりませんが、
課題らしいので何をするべきかの整理も課題の一環で、
むしろ整理が自力でできることのほうが重要な気がします…

投稿2021/01/28 06:56

編集2021/01/30 05:09
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoheiiii

2021/01/28 07:38

ご回答ありがとうございます。 2020年12月が2020年側に行きました! ただ合計が駄目です。 $bと$dはただの合計なので別で年別の合計作る感じでしょうか?
yoheiiii

2021/01/28 08:10

現状、下記で2020年の合計は出来ましたが、2021年がトータルになってしまいます。 if (($break_key_year != $work_date[0]) || ($break_key_month != $work_date[1])) { if ($i != 1) { echo $break_key_year.'年'.$break_key_month.'月'.'入金集計:'.$nyukin.'、出金合計:'.$syukin.PHP_EOL; $e[] = $nyukin; $f = array_sum($e); $g[] = $syukin; $h = array_sum($g); $nyukin = 0; $syukin = 0; if(($break_key_year != $work_date[0])){ echo '---------------------------------------------------'.PHP_EOL; echo $break_key_year.'年:'.'入金合計:'.$f.'出金合計:'.$h.PHP_EOL; echo PHP_EOL; $f = 0; $h = 0; } } $break_key_year = $work_date[0]; $break_key_month = $work_date[1]; }
yoheiiii

2021/01/28 09:24

ちなみに上記で2020年の合計が出ているので、2021年もそのまま出ると考えているのですが、 何が間違っているのでしょうか?
退会済みユーザー

退会済みユーザー

2021/01/28 09:33

技術的な課題はもうないと思いますので、CSV1行ごとの処理の流れをしっかり追ってください。思っていた動きと違うのであれば、例えば0で初期化忘れや、ループの最後の行読み取ったあとに計算しそびれたデータがあるなどが考えられます。それと長くなっても変数名は用途がわかるようにつけたほうが良いです。
yoheiiii

2021/01/28 09:34

承知しました。やってみます! ご教授ありがとうございました。
退会済みユーザー

退会済みユーザー

2021/01/28 09:40

回答のコメントだとソースが読みにくいので、ソース修正後にさらに質問が出た場合は質問に追記するといいと思います。流れ追ってみてもわからなければ質問に追記してください。
yoheiiii

2021/01/28 10:30

合算されているので、初期化だと思っているのですが、未だわかっておりません。 質問更新致しました。ご教授頂けないでしょうか?
退会済みユーザー

退会済みユーザー

2021/01/28 12:32 編集

素朴な疑問なんですが、$stock_nyukin[] = $work_field[1];ここなんで配列に入れてるんですか?totalは直接追加してもよいと思いますが…よくわからずやっているならあるべきプログラムの動作のフローチャートを書くなどして頭整理したほうが良いです。
yoheiiii

2021/01/29 06:37

array_sum()は、パラメーター1が配列であり、文字列が指定されていることを想定しています。 とエラーが出てきてしまうので配列にしました。
yoheiiii

2021/01/31 04:25

長々とお時間申し訳ございませんでした。 流れはだいぶわかってきたので おっしゃる通り再度頭整理致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問