Excelで2階層のメニューを作る
家計簿を付け始めたのだが、Excelの使い方がいまいち分からない。リボンインターフェースにイライラさせられるのはどうしようもないけど。
支出を「食費」や「交通費」のようにカテゴリで分けられれば、どんな生活をしているか分かる。しかし、これらの項目をセルごとに入力すると以下の問題がおこる。そのため、列挙項目として一箇所で管理しておきたい。
- 間違いのためにフィルタから漏れる
- 変更する際に漏れが生じる
また、列挙項目は将来増えるかもしれないので、自動的に選択肢が増えるようにしたい。更に、食費なら「間食」や「飲み会」のように階層化もしたい。
例として、シートの1行目にカテゴリを列挙し、2行目以降にサブカテゴリを列方向に列挙する場合について、2階層のメニューを作る方法を調べた。
-
- カテゴリ表始点: $A$1
- カテゴリ行: $1$1
[1] セルの値を選択式にするには入力規則を使う
セルに対して入力規則(データメニュー)を適用することが分かった。入力規則の設定において、値として許可するものに「リスト」を選択し、リストの範囲を指定してやればよい。こうすることで、リスト範囲内のセルの値が、セル上でプルダウンメニューから選べるようになる。
ただリスト範囲を直接指定してしまうと、変更の際に面倒なことになる。リストの項目を増やしたり移動したときに、無効な値の入ったリストを選択肢としてしまう。こうならないためにも、間接的な参照方法を活用すべきらしい。INDIRECT関数や、名前定義がその手段と分かった。
[2] カテゴリ数を可変にするためにはCOUNTAで数え、OFFSETで範囲を返す
リスト範囲を自動的に変更するためには、関数を使って範囲が設定されるようにしておく必要がある。
INDIRECT関数は、セルの中身を範囲とするC言語でいうポインタ的な役割。これは範囲を書いたセルか名前(あらかじめ名前定義する)が必要なので、今回は使わない。
- 参考: 連動したドロップダウンリスト
ここでは、OFFSET関数とCOUNTA関数を用いる方法を採用する。以下のリンクに方法がそのまま載っている。
- 参考: OFFSET関数
- COUNTA関数: 選択範囲(列、行全体も可能)にある空でないセル数を数え上げる
- OFFSET関数: 基準範囲とオフセット、(基準範囲の始点からの)幅と高さを指定することで、選択範囲を返す
これを使うと、以下のようにカテゴリリスト範囲を求められる。
- カテゴリリスト範囲: OFFSET( カテゴリ表始点, 0, 0, 1, カテゴリ数)
- カテゴリ数: COUNTA( カテゴリ行)
- 最終的なカテゴリリスト範囲: OFFSET( $A$1, 0, 0, 1, COUNTA( $1:$1))
[3] リストを多階層化するには
これには方法がいくつかあるはずだが、MATCH関数を使う方法をとる。
- 参考: エクセルの入力規則の階層選択について教えてください?
- 参考: INDIRECT関数を用いた例
- MATCH関数: 指定された値を指定された範囲から探し出し、範囲の始点からのオフセットを数字で返す...範囲は行か列方向のみに限定されているのかもしれない。
これを使うと、以下のようにサブカテゴリリスト範囲を求められる。重複があるのが気になるけど。
- カテゴリ始点: 実際のデータにおける、カテゴリ列のラベル
- サブカテゴリ列基準: $A:$A ...こうするとOFFSET関数の戻り値が有限範囲ではなく列となる
- カテゴリセル: OFFSET( カテゴリ始点, ROW() - 1)
- サブカテゴリリスト範囲: OFFSET( カテゴリ表始点, 1, カテゴリ列オフセット, サブカテゴリ数, 1)
- カテゴリ列オフセット: MATCH( カテゴリセル, カテゴリ行, 0) - 1
- サブカテゴリ数: COUNTA( サブカテゴリ列) - 1
- サブカテゴリ列: OFFSET( サブカテゴリ列基準, 0, カテゴリ列オフセット)
最終的なサブカテゴリリスト範囲:
=OFFSET( 分類!$A$1, 1, MATCH( OFFSET( $C$1, ROW() - 1, 0), 分類!$1:$1, 0) - 1,COUNTA( OFFSET( 分類!$A:$A, 0, MATCH( OFFSET( $C$1, ROW() - 1, 0), 分類!$1:$1, 0)-1))-1))
こんな感じでやったら、サブカテゴリも自動で増減するようにできた。