Monthly Archives: 12月 2017

2017-12-26

新しいtableのスタイル

なんとなく表(table)のCSSを変えてみた。

ポイントはセルの角、つまり縦線と横線が交差する点の色をどう制御するか。

表はHTML要素的には table > tbody > tr > td の順に重なっているわけだけど、基本的に手前である子孫要素(tdに近い側)が優先される。なので、セル(td)の区切り線の色を指定すると、それは表全体(table)の境界線よりも優先されてしまう。その結果表全体の境界線にセルの区切り線が食い込む形になってしまう。

そこで重要なのが境界線の指定が重なったときに何が優先されるかというルール。親要素であっても線の幅が太い方が優先される。同じ太さならスタイル(破線とか二重線とか)によって優先度が決められている。特に二重線(border-style: double)は使える。solidよりもdoubleのほうが優先されるからだ。その上二重線といっても1pxの太さならsolidと見た目は変わらない。

外側(親、祖先)の要素の太さやスタイルをより優先度が高い物に変えることによって、セル区切りの色が外にはみ出さないように出来る。

/* table style */
table{ border: 1px double #4472c4;}
  /* striped background color */
thead{ border: none; background-color: #4472c4; color: #ffffff;}
tbody>tr:nth-child(odd){background-color: #d9e1f2;}
  /* vertical line between colgroups */
colgroup{ border: none;}
colgroup+colgroup{ border: none; border-left: 2px double #81a0d7;}
  /* horizontal line between tbodys */
tbody{border: none;}
tbody+tbody { border-top: 2px double #81a0d7;}
  /* vertical line between columns  */
tr:nth-child(even) >td+td {border-left: 1px solid #d9e1f2;}
tr:nth-child(odd)>td+td, th+th {border-left: 1px solid #fff;}

テスト

0 1 2 3 4
a b c d e
f g h i j
k l m n o

ヘッダー無し

項目1 項目2
項目3 項目4

ヘッダー無し

項目1 項目2

ヘッダー無し

項目1 項目2
項目3 項目4
項目3 項目4

良くある奴

品名 価格
りんご 100
みかん 80
みかん 80
  180

列グループ

場所 最低 最高
東京 晴れ 晴れ 曇り -1 9
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
2017-12-26

2017秋最終回

最近は全12話が多いから終わるのが早いね。

今期はどんどん切った。ここまで切ったのは初めてじゃないだろうか?

最後まで見たのは次:

不愉快な要素が鼻につくものは面白いところがあっても切りがちだと思う。 逆にそれほど面白くなくてもあまり期待せず気楽にながら見できるようなものは残りがち。

2017-12-26

2017年末ゲームアンインストール祭り

城とドラゴン、どうぶつの森ポケットキャンプ、ソリティア、Pokemon GO、駅メモをアンインストールした。

それほど面白くなくなっていた割に、合わせると結構な時間を消費していたからだ。

城とドラゴン。人に勧められて始めたのだけど、ずいぶん長いことプレイした。農場ゲー的育成要素と単純・短時間な対戦要素。チケット制。適度な緩さが良かったのだが、育成が進んでレベルが上がるにつれトロフィー戦はおろかリーグ戦も勝てなくなった。どうやら育成に失敗したらしい。次々と出る新キャラが古いキャラを相対的に弱くしていく。ついて行くには新キャラを手に入れて育成し続けなければならない。そういうキリのなさが見えてしまうともうダメだ。キャラクター間の相性ももはや全く覚えられない。チケットも最初は少なくて長時間遊べないのが逆に良かったのだけど、最近は対戦形式が増えたせいもあって全く消費しきれなくなっていた。

どうぶつの森ポケットキャンプ。プレイしたのは1ヶ月くらいだろうか。緩いように見えて案外時間を消費させられる。画面切り替え効果やローディングの時間はもとより、動物たちとの会話が単調で面白くなく、単なる時間の浪費でしかない。プレゼントを渡したときに時々発生するちょっとしたイベントはもはや罰ゲームでしかない。「バーベキューやるけど食っていくだろ?」いやいやいかねーよ!! はやく終わってくれよ。日々の作業が全部一括で終わるボタンがあれば良かったのに。

ソリティア。Androidのそのものズバリなゲームなのだが、ずいぶん長くプレイしてしまった。デイリーチャレンジがあるのが良かったのだが、通知が機能せずに逃してしまうことが多くなっていた。やり逃しても過去に遡ってプレイできるのだが、カレンダーに着く王冠マークが微妙に変わってしまう。それ以外に何の罰もないのだが何か不愉快だ。ゲーム自体もソリティアなので、何も考えずに適当にポチポチ押してクリアできるかどうか何回か試すだけである。まぁ、もういいよね。

Pokemon GO。もうずっとプレイしてなかった。

駅メモ。最初全く面白さが分からなかった。何回か旅行の際に遊んでみるうちにある日突然面白くなった。ローカル線主体の旅行でやるのが一番良いと思う。バスはずっと同じ駅しか入らないし新幹線や特急はずっと画面を見てないと通過駅を逃してしまうのでつらい。キャラクターの育成も最初全く分からなかったが、どうやると稼げるのか分かるとちょっと面白くなった。溜めていた無料ライセンス(1日のチェックイン回数が伸びるアイテム)が無くなってきたので最近はやらなくなっていた。課金してまでやりたいほどではない。路線コンプリートも一見魅力的だが、別にいつ無くなるか分からないようなアプリでやらなくていいじゃない。

2017-12-21 ,

org-mode スプレッドシート(表計算)での参照の書き方まとめ

org-modeで表計算が出来るということはよくご存じかと思いますが、細かいところがよく分からないという方も多いのではないでしょうか。特にフィールド(いわゆるセル)を式内から参照する書き方は広く使われている表計算ソフトとは異なるのでなかなか覚えられない、普段使うところだけ覚えてるということも多いと思います。なので今回はorg-modeのスプレッドシート機能の内、「参照」に的を絞ってまとめてみました。

参考: Org Mode マニュアル 3.5.1 参照 References (The Org Manual)

表内のフィールドや範囲等を参照する方法

フィールド参照

意味
@0 現在の行
$0 現在の列
@1 1行目
$2 2列目
@1$2 1行目2列目
@-1 直上の行
$-1 左隣の列
@-1$+3 現在のフィールドから上に1行、右に3列
@< 最初の行
@> 最後の行
$< 最初の列
$> 最後の列
@>$2 最終行の2列目
@>$> 最終行の最終列(右下)
@<<< 最初の行から下へ数えて3行目(@3)
@>> 最後の行から上へ数えて2行目
$<< 最初の列から右へ数えて2列目($2)
$>>> 最後の列から左へ数えて3列目
@I 一つ目の水平線
@-I 現在の行から上にある最初の水平線
@+II 現在の行から下にある2番目の水平線
@III+2 三つ目の水平線から下にある二番目の行
@III-1 三つ目の水平線の直上の行
  • @行$列
  • 0は現在
  • 符号が付くと相対指定
  • <が先頭で>が末尾
  • @Iは水平線
  • < > I は複数連続で書くとその個数分だけズレる

範囲参照

意味
@2$3..@3$5 「2行目の3列目」から「3行目の5列目」までの矩形範囲(6フィールド)
@2$1..@>>$> 「2行目の1列目」から「下から2行目の右端列」までの矩形範囲
@I..@II 一つ目の水平線から二つ目の水平線までにある行、現在の列

始点.. 終点 の形で 始点 から 終点 までの 矩形範囲 を指す。 始点終点 はそれぞれフィールドへの参照。

式の右辺に書いた場合範囲内の値を含む ベクトル になる。(例えば @1$1..@2$2 なら4要素のベクトルになる)

式の左辺に書いた場合計算で書き換える対象を表す。(@1=1行目の全列の式, $1=1列目の全行の式, @1$1..@2$2=左上2x2(4マス)の式)

※式の 左辺 に範囲参照を書く時 始点 には水平線参照(@I 等)は書けない(ダメな例: @I+1$>..@II-1$>=foo)。 終点 にはなぜか書ける(書ける例: @2$>..@II-1$>=foo)。(参考: 水平線参照を左辺には書けないのはなぜ?)

名前参照

意味
$name nameという名前の何かを参照

参照できる物:

リモート参照

意味
remote(table1, @>$>) table1という名前の表の最終行最終列(右下)にあるフィールドを参照。

#+NAME: 名前 を表の直前に書くとその表を名前で参照できる。

フィールド座標

意味
@# 現在の(計算対象の)行番号に展開される
$# 現在の(計算対象の)列番号に展開される
@@# @ ( @# ) と解釈。つまり@現在の行番号
$$# $ ( $# ) と解釈。つまり$現在の列番号
@$# @ ( $# ) と解釈。つまり@現在の列番号
$@# $ ( @# ) と解釈。つまり$現在の行番号

例1:列名と範囲参照

#+NAME: purchase2016
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        5 |   640 |
| # | みかん |  200 |        3 |   600 |
|---+--------+------+----------+-------|
| # |        |      |          |  1240 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@>$>=vsum(@I..@II)

! の行は列名となる。列名は $unit*$quantity のように使える。 $3*$4 より幾分分かりやすい。 # の行は自動再計算(フィールド入力後TABやRETで全体を再計算する)対象となる。その他にも同じような方法でフィールド名やパラメータを定義する機能がある。(参考: Org Mode マニュアル 3.5.8 一歩進んだ機能 Advanced features (The Org Manual))

@3$>..@II$>=$unit*$quantity

式の左辺にある @3$>..@II$> は「3行目の最後の列」から「2本目の水平線までの行の最後の列」までの範囲を表す。つまり右端の小計を入れる部分(右下の合計部分を除く)を指す。水平線参照だけを使って @I$>..@II$> のようには(左辺には)書けない(エラー:"Can't assign to hline relative reference")。列名を使って @3$total..@II$total のようにも書けなかった。 @<<<$>..@>>$> のようには書ける。

@>$>=vsum(@I..@II)

@I..@II は現在の列の一つ目の水平線から二つ目の水平線の間の範囲を表す。範囲内の値を要素とするベクトルが作られ、vsumでその合計が計算される。結果は @>$> つまり一番右下のフィールドに格納する。

今回は代入先の範囲が重ならないように厳密に指定して書いたが、 #+TBLFM: $>=$unit*$quantity::@>$>=vsum(@I..@II) のように書いても構わない。 $> は右端の全てのフィールド(ヘッダー以外)を意味するので右下( @>$> )と重なってしまうように見えるが、列指定よりフィールド指定が優先されることが決まっている。(参考: Org Mode マニュアル 3.5.5 列の数式 Column formulas (The Org Manual))

例2:リモート参照

| 税抜き | 税率 | 税込み |
|--------+------+--------|
|   1240 | 1.05 |   1302 |
|   1240 | 1.08 |   1339 |
#+TBLFM: $1=remote(purchase2016,@>$>)::$3=floor($1*$2)

remote(表名, 参照) で別表の値を取り出せる。

この例ではpurchase2016という名前の表(例1)の一番右下のフィールド(@>$>)を1列目($1)へ代入している。

例3: リモート参照(表の名前を計算時に決める)

purchase2016とpurchase2017の二つの表があるとき、この二つの表の合計部分(一番右下のフィールド)を別の表から参照したいとする。

#+NAME: purchase2016
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        5 |   640 |
| # | みかん |  200 |        3 |   600 |
|---+--------+------+----------+-------|
| # |        |      |          |  1240 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@>$>=vsum(@I..@II)

#+NAME: purchase2017
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        3 |   384 |
| # | みかん |  200 |        8 |  1600 |
|---+--------+------+----------+-------|
|   |        |      |          |  1984 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@5$5=vsum(@I..II)

列に表名を入れれば次のように書ける。

|   表名       | 金額 |
|--------------+------|
| purchase2016 | 1240 |
| purchase2017 | 1984 |
#+TBLFM: @<<$>..@>$>=remote($1,@>$>)

remoteの第一引数である $1 は先に展開されるのに対して第二引数である @>$> は展開されない(1984に置き換わらない)のが興味深い。

表名を表の中に書くのはかっこ悪いので年から表名文字列を生成してリモート参照したいなら次のようにする。

|   年 | 金額 |
|------+------|
| 2016 | 1240 |
| 2017 | 1984 |
#+TBLFM: @<<$>..@>$>='(org-table-get-remote-range (concat "purchase" $1) (string ?@ ?> ?$ ?>))

remote(表名, 参照) の書き方では文字列の結合等はできない(リモート参照の展開タイミング的に)ので、Elisp式を使っている。

(string ?@ ?> ?$ ?>) の部分は "@>$>" とは書けない。展開のタイミング的に。

(参考: emacs - Org mode spreadsheet programmatic remote references - Stack Overflow)

例4: 結果の行内への埋め込み

行内コードブロックを使えば表の中の値を文書中の行内に埋め込める。

#+NAME: ex4
| 品名   | 金額 |
|--------+------|
| りんご |  123 |
| みかん |   89 |
|--------+------|
|        |  212 |
#+TBLFM: @>$>=vsum(@I..@II)

合計は src_emacs-lisp[:results raw]{(org-table-get-remote-range "ex4" "@>$>")} 円です。

参考: Org Mode: Using table formula outside of a table? - Emacs Stack Exchange

例5: 連番

| 番号 | 番号4桁 |
|------+---------|
|    0 |    0000 |
|    1 |    0001 |
|    2 |    0002 |
|    3 |    0003 |
#+TBLFM: $1=@#-2::$2='(format "%04d" (- @# 2))

例6: 文字列の参照

基本的にElisp式で行った方が良い。Calcで扱えないこともないが非ASCIIは怪しい?

| 参照する文字列→      | abc                  | りんご                     >
| ↓式                  | ↓結果               | ↓結果                     >
|-----------------------+----------------------+---------------------------->
| @1                    | abc                  | #ERROR                     >
| "@1"                  | [40, 97, 98, 99, 41] | [40, 12426, 12435, 12372, 4>
| string("@1")          | (abc)                | string([40, 12426, 12435, 1>
| '(identity @1)        | abc                  | りんご                     >
| '(format "%sです" @1) | abcです              | りんごです                 >
#+TBLFM: @3$2=@1::@3$3=@1::@4$2="@1"::@4$3="@1"::@5$2=string("@1")::@5$3=string("@1")::@6$2='(identity @1)::@6$3='(identity @1)::@7$2='(format "%sです" @1)::@7$3='(format "%sです" @1)::@8$2=string("$s1")

水平線(hline)参照の謎

水平線参照をフィールド参照として使うとどうなるか

単に @I と書いた場合どこを参照するのか。

|       | 10 |
|-------+----|
|       | 11 |
|       | 12 |
|-------+----|
| ↓式  |    |
| @I-1  | 10 |
| @I    | 11 |
| @I+0  | 11 |
| @I+1  | 11 |
| @I+2  | 12 |
| @II-1 | 12 |
#+TBLFM: @5$2=@I-1::@6$2=@I::@7$2=@I+0::@8$2=@I+1::@9$2=@I+2::@10$2=@II-1

水平線の直下の行を参照する模様。意図した動作かは不明。 @I+1 と書いた方が安心?

水平線参照を左辺には書けないのはなぜ?

範囲参照例1にも書いたが、水平線(hline)への参照(@I 等)は式の左辺に書けない。

例えば次の良くあるような例では、小計を集計するのに「一つ目の水平線から二つ目の水平線までの行、右端列」つまり @I$>..@II$> と左辺に書けると便利である。

|        | 重量 | 個数 | 計 |
|--------+------+------+----|
| みかん |   30 |    2 |    |
| りんご |   50 |    3 |    |
|--------+------+------+----|
|        |      |      |    |
#+TBLFM: @I$>..@II$>=$-2*$-1

しかし実際に書くとエラーになる。

Can't assign to hline relative reference

なぜ書けないのかメーリングリストを"left hline"で検索してみた。

長年未解決で放置中らしい。

リモート参照とフィールド座標の展開規則

例3でも触れたがremoteの第二引数は別表の参照前に展開されないように見える。

しかしマニュアルには次のような例がある。(Field coordinates in formulas)

@3 = 2 * remote(FOO, @1$$#)
Insert the doubled value of each column of row 1 of the table named FOO into row 3 of the current table.

この例の @1$$# はremote()を解決する前に @1$1 , @1$2 , @1$3 のように参照元の列の番号に展開されなければならないはずだ。

#+NAME: remote-ref-tbl1
| 1 |  2 |  3 |  4 |
| 5 |  6 |  7 |  8 |
| 9 | 10 | 11 | 12 |

| 2 | 4 | 6 |
#+TBLFM: @1=2*remote(remote-ref-tbl1, @1$$#)

ちなみに「現在の列」を表したいなら $0 やそもそも列を省略すれば良さそうだが、実際にやると次のようになる。

| 2 | 2 | 2 |
#+TBLFM: @1=2*remote(remote-ref-tbl1, @1$0)

マニュアルにもリモート参照の第二引数は絶対参照か名前参照でなければならないと書いてあるのでこの書き方はできないのだろう。

org-table-eval-formula 関数を見ると、 @# 等のフィールド座標表記はリモート参照よりも前に解決しているようだ。つまり、remoteとその引数の展開は次のような順番になっている。

  1. フィールド座標(@# $#)だけ先に解決(数字へ置き換え)
  2. 第一引数を現在の表上で解決し、得られた名前に従って参照先となる表を見つける
  3. 見つけた表上で1の結果得られた第二引数の参照を解決する

そもそもこの remote(表名, 参照) という表記は関数の計算などではなく文字列の置き換えに過ぎない。なので展開の規則はCalcともElispとも異なる。 実際マニュアルの例にもあるとおりElisp式内でも同じように書ける。

$2 = '(identity remote(FOO, @@#$1))
Copy text or values of each row of column 1 of the table named FOO into column 2 of the current table.