TkTable

TkTableは、Tkで表を扱うためのWidgetを提供します。TkのWidgetと同等に扱えます。
TkTableは、最近のActiveTclにも添付されているので、簡単に使えるようになりました。
TkTableを使うと、簡単に表とスプレッドシート(表計算ソフト)を作ることができます。

表の作成

Tktableパッケージをロードすると、table Widgetが使えるようになります。
以下は、table Widgetを使って5行5列の表を作成しています。

package require Tktable

# 5行5列のテーブル
pack [table .t -variable ary -rows 5 -cols 5]

# 配列の添え字の表示
for {set i 0} {$i < 5} {incr i} {
    for {set j 0} {$j < 5} {incr j} {
        set ary($i,$j) "ary($i,$j)"
    }
}

-variableオプションで配列変数を与えると、その配列変数を2次元配列のように使い各セルの値を格納します。
各セルと配列変数の添え字の関係を以下に示します。

この時の配列変数aryをダンプしてみると、以下の様になっています。
最後のary(active)は、アクティブなセル(キャレットがあるセル)がどこかを示します。
現在は、アクティブなセルがないので、空になっています。

% parray ary
ary(0,0)    = ary(0,0)
ary(0,1)    = ary(0,1)
ary(0,2)    = ary(0,2)
ary(0,3)    = ary(0,3)
ary(0,4)    = ary(0,4)
...途中省略...
ary(4,0)    = ary(4,0)
ary(4,1)    = ary(4,1)
ary(4,2)    = ary(4,2)
ary(4,3)    = ary(4,3)
ary(4,4)    = ary(4,4)
ary(active) = 

次に、5行5列の表にタイトルとスクロールバーを付けてみます。
スクロールバーの付け方は、TkのWidgetの場合と同じです。

package require Tktable

# 5行5列のテーブル
table .t -variable ary -rows 5 -cols 5 \
    -colstretchmode unset -rowstretchmode unset \
    -multiline 0 -selectmode extended \
    -titlerows 1 -titlecols 1 -selecttitle 1 \
    -xscrollcommand {.x set} -yscrollcommand {.y set}
scrollbar .x -command {.t xview} -orient horizontal
scrollbar .y -command {.t yview} -orient vertical
grid .t .y -sticky news
grid .x -sticky news
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

# タイトルの作成
.t tag config title -relief groove
for {set i 0} {$i < 5} {incr i} {
    for {set j 0} {$j < 5} {incr j} {
        if {$i == 0 && $j > 0} {
            set ary($i,$j) [format %c [expr 64+$j]]
        } elseif {$j == 0 && $i > 0} {
            set ary($i,$j) $i
        }
    }
}

# colのサイズ設定
.t width 0 3

これで画面のリサイズにも追従しますし、タイトル部をクリックすると、
行または列ごとセレクトできます。

更に、セルや行/列ごとに色を付けることもできます。
-rowtagcommandと-coltagcommandオプションで色付けのコマンドを起動します。

package require Tktable

# 5行5列のテーブル
table .t -variable ary -rows 5 -cols 5 \
    -colstretchmode unset -rowstretchmode unset \
    -multiline 0 -selectmode extended \
    -titlerows 1 -titlecols 1 -selecttitle 1 \
    -xscrollcommand {.x set} -yscrollcommand {.y set} \
    -rowtagcommand rowProc -coltagcommand colProc
scrollbar .x -command {.t xview} -orient horizontal
scrollbar .y -command {.t yview} -orient vertical
grid .t .y -sticky news
grid .x -sticky news
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

# 奇数の行/列に色を設定
.t tag config OddRow -bg orange -fg purple
.t tag config OddCol -bg brown -fg pink
proc rowProc row { if {$row>0 && $row%2} { return OddRow } }
proc colProc col { if {$col>0 && $col%2} { return OddCol } }

# タイトルの作成
.t tag config title -relief groove
for {set i 0} {$i < 5} {incr i} {
    for {set j 0} {$j < 5} {incr j} {
        if {$i == 0 && $j > 0} {
            set ary($i,$j) [format %c [expr 64+$j]]
        } elseif {$j == 0 && $i > 0} {
            set ary($i,$j) $i
        }
    }
}

# colのサイズ設定
.t width 0 3

スプレッドシートの作成

表を発展させて簡単なExcel風のスプレッドシートを作成してみます。
A+B=Cを実行する単純な機能をTclプロシジャで実装しました。
-browsecommandオプションは、セルの移動があった場合にコマンドを起動します。
'%s'は移動する前のセルを示します。

package require Tktable

# A+B=C
proc change_cell {cell} {
    global ary
    set row [lindex [split $cell ,] 0]
    set col [lindex [split $cell ,] 1]
    if {$row == 0 || $col == 0} return
    set sum 0
    for {set i 1} {$i < 3} {incr i} {
        catch "set sum [expr $sum + $ary($row,$i)]"
    }
    set ary($row,3) $sum
}

