13
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BRIGHT VIEAdvent Calendar 2017

Day 19

PHPでExcel出力する際にfromArrayが便利ですが、0が空でセルに表示される問題の対応

Last updated at Posted at 2017-12-18

この記事は BRIGHT VIE Advent Calendar 2017 - Qiita 19日目の記事になります。

とある案件で、PHPでExcel出力をする必要があり、
そのときに0を表示したいのに空でセルに表示されている問題があったのでその対応メモです。

はじめに

PHPでExcel出力するのは、PHPExcel_IOFactoryを利用するととっても簡単!(調べればすぐですね!)

実装

//ライブラリの読込
require_once 'PHPExcel.php';
require_once 'PHPExcel/IOFactory.php';

// テンプレートファイル読み込み
$reader = PHPExcel_IOFactory::createReader('Excel2007');
$excel = $reader->load("template.xlsx"));

// シートの設定を行う
$excel->setActiveSheetIndex(0);
$sheet = $excel->getActiveSheet();

/******************
 * 書き込み処理 *
 ******************/
// セルを指定して書き込み
$sheet->setCellValue('B2' , "書き込みたいデータ");

// 配列データを書き込み(B6のセルから$arrayのデータを書き込む)
$sheet->fromArray($array, null, 'B6');


/******************
 * 出力処理 *
 ******************/
header('Content-Type: application/octet-stream');
// ダウンロードするファイル名を設定
header('Content-Disposition: attachment;filename="download_test.xlsx"');

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

はい、これだけで実施できちゃいます。
集計機能などExcelの出力状態がわかっていれば、
fromArrayで予め表示用の配列を作っておけば出力処理はすぐです!

fromArrayで0を出力していたはずなのにセルの状態が空になる

ここで本題です。
こちらは集計画面の内容をExcelに出力するという機能で利用していたのですが、
0のデータが軒並み空文字になっていました。

なんでだろうと思ってさぐっていると、いつもお世話になっているstack overflowに下記のような記載が...

I think you are a victim of loosely-typed comparisons here - you have specified null as your second parameter to fromArray(), which represents the Value in source array that stands for blank cell. Since null == 0 this means that zero will result in a blank cell unless you set the fourth argument to true.

引用元: PHPExcel outputting zeros as blank cells -stack overflow

fromArrayメソッドの第二引数は、セルが空になる定義で、今回の場合だと「null」を指定している。
そのため、fromArrayでセルに0を書き出すときには、「null == 0」な曖昧な判定で行われてしまっているため、
0が出力されずに空になってしまっているという原因ぽい。

実際にどんな処理なのかPHPExcelのfromArrayメソッドをGitHubで見てみました。

まずは、fromArrayメソッドの定義部分。
第二引数に「$nullValue」、第四引数に「$strictNullComparison」というのがあるのが分かる。

/**
 * Fill worksheet from values in array
 * 
 * @param array $source Source array
 * @param mixed $nullValue Value in source array that stands for blank cell
 * @param string $startCell Insert array starting from this cell address as the top left coordinate
 * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array
 * @throws PHPExcel_Exception
 * @return PHPExcel_Worksheet
 */
 public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) |

参照元: PHPExcel Worksheet.php 2406行目付近 - GitHub

そして肝心の判定処理

if ($strictNullComparison) {
  if ($cellValue !== $nullValue) {
    // Set cell value
    $this->getCell($currentColumn . $startRow)->setValue($cellValue); 
  }
} else {
  if ($cellValue != $nullValue) {
    // Set cell value
    $this->getCell($currentColumn . $startRow)->setValue($cellValue); |
  }
}

参照元: PHPExcel Worksheet.php 2430行目付近 - GitHub

確かに、第四引数の「strictNullComparison」をtrueにしていると、
「cellValue !== nullValue」厳密なチェックが行われており、
そうでない場合には「cellValue != nullValue」と曖昧なチェックが行われている。

なろほど...

第四引数のstrictNullComparisonをtrueにする

ということで、

// 配列データを書き込み(B6のセルから$arrayのデータを書き込む)
$sheet->fromArray($array, null, 'B6', true);

とすることで、Excelに0がきちんと出力されるようになりましたー

まとめ

新卒の頃曖昧な型チェックを行うのであれば、起こり得る全ての判定パターンを理解した上で使っているのかを厳しくチェック頂いたためか、
今では迷うことはなくなりましたが...(チーム開発となるとバグを防ぐために基本的には厳密な型チェックを利用)

曖昧チェックの良さはありつつも、こういうハマリポイント?もあるのでなんだかなぁという気持ちにはなりました。

13
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?