Help us understand the problem. What is going on with this article?

Excel方眼紙をHTMLライクに作ってみる

More than 5 years have passed since last update.

Slideshareに投稿したのですが、LTでやったので詳細が伝わらないと思ったので解説します。
http://www.slideshare.net/kawasima/ss-33220875

Excel方眼紙の話題は尽きることはありませんが、どうも殺意ばかりが前面にでて、Excel方眼紙と上手く付き合う方法がみられなかったので、作ってみた次第です。
Excel方眼紙をPDF等のただの帳票として考えると、これはなかなか面白いものですし、iTextを使ってPDFを作るより、Excel方眼紙を作ってからPDF化した方が簡単に帳票出力コードかける気がしています。帳票レイアウトもExcel方眼紙であればユーザに直接作ってもらったものが使えますし、ね :laughing:

axbomber-cljとは

axebomber-cljは、HTML-likeなコードでExcel方眼紙をアウトプットするためのツールです。

構文はhiccupと同じく[タグ 属性 コンテンツ]というClojureのvectorによるツリー構造になります。非常に直感的です。

renderタグは方眼紙に対する絶対座標での位置を示しますが、中のコンテンツは原則的に垂直フローティングされます。すなわち、行の中身が数行に及べば、その分だけ後ろのコンテンツは自動的に下にずれて配置されます。

レンダリングの基本

指定した位置に書き込む

render関数を使って、任意の方眼紙のマス目に書き込めます。

(render sheet 1 1 "こんにちは、Excel方眼紙!")
(render sheet 1 2 "さようなら、UIとしてのExcel…")

SnapCrab_NoName_2014-4-9_16-23-20_No-00.png

第1引数はPOIのシートオブジェクトで第2、第3引数が、x,y座標を指します。
axebomber-cljには、Excelシートを方眼紙にするユーティリティ関数のto-gridがあるので、それを使うとよいでしょう。

(let [sheet (to-grid (.createSheet wb "Simple table"))]
  ;; renderの処理をここに書く
)

表組み

このように、HTMLのtable,tr,tdタグを使ってテーブルを表現すると、Excelシート上に

(render sheet 0 0
        [:table
         [:tr
          [:td "ID"]
          [:td "名前"]]
         [:tr
          [:td 1]
          [:td "りんご"]]
         [:tr
          [:td 2]
          [:td "ばなな"]]])

SnapCrab_NoName_2014-4-9_15-53-53_No-00.png

tdタグにはHTMLのスタイルシートよろしく、スタイルを定義できます。

(render sheet 0 0
        [:table
         [:tr
          [:td {:data-width 3 :style "background-color: lightblue"} "ID"]
          [:td {:data-width 8 :style "background-color: lightgreen"} "名前"]]
         [:tr
          [:td 1]
          [:td "りんご"]]
         [:tr
          [:td 2]
          [:td "ばなな"]]])

SnapCrab_NoName_2014-4-9_16-26-19_No-00.png

スタイルは、クラス定義して要素に適用することも可能です。

(create-style ".title1" :background-color "lightblue")
(create-style ".title2" :background-color "lightgreen")
(render sheet 1 1
        [:table
         [:tr
          [:td.title1 {:data-width 3} "ID"]
          [:td.title2 {:data-width 8} "名前"]]
         [:tr
          [:td 1]
          [:td "りんご"]]
         [:tr
          [:td 2]
          [:td "ばなな"]]])

便利ですね!

テーブルのネストも可能です。※ただし、適切にマージンを取らないとデザインが崩れます。

(render sheet 1 1
        [:table
         [:tr
          [:td.title1 {:data-width 3} "ID"]
          [:td.title2 {:data-width 8} "名前"]]
         [:tr
          [:td 1]
          [:td [:table {:data-margin-top 1 :data-margin-left 1 :data-margin-bottom 1}
                [:tr
                 [:td {:data-width 3} ""]
                 [:td {:data-width 3} "産地"]]
                [:tr
                 [:td "ふじ"]
                 [:td "青森"]]
                [:tr
                 [:td "あずさ"]
                 [:td "長野"]]]]]
         [:tr
          [:td 2]
          [:td "ばなな"]]])

