質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

90.35%

  • PHP

    22389questions

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

  • Excel

    1742questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。

PHPExcelでexcelへの書き込み

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,320

ao_love

score 420

お世話になっております。
PHPExcelによるエクセルDLについてお尋ねです。

前提・実現したいこと

PHPExcelでテンプレート読み込み

DBから取得したデータを書き込み

書き込んだエクセルのDL

書き込みの量としては最大でも20行15列程度。
3行15列程度でテストしています。

発生している問題・エラーメッセージ

ローカルのxammpp,サーバー1では問題なく行えていたDLがサーバー2ではできなくなった。
500サーバーエラーが発生し、PHPのエラーなどの表示は出ません。

DLではなく出力する方法でも同じです。

該当のソースコード

//ディレクトリ設定
$dir = '.';

//ライブラリ読み込み
require_once $dir . '/Classes/PHPExcel.php';
require_once $dir . '/Classes/PHPExcel/IOFactory.php';

//テンプレート読み込み
$file   = $dir.'/temp.xlsx';//テンプレート名
$reader = PHPExcel_IOFactory::createReader('Excel2007');
$book   = $reader->load($file);

// $_SESSIONから読み込み
session_start();
$term_id   = $_SESSION["term_id"];
$term_name = $_SESSION["term_name"];
$ticket    = $_SESSION["ticket"];

// シート名をDBから取得して設定
$sql   = "SELECT year,month,place,first_date FROM term ORDER BY id DESC LIMIT 1";
$res   = $conDB->pdoQuery($sql);
$year  = $res[0]['year'];
$month = $res[0]['month'];
$place = $res[0]['place'];
$first = $res[0]['first_date'];

// 前売テーブルから最新期間の情報を取得
$sql = "SELECT * FROM advance WHERE term_id = ".$term_id;
$res = $conDB->pdoQuery($sql);
foreach ($res as $value) {
    $ad_arr[$value["ticket_id"]] = $value;
}


//シートを設定する
$book->setActiveSheetIndex(0);//一番最初のシートを選択(2枚目なら(1))
$sheet = $book->getActiveSheet();//選択シートにアクセスを開始
$sheet->setTitle( $year.'年'.$month.'月' ); //シート名を設定、変数OK


/************************
 * シート書き込み内容設定
 ***********************/
// 現在の状況の書き込み
$col = 3;
foreach ($ad_arr as $tid=>$value){
    $sheet->setCellValueByColumnAndRow(0,$col,$tid);
    $sheet->setCellValueByColumnAndRow(1,$col,$ticket[$tid]["name"]);
    $sheet->setCellValueByColumnAndRow(2,$col,$value["1st"]);
    $sheet->setCellValueByColumnAndRow(3,$col,$value["2nd"]);
    $sheet->setCellValueByColumnAndRow(4,$col,$value["3rd"]);
    $sheet->setCellValueByColumnAndRow(5,$col,$value["4th"]);
    $sheet->setCellValueByColumnAndRow(6,$col,$value["5th"]);
    $sheet->setCellValueByColumnAndRow(7,$col,$value["6th"]);
    $sheet->setCellValueByColumnAndRow(8,$col,$value["7th"]);
    $sheet->setCellValueByColumnAndRow(9,$col,$value["8th"]);
    $sheet->setCellValueByColumnAndRow(10,$col,$value["9th"]);
    $sheet->setCellValueByColumnAndRow(11,$col,$value["10th"]);
    $sheet->setCellValueByColumnAndRow(12,$col,$value["11th"]);
    $sheet->setCellValueByColumnAndRow(13,$col,$value["12th"]);
    $sheet->setCellValueByColumnAndRow(14,$col,$value["13th"]);
    $sheet->setCellValueByColumnAndRow(15,$col,$value["14th"]);
    $sheet->setCellValueByColumnAndRow(16,$col,$value["15th"]);

    $col++;
}

// 日付の書き込み
for ($i=0; $i < 15; $i++) {
    $date = $month."月".($first+$i)."日";
    $sheet->setCellValueByColumnAndRow($i+2,2,$date);
}

