システム環境
Amazon Linux Release 2 ( kernel 4.14.70-72.55.amzn2.x86_64 )
Perl v5.16.3
spreadsheet::XLSXを使うべきではない理由
EXCELのセルに日時を入力して保存した場合、そのデータはシリアル値として保存されています。
そのシリアル値を読み込むと小数点2位で丸められてしまう(切り捨て、切り上げ、四捨五入かは未検証)ため、日付は問題ありませんが、時間がずれます。
1 2 3 4 5 6 7 8 |
use Spreadsheet::XLSX; my $f = "test.xlsx"; my $xlsx = Spreadsheet::XLSX -> new ($f); my $s = $xlsx->{'Worksheet'}[0]; my $serialtime = $s->{'Cells'}[0][0]->value; #A1に日時が入っていることを想定。この値が小数点2位で丸められる my $unixtime = - ( $serialtime - 25569) * 86400; #Windows版EXCELでは1900年1月1日が基準になっているため、70年分の日数(25569日)を減算して1日の秒数を掛ける #Excel for macの場合、基準日が1904のため、正しく計算されません。 |
spreadsheet::Readを使う理由
あくまでEXCELを生成するのではなく、読むことだけを目的とした場合とても直感的に利用できることが理由です。
また何より上のSpreadsheet::XLSXで起きる問題が解決できます。
この2つのモジュールはセルの読み出し方がspreadsheet::XLSXは[行番号][列番号]なのに対してspreadsheet::Readは[列番号][行番号]な点は注意が必要です。
ちなみに、「直感的に利用できる」と記載した理由は以下のような書き方ができるからです。
1 2 3 4 5 6 7 8 9 |
use Spreadsheet::Read; use POSIX qw(ceil); my $f = "test.xlsx"; my $xlsx = ReadData($f); my $sheet = $xlsx->[1]; #ファイルオブジェクトの[0]にはファイルの情報が入る my $serialtime = $sheet->{'A1'}; #A1に日時が入っていることを想定。丸められない。{'A1'}の代わりに[0][0]でも読み出せる。 my $unixtime = - ceil(( $serialtime - 25569) * 86400); #割り切れない少数の場合にシリアル値の最後の桁が切り捨てられているため、切り上げる必要がある。 #Excel for macの場合、基準日が1904のため、正しく計算されません。 |