スタイル

表は必ずテーブルにする

法律事務所の仕事では、エクセルをデータベースとして使うことが多くあります。エクセルをデータベースとして使用する場合に便利な機能として、テーブル機能があるのですが、使っている人は少ないようです。

テーブル機能がどうして便利なのかについては、こちらの記事が参考になります。

そして、このテーブル機能は、VBAとの親和性が非常に高い機能でもあります。
この点に関しては、こちらの記事にが参考になります。

「VBAエキスパート公式テキスト」の「Excel VBAスタンダード」には、2019年に改訂された際に「テーブルの操作」に関する20ページ以上の記事が追加されました。つまり、VBAエキスパート試験の試験範囲に含まれたということです。このことは、このテーブルを操作できることが、VBAを習得するうえで重要なものになっていることを表しています。

「テーブルにすると何が良いのか」を説明するためには、「テーブルがないと何が問題なのか」を説明しなければなりません。その問題に実際に直面した人でなければ、理解してもらうのは極めて困難だと思いますが、一番重大な問題点を一言でいうならば、「変化に弱い」ということです。

「Excel VBAを実務で使い倒す技術」には、「『変化』は必ずやってきてVBAを劣化させる」とし、「予測できる変化に備えておく」ことや「そもそも変化に強い作り方をしておく」ことが重要だと述べられています。そういった観点で、「テーブル機能」を活用することには、大きな利点があります。

一度、テーブルを用いたVBAプログラミングを経験したならば、もう二度と元には戻れなくなるほどです。また、テーブルを用いる場合のVBAのコードは、それを用いないものとは大きく異なるため、VBAでデータベースを扱う場合には、最初から「テーブル機能」を用いるべきです。

ということで、VBAアセットでは、「表は必ずテーブルにする」というスタイルを採っています。

テーブルの特定

VBAアセットでは、テーブルを特定するのにテーブルの名前を使っています。法律事務所では、データベースを作ったら、それを更新して使い続ける場面がほとんどだと思います。次々にテーブルを自動的作成しなければならないことは、経験したことがありません。このため、テーブルに付けられた名前を使って特定するのが、最も簡単で確実な方法だと思います。

例えば、テーブル名が「テーブル」の場合、次のようにテーブルのデータ領域を特定できます。

Range("テーブル")

テーブルの最終行列番号は、次のようにして求めることができます。
テーブルを使わない場合に表の最終行を求めるのに苦労していたのが、嘘のようです。

r = Range("テーブル").Rows.Count
s = Range("テーブル").Columns.Count

Rangeの前にシート名が必要かどうかについては、次のとおりです。
・標準モジュールおよびWorkbookモジュールでは、(ブックの配下となるので)シート名は必要ない
・Sheetモジュールでは、自分のシートにテーブルがある場合のみシート名は必要ない(他のシートにテーブルがある場合はシート名を指定しないとエラーになる。) 

テーブル内部の部位の特定

まずは、テーブル行列番号を使って特定することができます。特にテーブル行を0にして、見出しを特定する手法は使う場面が多いです。

Range("テーブル")(r,s)     'データ領域のr番目の行、s番目の列のセル
Range("テーブル").Cells(r,s)  '同上
Range("テーブル")(0,s)     '見出しのs番目の列のセル
Range("テーブル").Cells(0,s)  '同上

次に構造化参照を使って、見出しを使って特定することができます。
これができることが、テーブルを使うことで得られる最大の利点です。後からテーブルの途中に新しい列を追加しても、マクロを修正する必要がなくなります。

Range("テーブル[番号]")(r)    '「番号」列のr番目の行のセル
Range("テーブル[番号]").rows(r)  '同上

特定の見出しの列番号を求めることも簡単です。

Range("テーブル[番号]").Column '「番号」列の列番号

データ領域の行や列全体を特定することもできます。特に「行全体」は、特定の行の書式を設定する場合にとても便利です。

Range("テーブル").Rows(r)    'r番目の行全体
Range("テーブル").Columns(s)  's番目の列全体(見出しを除く)

テーブルの位置

テーブルの位置(シートの行列番号)は、次のようにして求めることができます。

i = Range("テーブル").Row
j = Range("テーブル").Column

イベントプロシージャは、シートの行列番号しか返しませんので、イベントでテーブルを操作する場合は、これによって求めた位置でテーブルの行列番号に補正する必要があります。

r = Target.Row - Range("テーブル").Row + 1
s = Target.Column - Range("テーブル").Column + 1

参考

ListObjectsを使う方法もあります。

コメント

  1. 管理人 より:

    特定の見出しの列番号の求め方を追加しました。

  2. 管理人 より:

    Rangeの前にシートの指定が必要かどうかについて、追記しました。

タイトルとURLをコピーしました