だいぶお久しぶりになりました。
WEBおじさんです。
今回の内容はねー、結構困っている人たちが多いみたいですねー。
私もだいぶ悩まされました。約1ヶ月くらい調べっぱなしの検証しっぱなし、みたいな感じで、いろんな人たちに聞いても「phpspreadsheetを使ったことないからわからない」とか「こんな感じの記事が出てきました」と親切に教えてくれるものの、3回くらい隅から隅まで見まくって検証しまくった記事だったり。
当然、クライアントさんに依頼されてphpspreadsheetを使っているのですが、色んなパターン(5種類くらい)でエクセルの出力をしているのです。
その中で、「画像の貼り付けを使っていない」パターンは1つ、それ以外は全て画像の貼り付けを使っているパターンでしたが、1パターンだけ、何の問題もなくエクセル出力ができていたのです。
これは私にとっては非常にラッキーな出来事で、「なぜこのパターンのみが何のアラートも出ずに正常に出力できているのか」ということだけを突き詰めていけばいいだけの問題でした。
でも、どんだけ調べても全然解決されなかったのですが、ついこないだやっと解決したので、それを同症状で困っている色んな方々の為に、ここに記しておきたいと思いました。
それでは、そもそものこの問題について、というところからお話ししましょう。
【PHPSpreadsheetで出力したエクセルを開こうとするとアラートが表示される】
まず、どういった症状なのかを説明すると、phpspreadsheetを使ってxlsxファイルを出力した際、そのファイルを開こうとすると、以下のようなアラートが表示されます。
「’●●(ファイル名)’の一部の内容に問題が見つかりました。可能な限り内容を回復しますか?ブックの発行元が信頼できる場合は、[はい]をクリックしてください。」
実は、今まではPHPExcelを使用していたのですが、色々な問題からサーバー移行することが決定し、PHPのバージョンの問題からPHPExcelからphpspreadsheetへ移行することが必須となりました。
なので、ある程度のエラーには耐性があり、アラートが出る場合のほとんどはPHPエラーが発生しており、ファイルを開くとPHPエラーが表示されている、という感じだったので、今回もその類いなのかと思い、何も考えずに「はい」をクリックしてファイルを開きました。
すると、エクセルファイル自体は正しくデータが反映され、もちろん画像も正常に配置されていました。
「ん?」と思い、そのエクセルを上から下まで細かくチェックしてみたけど特におかしな表示部分は見当たらなかったのです。
いわゆる「ただアラートが出ているだけ」状態。
これが自分自身の為のプログラムであれば、何も気にせずに使い続けるのですが、これはそうではなくクライアントが使用するプログラム。
「アラートが出ますが、気にせず【はい】をクリックしてくれればエクセルファイルは正常に作られていますので、そのままお使いください」とは言えません。
当たり前ですが、オレがクライアントなら「いやいや、アラートが出るならどっかで何かしらのエラーが出てるんでしょ?それは解決しておこうよ。」と間違いなく言うでしょう。
なので、当然この問題を解決するために、Google先生に頼ることにしました。(毎度のことですが)
ということで、Google先生に聞いてみたところ、同じような症状が発生している先人の方々が多数いらっしゃいました。
掲示板に書き込んでいる方々もいらっしゃいました。
色々な記事を読んでいくと、この症状はどうやらテンプレートを使用し、「Drawクラス」、つまり画像の貼り付けを使ってエクセルファイルを出力すると発生する症状であることが判明。
ということで、とりあえず画像の貼り付け部分を一度排除してエクセルの出力を試してみました。
すると、出力されたエクセルファイルはアラートが出ることもなく正常に開きました。
「なるほど。こいつはなかなか厄介っぽい問題だなー。」
と思いましたね。
なぜなら、これは解決した人がスクリプトを書いてくれていないと解決するまでに時間がかかるタイプの問題だと思ったからです。
でも、どこにも解決するためのスクリプトが書いていない。
さらに調べていくと、どうやらこれはphpspreadsheet側の仕様だという記事まで出ている始末。本当にそうだとすると、これはphpspreadsheet側が改善してくれないとどうにもならない症状だということ。
これは困った。
しかし、記事冒頭でも書いたように、画像の貼り付けをしていてもアラートが出ずに正常に開けるパターンがあったため、解決の目処、というか、解決はできる問題であるはず、と思っていました。
なので、とりあえずクライアントさんには今回の状況を説明し、一旦アラートについてはそのまま流して使ってもらうように案内し、まずはサーバー移行を全て完了させ、その後全力でphpspreadsheetアラート問題を解決させることにしました。
ということで、解決の為にまず問題の切り分け作業から入ります。
今回の場合、「Aパターンはアラートが出ず、Bパターンが出る理由条件」を探すところから始めました。
色んな記事を読んでいると、テンプレート側に問題があるということが書かれているのがいくつかありました。
まぁ、スクリプト側はphpspreadsheetの仕様に沿って正しく書いているはずなので、そちらが悪い、ということはないですよね。
そして、画像の不具合というのも疑ったのですが、こちらは同じ画像を使っていてもアラートが出たり出なかったりしていたので、これは早々に排除。
ということで、アラートが出ないテンプレートを使ってアラートが出るスクリプトでエクセルファイルを出力することにしてみた。
このパターンだとアラートが出る。
では、PHPファイルのファイル名をアラートが出るパターンのファイル名に変更したアラートが出ないPHPファイルを使用してエクセルファイルを出力。(ややこしい)
このパターンはアラートが出ない。まぁ、そりゃそうだ。ファイル名が変わっただけで、テンプレートとPHPファイルはアラートが出ないものなのだから。
では、テンプレートがどうのこうの言っていたので、テンプレートファイルに使用するxlsxファイルを新規で開いて何の加工もしていないxlsxファイルで試してみる。PHPファイルはアラートが出るパターンのファイル。
すると、なんとアラートが出ない!
ということは、PHP側には特に問題がなく、やはりテンプレート側に原因があることが判明!
ちなみに、テンプレートを使用せずに作成するパターンで試してみてもアラートは出ませんでした。
ここまでたどり着くのに2週間ほど経過www
ということで、まずはテンプレートを使わずに作ることをやってみるものの、処理が多くて書くのがめんどくさい!
なので、再度Google先生と相談しながらテンプレートを作っていくことに。
何の加工もしていないxlsxファイルの場合はアラートが出ないのであれば、どの時点でアラートが出るのか、ということを調査することにしました。
例えば、文字色を使ったり、背景色を使ったり、セルのマージを使ったりするなど、エクセルファイルをどこまで加工するとアラートが出るのか、を細々検証していくのですが、なんか不規則というか、「ここまではアラートが出なかったはずなのに、アラートが出るようになってしまった」といった状態がありました。
全然理解できない状況ではあったものの、さらに一つ一つの作業を注意して実施していくと、なんと全ての色やセルのマージ加工が終わった時点のテンプレートで正常に出力できるようになった!
色やセルのマージ等の加工が原因ではなかった!よかった!
詳細のことはよくわからないが、アラートが出るようになってしまったら一からテンプレートを作り直すことで解決されるんだ!
面倒だけどしょうがないか!
そう思い、そのテンプレートのズームや印刷範囲の処理を行い、再度アップして最終チェックを行ってみたところ、なんとここまで来て再度アラートが発動するようになってしまった!
「ハァ!?」と思い、アラートが出ないテンプレに対して行った処理を思い返し、その処理を取り消してみたが時すでに遅し。もうアラートが消えることはなかった。
ということで、非常にめんどくさいことだが再度新規でテンプレートを作り直すことに。そして、ここまではアラートが出ないという手順で一度ファイルを保存し、幾つかのコピーを取っておく。
そして、その一つを使って、まずテンプレートのズームを変更してアップしてみたところ、アラート発生。別のファイルでズームはそのままに印刷範囲の処理を行ったところ、アラート発生。
ということで、これらの処理は行わずにテンプレートを使用することに。
とここで、どっかの記事を思い出した。
「印刷設定をしていることが原因になっているようだ」ということが書いてあった。なるほど。これがそうか。
そして、更にそこには「アラートが出るようになってしまった場合は、シートを新しく追加し、そこにテンプレートで作った内容を全コピーするだけでアラートは出なくなる。しかしそこで印刷設定等の処理は入れないように。印刷設定はphpspreadsheetの処理側で行うように。」と書いてあった。
まさか、と思い、アラートが出るようになってしまったファイルを再度開き、シートを新しく一つ追加し、そこにテンプレートの内容を全コピーした後、そのシートを削除して使用してみたところ、アラートは発生しなかった!
変な時間食った!なんだよ!
ということで、ズームの数値設定や印刷範囲設定、印刷縮小拡大設定等に関してはphpspreadsheet側で処理を追加してみると、全てがうまくいった完璧な状態でエクセルファイルを出力することができたのだ!
と、ここまでが今回の問題の全容でした。
ある記事によると、やはりこの問題はphpspreadsheet側の問題で、テンプレートに使用しているxlsxファイルに印刷設定が一度でもされた場合、取り消しをしてもその履歴がファイル(シート)内に残ってしまい、それが原因となりアラートが発生してしまうのではないか、とのこと。
まぁ、画像の貼り付けを使わなければ今回の問題は出なかったし、画像の貼り付けを使った場合の対処も知識として追加することができたのでまた一つレベルアップしたとして今回の問題は完了することにしました。
この記事を読んで同症状で困っている一人でも多くの人が助かりますように。
WEBおじさんでした。