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

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

詳細はこちら
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

1回答

5581閲覧

PhpSpreadsheetで複数シートに書き込まれるデータの順番が狂ってしまう

avantgarden

総合スコア121

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2019/10/24 01:55

編集2019/10/24 01:57

複数の注文データをエクセルに出力してダウンロードする機能を実装しているのですが、複数のシートに書き込まれる注文データの順番が狂ってしまいます。

エクセル生成部分のコードは下記の通りです。
処理の順番としては、注文一覧画面で複数の注文データにチェックを付けて、ajaxでpost送信→下記の処理でエクセルを生成し、base64_encodeしてjsonを返す、という流れにしています。

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx; $reader->setReadDataOnly(false); $spreadsheet = $reader->load(storage_path('excel/order_template.xlsx')); // $order_number_arrayは注文一覧でチェックを入れてpost送信した複数の注文番号の配列 $order_number_array = $request->post('order_number'); foreach($order_number_array as $key => $order_number) { // ループの2回目以降はシートを複製 if ($key > 0) { $sheet_num = $key + 1; $clone_spreadsheet = clone $spreadsheet->getSheetByName('Table 1'); $clone_spreadsheet->setTitle('Table '.$sheet_num); $spreadsheet->addSheet($clone_spreadsheet); } $sheet = $spreadsheet->getActiveSheet(); $orders = Order::where('order_number', $order_number)->get(); // 注文情報をエクセルへ埋め込み foreach ($orders as $key1 => $order) { // 注文情報 $sheet->setCellValue('D5', $order->order_number); $sheet->setCellValue('D6', $order->purchase_order_number); $sheet->setCellValue('D8', $order->customer_name); $sheet->setCellValue('D9', $order->customer_address); // 商品情報 $row_num = 12 + $key1; $sheet->setCellValue('A'.$row_num, $order->jan_code); $sheet->setCellValue('D'.$row_num, $order->product_name); $sheet->setCellValue('N'.$row_num, $order->order_amount); } } ob_start(); $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx'); $writer->save('php://output'); $xlsxData = ob_get_contents(); ob_end_clean(); return response()->json([ 'status' => \Illuminate\Http\Response::HTTP_OK, 'file' => 'data:application/vnd.ms-excel;base64,' . base64_encode($xlsxData), 'datetime' => date('mdHis') ]);

この結果、エクセルには「Table 1」「Table 2」…のシートができていますが、例えば、上記の$order_number_arrayが

$order_number_array = [ [0] => 'order_number1', [1] => 'order_number2', [2] => 'order_number3', [3] => 'order_number4', [4] => 'order_number5', ];

だとすると、

Table1 にorder_number5のデータ
Table2 にorder_number1のデータ
Table3 にorder_number2のデータ
Table4 にorder_number3のデータ
Table5 にorder_number4のデータ

が入ってしまいます。

foreach($order_number_array as $key => $order_number) { }

の最初のループ時に

var_dump($sheet); var_dump($orders);

を確認すると、$sheetの出力内容には「Table1」という文字列があり、$ordersの出力内容は、最初にチェックを入れた注文データになっているのですが、なぜか、そのデータは「Table 2」に入ってしまい、「Table 1」には最後にチェックを入れたデータが入ってしまいます。

ちょっと原因が分からず、ご教示いただければ幸いです。

バージョンについては、PHP7.2、Laravel5.6、エクセル出力にはPhpSpreadsheetを使っています。

よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

PHP

1 // ループの2回目以降はシートを複製 2 if ($key > 0) { 3 $sheet_num = $key + 1; 4 $clone_spreadsheet = clone $spreadsheet->getSheetByName('Table 1'); 5 $clone_spreadsheet->setTitle('Table '.$sheet_num); 6 $spreadsheet->addSheet($clone_spreadsheet); 7 } 8 $sheet = $spreadsheet->getActiveSheet();

$key > 0 のとき、新しいシートを追加していますが、addSheet したシートが ActiveSheet になる、なんて挙動は明示されてないはずです。ですから次の getActiveSheet() の結果が意図したとおりになるとは限らないのでは?

PHP

1 if ($key > 0) { 2 $sheet_num = $key + 1; 3 $clone_spreadsheet = clone $spreadsheet->getSheetByName('Table 1'); 4 $clone_spreadsheet->setTitle('Table '.$sheet_num); 5 $spreadsheet->addSheet($clone_spreadsheet); 6 } 7 $sheet = $spreadsheet->getSheetByName('Table '.$key + 1);

としたらどうでしょうか。

投稿2019/10/24 08:59

tacsheaven

総合スコア13703

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

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

avantgarden

2019/10/24 22:12

ありがとうございます。 たしかに、追加したシートをActiveSheetにする所がないですね。。 ご指摘の内容を元に、 if ($key > 0) { $sheet_num = $key + 1; $clone_spreadsheet = clone $spreadsheet->getSheetByName('Table 1'); $clone_spreadsheet->setTitle('Table '.$sheet_num); $spreadsheet->addSheet($clone_spreadsheet); } else { $sheet_num = 1; } $sheet = $spreadsheet->getSheetByName('Table '.$sheet_num); としたところ、順番通りにシートが出力されました! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問