/**************
 * 出力処理
 **************/
//出力ファイル名の設定(拡張子は出力形式に合わせて変える)
$output = 'output_'.$year.'_'.$month.'.xlsx';

// Excel2007形式(xlsx)で出力する
$writer = PHPExcel_IOFactory::createWriter($book, 'Excel2007');
$writer->save($output);

試したこと

とりあえずは問題の切り分けということでソースを細切れにして実行してみたところ
最後の$writer->save('php://output');があるとエラーになります。
その直前まではvar_dump等で変数の出力も問題なく行えています。

以下の環境の通り、実行したいサーバー2はメモリがかなり小さいので対策としてテンプレート読み込みの前に

$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings = array('dir' => '/tmp');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);


を挿入して実行してみましたが状況は変わりませんでした。
読み込みの時点では処理は止まらず、
Fatal error: Allowed memory size of ~~の様なエラーもでていません。

$writer->save($output);
exit();


にもしてみましたがやはり同様でした。

補足情報(言語/FW/ツール等のバージョンなど)

各環境は以下です

xampp(DL・出力できる)

XAMPP:for Windows 5.6.23
Apache:2.4.17
PHP:5.6.23
mysql:Ver 15.1 Distrib 10.1.13-MariaDB 

 サーバー1(DL・出力できる)

OS:Turbolinux Appliance Server 3.0
Apache:2.2.6
PHP:5.2.4
mysql:5.0.45

 サーバー2(DLも出力もできない)

OS:CentOS7.2
Apache:2.4.6
PHP:7.0.12
mysql:5.6.34

GMOALTUSのミニサーバーなので1コア1CPUのメモリ512MB

 追記

seastar3さんからのご回答で肝心のDL仕様のコードを載せていないことに気づきましたので追記させていただきます。

// DLさせるときはこちらを使用
// header('Content-Type: application/force-download'); #1
// header('Content-Type: application/vnd.ms-excel'); #2
header('Content-Type: application/octet-stream');
ob_end_clean();//バッファのゴミ捨て
header('Content-Disposition: attachment;filename='.$output);
header('Cache-Control: max-age=0');

$writer = PHPExcel_IOFactory::createWriter($book, "Excel2007");
$writer->save('php://output');
exit();


Content-Typeについてはコメントアウトしてあるものも含めてすべて試してみましたがすべて同じ結果でした。
動きとしては他ページのボタンからtarget="_blrank"でリンクしています。
$writer->save('php://output');
をコメントアウトするとシート名の正しい空のエクセルが出力されます…。

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

check解決した方法

+1

PHPのバージョンの影響でした。
PHP7以降ではloopswitch内以外でbreakを利用するとエラーになるため。

Classes/PHPExcel/Calculation/Functions.php
の581行目にある
break;
のコメントアウトで期待の結果が得られました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

$writer->save('php://output');があるとエラーになります。 

具体的にどんなエラーなのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/02 11:25

    エラーは500メッセージです。
    PHPのエラーをはいてくれれば対処しやすいのですが><
    ちなみにchromeだと【一時的に停止しているか、新しいウェブアドレスに移動した可能性があります】
    Firefoxだと【ファイルが見つかりませんでした】というメッセージです

    キャンセル

0

バッファのクリアが必要なのではないでしょうか。

ob_end_clean(); 

をsave()メソッドを使う前に仕込んでみるといけるかも知れません。

私の体験ですが、PHPExcelを活用して
Excelワークシートに保存したファイルのダウンロード操作で、

readfile(Excelブック名, FILE_BINARY);

を記述する前に

ob_end_clean(); 

と入れるまで、破損したファイルが保存されて苦労したことがあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/02 11:23

    ありがとうございます。
    私も以前そのトラップにハマって、ob_end_clean(); を追記したのに、転記し忘れていたようです…(^^;

    基本やりたいのはDLさせることなので追記したものを使用しています。

    キャンセル

同じタグがついた質問を見る

  • PHP

    22389questions

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

  • Excel

    1742questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。