やめてしまえそんなもの

できることを無理なくやって生きていきたいです

RubyXLでセルの水平位置が全セルで同一になってしまう(未解決)

アプリから出力するExcelで、このあたりは左寄せにしたいけど、このあたりは中央揃えにしたいといったことがありました。 Excelの出力にはrubyXLを使用しています。 github.com

https://github.com/weshatheleopard/rubyXL#horizontal

セル単位、行列単位で水平位置が変更できそうな雰囲気です。 この内容を出力するセルは中央揃え、この内容を出力するセルは左寄せという風に設定して、出力してみました。

全部左寄せになってる、、

部分部分で設定したのですが、一番最後に設定した水平位置に一律揃ってしまいました。 ナンデヤネン、と思いpryを突っ込んで数時間ゴリゴリやっていたのですが、理屈は分かりました。

RubyXLがセルの書式設定をどうしているかというと、 ざっくり言うと、RubyXLには書式設定を表すRubyXL::XFというクラスがあります。 セル作成時にRubyXL::XFのオブジェクトも作成し、配列cell_xfsに詰めます。 セルのオブジェクトは、自分の書式設定がcell_xfsの何番目に入っているかを覚えておきます。

#<RubyXL::XF:0x007f4a66b03238
  @alignment=
    #<RubyXL::Alignment:0x007f4a66a73408
      @horizontal="center",

…中略…

  @xf_id=0>

RubyXL::XF@alignment中にRubyXL::Alignmentがあり、そいつが持っている@horizontalが水平位置の設定を担っています。

セル作成時にRubyXL::XFのオブジェクトを作る際、cell_xfs[0]dupします。 この時、cell_xfs[0]の値が@alignmentを持っていれば、同じ値を引き継ぎます。 つまり、cell_xfs[0]の持っているそれと同一のRubyXL::Alignmentが入ります。

https://github.com/weshatheleopard/rubyXL/blob/df0afbddf3939cd8f04f45b6fff3eb9353259c4e/lib/rubyXL/convenience_methods.rb#L153

pryで追ったところ、一つ目のセルの作成の時点で、cell_xfs[0]@alignmentを持っていました。 なので、その後生成されたセルは、全てcell_xfs[0]@alignmentと同一のRubyXL::Alignmentオブジェクトを有することになります。 同一のRubyXL::Alignmentですから、@horizontalの値も同一です。 これにより、セル単位で水平位置を変更したとしても、全てのセルが参照している水平位置の設定が同じため、全てのセルの水平位置が同じという結果になっていました。

最初にテンプレートから展開したり、initializeでパッチを当てたりしているので、そこでgem製作者の想定外の挙動が起こっているのかなぁと思っています。 一旦対応はpendingにしています。