SnapCrab_NoName_2014-4-9_17-5-3_No-00.png

リスト

リストもHTMLと同じようにul, ol, liタグが使えます。

(render sheet 1 1
        [:ul
         [:li "りんご"]
         [:li "ばなな"]
         [:li "いちご"]])

SnapCrab_NoName_2014-4-9_17-10-36_No-00.png

(render sheet 1 1
        [:ol
         [:li "りんご"]
         [:li "ばなな"]
         [:li "いちご"]])

SnapCrab_NoName_2014-4-9_17-10-43_No-00.png

まだ、ハコしか書けませんが、方眼紙を利用して図を書くことができます。

(render sheet 1 1
        [:graphics {:data-width 30 :data-height 30}
         [:box {:x 1 :y 1 :w 3 :h 3} "ハコ1"]
         [:box {:x 5 :y 2 :w 4 :h 2} "ハコ2"]])

SnapCrab_NoName_2014-4-9_17-13-13_No-00.png

スケジュールや体制図もExcel方眼紙に書くことができますね!

実用的な方眼紙を書く

さて、それではこれらを組み合わせて、かの有名な「Excel方眼紙」の何が悪い?の記事に出ていた営業日報を作ってみます。

hiccupでHTMLレンダリングするときと同じように、データを定義します。

(def model
  {:店舗 "西新宿店"
   :担当 "川島義隆"
   :日付 (Date.)
   :計画
   {:来客数 150
    :売上高 150000
    :販売点数 1000}
   :実績
   {:来客数 2
    :売上高 1800
    :販売点数 30}
   :備考 "さっぱりでした…"

   :取引記録
   [{:取引先名 "A社"
     :連絡先   "03-XXXX-XXXX"
     :内容     "担当者の笑顔が素敵です。"}
    {:取引先名 "B社"
     :連絡先   "03-XXXX-XXXX"
     :内容     "担当者怖いです。"}
    {:取引先名 "C社"
     :連絡先   "03-XXXX-XXXX"
     :内容     "電話にでんわ。"}]

   :特記事項 "特になし\n\n\n\nですが、改行の分だけ行数が伸びます。"})

それから、これらの値をテンプレートに埋めていきます。ifforを使った制御も可能です。

一部抜粋
(defn template [sheet model]
  (render sheet 1 1
          [:table
           [:tr
            [:td.header {:data-width 28} "営業日報"]]
           [:tr
            [:td.title {:data-width 3} "店舗"]
            [:td {:data-width 8} (:店舗 model)]
            [:td.title {:data-width 3} "担当"]
            [:td {:data-width 7} (:担当 model)]
            [:td.title {:data-width 2} "日付"]
            [:td {:data-width 5} (:日付 model)]]

そして定義したモデルをテンプレートでレンダリングしてやると、Excel方眼紙「営業日報」が出力できます。

(create-style ".title"
              :border-style "solid"
              :background-color "lightgreen")
(create-style ".header"
              :border-style "solid"
              :color "white"
              :background-color "seagreen")
(create-style ".number"
              :text-align "right")
(create-style ".vertical"
              :writing-mode "vertical-rl"
              :vertical-align "top"
              :text-align "center")
(create-style ".center"
              :text-align "center")
(template sheet model)

SnapCrab_NoName_2014-4-9_17-27-27_No-00.png

詳しくは、axebomber-cljのテストコードを見てみてください。

今後の予定

まだ、開発中のSNAPSHOTバージョンしかないので、これからもインタフェース変えることもあると思いますが、データとスタイルを分離したテンプレートを元に、Excel方眼紙にキレイにレンダリングできることは、Excel方眼紙に対する評価を180度変える可能性があるので、LTの一発ネタだけではなく、開発継続したいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした