ひらい ぶらり Hi-Library

ぷろぐらみんぐについて。ときどきどうでもいいことについて。

PHPSpreadSheet で getRowIterator, getCellIterator を使って getFormattedValue で値を取得すると Formatted されない

結論: getCell()->getFormattedValue() を使う場合は、すぐ使う。Cellを変数に格納してから、別のCellを getCell() してしまうと、Formatのデータは一番最後に呼び出されたCellのものになる。

業務ツールでありがちな、Excelからデータをインポートするみたいな機能を作っている時に困った現象が起きた。
日付の値をCellから取得したいのだけど、書式的には yyyy年mm月 みたいな書式や yyyy年mm月dd日 みたいな書式の両方が入ってくる。
そのため Date::excelToDateTimeObject() で取ってしまうと、必ず日付まで入ってしまうため、月のみのセルなのか日まで入っているセルなのかの区別がつかない。
getFormattedValue() を使えば、書式を反映したデータが取れるはずだけども、getRowIterator() , getCellIterator() を使って取得すると書式が無視される…。

調べて見ると、getRowIterator() 経由で取得したCellの getStyle()->getNumberFormat()->getFormatCode() の結果は全て 一般 になってしまっている。
普通に getCell()getFormatCode() を使用した場合は、セルに指定された書式が入っている。
ReadersetDataOnly(false) にしてもだめ( ˘ω˘).

getRowIterator() を使うのをやめ、getHighestDataRow() で最終行を取得し for で回しながら getCell() を使って見たがだめ。
どうやら、Format情報は最後に呼び出されたCellのものが使用されるっぽい。

<?php

$cell1 = $sheet->getCell('A1'); // Format → テキスト
$cell2 = $sheet->getCell('B1'); // Format → 日付

$cell1->getFormattedValue(); // 日付フォーマット扱い
$cell2->getFormattedValue(); // 日付フォーマット扱い

みたいになる。悲しい。
そんなわけで、Formatを適用した値が欲しい場合は、getCellIterator()rangeToArray() を使ってはいけない。ゴリゴリ書くしかない。