# 5行5列のテーブル
table .t -variable ary -rows 5 -cols 5 \
    -colstretchmode unset -rowstretchmode unset \
    -multiline 0 -selectmode extended \
    -titlerows 1 -titlecols 1 -selecttitle 1 \
    -browsecommand {change_cell %s} \
    -xscrollcommand {.x set} -yscrollcommand {.y set}
scrollbar .x -command {.t xview} -orient horizontal
scrollbar .y -command {.t yview} -orient vertical
grid .t .y -sticky news
grid .x -sticky news
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

# Excel風のbindings
bind Table <Tab>	{::tk::table::MoveCell %W  0  1}
bind Table <Return>	{::tk::table::MoveCell %W 1 0}

# セルのanchor
.t tag config active -anchor w
.t tag config e -anchor e

# タイトルの作成
.t tag config title -relief groove -fg black -bg [.t cget -bg]
.t tag config active -fg black
for {set i 0} {$i < 5} {incr i} {
    for {set j 0} {$j < 5} {incr j} {
        if {$i == 0 && $j > 0} {
            set ary($i,$j) [format %c [expr 64+$j]]
        } elseif {$j == 0 && $i > 0} {
            set ary($i,$j) $i
        } else {
            .t tag cell e $i,$j
        }
    }
}

# colのサイズ設定
.t width 0 3

タグの機能を使って、値のセルは右寄せにして、アクティブのセルは左寄せにしてあります。

お小遣い帳の作成

更にスプレッドシートを発展させて、お小遣い帳を作成してみました。
収入と支出から差引残高を自動的に計算します。

package require Tktable

# 配列の値を取得
proc getary {cell} {
    global ary
    # 空のセルは0とみなす
    if {![info exists ary($cell)]} {
        return 0
    } else {
        return $ary($cell)
    }
}

# 差引残高+収入-支出
proc change_cell {cell} {
    global ary
    set row [lindex [split $cell ,] 0]
    set col [lindex [split $cell ,] 1]
    if {$row == 0 || $col == 0} return
    while {[info exists ary($row,1)]} {
        set in [getary $row,4]
        set out [getary $row,5]
        if {$row == 1} {
            set total 0
        } else {
            set total [getary [expr $row-1],6]
        }
        set sum [expr $in - $out]
        set ary($row,6) [expr $total + $sum]
        incr row
    }
}

# 5行5列のテーブル
table .t -variable ary -rows 101 -cols 8 -height 11 \
    -colstretchmode unset -rowstretchmode unset \
    -multiline 0 -selectmode extended \
    -titlerows 1 -titlecols 1 -selecttitle 1 \
    -browsecommand {change_cell %s} \
    -xscrollcommand {.x set} -yscrollcommand {.y set}
scrollbar .x -command {.t xview} -orient horizontal
scrollbar .y -command {.t yview} -orient vertical
grid .t .y -sticky news
grid .x -sticky news
grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1

# Excel風のbindings
bind Table <Tab>        {::tk::table::MoveCell %W 0 1}
bind Table <Return>     {::tk::table::MoveCell %W 1 0}
bind Table <Control-b>  {%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-f>  {%W icursor [expr {[%W icursor]+1}]}

# セルのanchor
.t tag config active -anchor w
.t tag config e -anchor e
.t tag config w -anchor w

# タイトルの作成
.t tag config title -relief groove -fg black -bg [.t cget -bg]
.t tag config active -fg black
set i 1
foreach item {日付 曜日 摘要 収入 支出 差引残高 備考} {
    set ary(0,$i) $item
    incr i
}
for {set i 1} {$i < 101} {incr i} {
    for {set j 0} {$j < 8} {incr j} {
        if {$j == 0 && $i > 0} {
            set ary($i,$j) $i
        } else {
            if {$j == 4 || $j == 5 || $j == 6} {
                .t tag cell e $i,$j
            } else {
                .t tag cell w $i,$j
            }
        }
    }
}

# colのサイズ設定
.t width 0 3 1 10 2 4 3 20 4 8 5 8 6 8

タグの機能を使って、列によって右寄せ/左寄せを変更しました。

まとめ

TkTableは、表とスプレッドシートを作成するためのフレームワークを提供してくれます。
実際に、表計算をさせたり、行をソートしたり、列を入れ替えたりする等の処理は、
すべてTclのプロシジャで記述するため、プログラマーの力量が問われます。(^^;)
欲を言えばきりがないのですが、スプレッドシートを作ろうした場合、Excel等の
表計算ソフトとのbindingsの違いが気になります。微妙な癖ってやつですね。
このあたりはバージョンアップで改善されることを期待したいです。


TkTable