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

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

ただいまの
回答率

88.10%

Laravel Excel でxlsxファイルに画像を設定すると破損

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 5,538

score 12

前提・実現したいこと

  1. Laravel で xlsxファイルを出力します。
  2. 処理内で、xlsx内に画像ファイル(png)を貼り付けして出力。
  3. そのxlsxファイルを開くと、破損メッセージが表示されます。(問題点)
  4. 「はい」をクリックすると、ファイルは画像含めて、正しく表示されます。

★破損メッセージを出ないようにしたいです。★

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

xlsxの一部の内容に問題が見つかりました。可能な限り内容を回復しますか?ブックの発行元が信頼できる場合は、[はい]をクリックしてください。

該当のソースコード

use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as ReaderXlsx;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as WriterXlsx;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

public function excel()
{
    // テンプレートファイル定義
    $excel_file = storage_path('excel/template.xlsx');

    // テンプレートファイル取得
    $reader = new ReaderXlsx();
    $spreadsheet = $reader->load($excel_file);

    // アクティブシートの取得
    $sheet = $spreadsheet->getActiveSheet();

    // 画像設定
    $imagePath = 'name.png';
    (new Drawing())
     ->setPath($imagePath)
     ->setWorksheet($sheet)
     ->setResizeProportional(false)
     ->setCoordinates(Coordinate::stringFromColumnIndex(4) . 1); //セルD1に設定

    // ダウンロード
    // Xlsxにした場合、画像をPHPで設定したファイルを開くと、破損する
    // Xlsにした場合、画像をPHPで設定したファイルを開くと、破損しない
    $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="file.xlsx"');    // ダウンロードファイル名
    $writer->save("php://output");  // PHPのoutputストリーム
}

試したこと

  • 出力ファイルを「xls」にすると、破損しませんでした。
  • テンプレートの読込み方がいけないのか、出力ファイルの形式指定が足りないのか。。
  • 画像ファイルは、普通にExcelで挿入、保存した場合は破損になりません。=画像は悪くない。

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

Windows7
Laravel5.7
Laravel Excel 3.1
phpspreadsheet 1.6
Excel Office365

もし何か、ご助言いただければありがたいです(。。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

以前仕事で、同じ症状に、頭を悩ませたことがあります。

その時は、色々と試みた経緯で、たまたま上手く行く方法が見つかったため(VBAマクロ付きのExcelだったので、それらも利用して解決した)、
時間もなかったこともあり、詳しい調査はさておいたまま、とりあえず解決としてしまったのですが、
同じような現象に困っているのこの質問を見つけ、そういえば私も結局原因とか分かってないな・・と思い、
改めて、色々と試してみました。


私の検証した限りの話になりますが、どうやら、きっかけはExcelのシートそのものにあるようで。。。

■「新規シート追加 → シート内を編集 → 保存(1回目)」

ここまでの状態のシートであれば、画像貼り付けで、破損エラーが表示されないのですが、

■「保存(1回目) → シート内を編集 → 保存(2回目以降)」

これだと、破損エラーが表示されるようです。

シート内の編集は、こういう変更すべてです。

・セルへの文字追加・削除
・セルの書式設定
・ページ設定
・印刷範囲

これらを、一度保存済みのシートに対して変更→保存し、そのシートに画像を貼りつけると、破損エラー表示に繋がるようです。

もしかすると、シートがこっそり持っている「編集履歴のような情報」が、SpreadSheetから貼り付けた画像に、なんらかの影響を及ぼして、破損メッセージに繋がっているのかもしれません。
「xlsで保存する破損エラーが表示されない」のは、この「編集履歴のような情報」が破棄されるからかも・・・(xlsxとxlsでは、シートの列・行の上限が大きく異なるので、xlsでは持っていられない情報になり得るため、こういった情報が破棄されること自体は不思議ではないと思います)

ということで、PhpSpreadsheet側の問題だとは思いますが、だからといって「破損メッセージがでるのは仕方ないです」とは言えないのが現実なので。

手間だとは思いますが、テンプレートファイルの「シート」を、まるっと新しく作り直してみて下さい。
それで、この現象自体は解決するはず、です(多分 ^^;)

作り直しは、新規シート追加で元のシートを全コピペするような方法でお試しください。(シートの複製ではダメ)
また、新規シートは調整が完全に終了するまで、絶対に保存しないよう気を付けてくださいね・・!

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/28 17:02 編集

    ありがとうございます!!

    テストとして、テンプレートを、Excel新規作成しただけのxlsxファイルを使った結果、
    破損エラーが発生しませんでした!

    この考えで、テンプレートを見直します(。。

    キャンセル

  • 2020/01/27 19:48

    読み込み直後で、データを投入する前なら既に加工したテンプレートでも、レイアウトが崩れないまま画像を貼り付けられました。

    したがって
    1)画像を貼り付ける
    2)データを貼り付ける

    この順番を守ればまっさらのスプレッドシートでなくても大丈夫なようですね。

    キャンセル

0

Laravelというより、PhpSpreadsheetの問題っぽいですね。
下記の質問が参考になるのではないでしょうか。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/27 15:49

    xlsxのほうが色々と厳密なのかもしれませんね。

    キャンセル

  • 2019/08/27 16:08

    「xlsxの一部の内容に問題が見つかりました。可能な限り内容を回復しますか?」このメッセージが出るときは、ファイルにPHPのエラーが文字列で出力されているようなことが多いのですが、
    出力されたファイルをテキストエディタで強制的に開いた時に、ファイルの先頭、もしくは末尾にPHPのエラー出力や、HTMLのような記述がないか確認してみてください。

    キャンセル

  • 2019/08/27 17:07

    ありがとうございます。

    xlsxファイルを、テキスト/バイナリエディタで開きました。
    PHPエラー、HTMLのような記述は見つかりませんでした。

    キャンセル

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

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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