前回同様、またAxlsx関連のマニアック話ですが、なぞ仕様に嵌ってしまったので記録として残しておきます。 同じように悩んでしまっている方の一助になれば幸いです。
Cellのtypeに:dateを指定しているのに日付型のセル書式にならない
以下のようにadd_cellで日付型オブジェクト(Date.today)、typeに:dateを指定しているのにも関わらず、セルの書式が日付型として入力されない事象が発生しました。
p = Axlsx::Package.new ws = p.workbook.add_worksheet header_style = ws.styles.add_style(border: { style: :thin, color: '000000' }, bg_color: 'E4E4E4') value_style = ws.styles.add_style(border: { style: :thin, color: '000000' }) row = ws.add_row row.add_cell('日付', style: header_style, type: :string) row.add_cell(Date.today, style: value_style, type: :date)
▼日付型ではなく数値データ入力されている
なお、add_cellメソッドというのはCellをnewしているだけのシンプルなプログラムです。
# Adds a single cell to the row based on the data provided and updates the worksheet's autofit data. # @return [Cell] def add_cell(value = '', options = {}) c = Cell.new(self, value, options) self << c worksheet.send(:update_column_info, self, []) c end
axlsx/row.rb at 8e7b4b3b7259103452c191f73ce0bf64f66033fe · randym/axlsx · GitHub
ちなみにこの事象は、以下のようにstyleは未指定、type :date
のみ指定する場合だと正しく日付型で入力されます。
p = Axlsx::Package.new ws = p.workbook.add_worksheet row = ws.add_row row.add_cell('日付', type: :string) row.add_cell(Date.today, type: :date)
▼日付型として入力されている
どうやら、Cellをnewする時にstyleとtype :dateを併用するとセルの書式設定が日付型として認識されないという動きのようです。
styleに明示的にnum_fmtを指定すると日付型の書式が適用される
小一時間ほど悩んでいましたが、以下のドキュメントに答えが記載されていました。
Method: Axlsx::Styles#add_style — Documentation for randym/axlsx (master)
styleにnum_fmt
というオプションで日付フォーマットを指定することで、セルの書式に日付型が適用されるようです。
p = Axlsx::Package.new ws = p.workbook.add_worksheet header_style = ws.styles.add_style(border: { style: :thin, color: '000000' }, bg_color: 'E4E4E4') date_style = ws.styles.add_style(num_fmt: Axlsx::NUM_FMT_YYYYMMDD, border: { style: :thin, color: '000000' }) row = ws.add_row row.add_cell('日付', style: header_style, type: :string) row.add_cell(Date.today, style: date_style, type: :date)
▼日付型として入力されている
Cellをnewする際に、styleとtype :date
を併用する場合は、明示的にnum_fmt
を指定する必要があるようです。
なぜこのような動きになるかというと、Cellクラスのコードを見るとわかるように、デフォルトの日付用style(STYLE_DATE)がオプションで指定したstyleで上書きされてしまうからです。
def cast_value(v) return v if v.is_a?(RichText) || v.nil? case type when :date self.style = STYLE_DATE if self.style == 0 v
axlsx/cell.rb at 8e7b4b3b7259103452c191f73ce0bf64f66033fe · randym/axlsx · GitHub
Cellに対してオプションでstyleを指定してしまうと、typeごとに定義されたデフォルトのstyleが上書きされてしまい、セルの書式設定が無効となるようです。