列番号をクラスに持てば、列名が候補表示されて非常に便利です。これを実装するには、かなりの手間がかかります。クラス作成に手間をかけて、その後を楽にするということになります。クラスを使う理由は入力支援だけではなく、むしろそれは結果としての付属的なものでしかありません。列挙体(Enum)列挙体は、数値限定のConst定数をひとまとめにして参照しやすくしたものになります、マクロVBAの中で数値を固定で記述することは、メンテナンスが大変になります。列位置3(C列)を参照する場合、VBA内で何度も3と記述しては、これを変更することが大変になります。構造体(Type)ユーザー定義型は、名前の通りユーザーが定義できるデータ型になります。普通の変数は、1つの値しか入れられませんが、ユーザー定義型は、複数の異なるデータ型を入れる事が出来ます。プログラミング言語での一般的な呼び方としては、構造体とも呼ばれます。クラスを作る際に列名も持たせる場合ということになります。クラスについての概要は、VBAのクラスとは(Class,Property,Get,Let,Set)VBAを覚えて、いろいろ作りながらネットで調べたりしていると、クラスとかオブジェクト指向といった言葉に出くわします。VBEの「挿入」の一番下にある「クラスモジュール」は気になっていたかもしれません。このクラスモジュールを使ってクラスを作ります。列挙体と構造体を使った場合の具体例を見てみます。列名の表示だけなら、これで十分です。問題点としては、列を入れ替えたり列挿入したりすると、列挙体の記述を変更しなければならない点です。列の移動や入れ替えに対応する方法には名前定義を使う方法があります。列タイトルに事前に名前定義しておくことで、実行時に名前定義をもとに列数を取得します。Range("名前定義の名前").Columnこれで取得した列数をVBAで使うことで、列移動や表の途中に列挿入されても正しい列位置で処理ができるようになります。列挙体は数値定数で値の変更はできません。名前定義で取得した列数は、そのまま使うか変数に入れるしかありません。列挙体と名前定義の両方を同時に使う為には工夫が必要です。列挙体に合わせた配列を用意しその中に名前定義で取得した列数を入れる方法が考えられます。Typeこの構造体に列数を事前に入れておきます。Range("nm氏名").Columnその後は、列名で扱うことができるようになります。列位置変更に対応するなら、構造体+名前定義が最も良い方法になると思います。構造体は関連するデータを一つにまとめる機能であり、クラスに近い存在となります。クラスは、関連するデータを一つにまとめ、さらに関連する操作まで組み込める機能だと理解すればよいでしょう。クラスはそんな単純なものではありませんし、もっと多くの機能があります。関連するデータやその操作を一つにまとめたものがクラスであり、つまりは、構造体+関連するプロシージャーを一つにまとめたもの、これくらいの認識でも構いません。従って、構造体を使ったことが無ければ、まずは構造体を少しでも理解してからクラスに入ったほうが理解がしやすいと思います。クラスの各種機能については、今後VBAコードとともに徐々に解説していきます。対象物を部品を使って組み立てるように表現してプログラミングしていくものです。(polymorphism)VBAでは、継承も多態性も使えない。(インターフェースだけ使える)従って、カプセル化だけを意識すれば良いのです。関連するデータやその操作を一つ(カプセル)にまとめることを言います。関連するものを一つのカプセルにまとめ、そのカプセルをコピーしつつ使いまわすというイメージになります。カプセル化の重要な要素として、「隠蔽」があります。必要なもののみ外部に公開し、不必要なものは非公開として隠蔽します。隠蔽が正しくできないと、カプセルの中身をあちこちから何時の間にか変更されたりして困ることになります。・クラスの完成コード以下で、順に説明します。シートに名前定義を設定シートの列タイトルに名前定義を設定します。上記サンプルシートでは1行目になります。Function列タイトル行のA列から最終列までの空白セルを除くセルに名前定義を設定しています。こちらを参照してください。名前定義をマクロVBAで扱う場合の解説になります、名前定義は、複数セル範囲や単一セルに対して名前を付けることで、そのセル範囲を参照する時に名前で参照できるようにするものです。名前で参照できることで、セル位置(行位置、列位置)を固定値で指定しなくて済むようになります。名前定義に使う名前(後でプロパティ名としても使います)にするために、_(アンダーバー)以外の記号を_(アンダーバー)に置換します。そもそも列タイトルに色々な記号を使うことはあまりお勧めしません。改行コードやスペースは削除しています。記号置換の関数になります。本来なら、_(アンダーバー)以外の記号は全て外したいところですが、ここでの本旨から外れるので、簡易的にキーボードから簡単に入力できる記号だけの判定にしています。)の判定マクロVBAで、文字の種類を判定する具体的なコードになります、書き方はいろいろありますし、なにより、文字を何の種類に入れるかは決まりがありません。このような細部については、使用する時々に合わせて微調整が必要になります。このあたりを参考に文字判定を組み込んでください。名前のプリフィックスは名前定義として分かり易くしているだけであり、必須ではありません。上記コードでは、シートに対してシート.Names.Addとしているので、名前の適用範囲はそのシートに限定されます。列タイトルは、他のシートの列タイトルと重複してしまうので、これを避けるためです。名前が長いとプロパティ名として扱うときに不便なので、なるべく短く済むようにするためです。従って、同一シート内の列タイトルは重複しないようにしなければなりませんし、さらに、適度な長さの適切な名称にしておく必要があります。名前が適度な長さの適切な名称とはクラスのプロパティ名としても使いますので、プロパティ名として適切なということになります。入力支援で表示される名称としてふさわしい名称ということであり、その規則は、VBAの変数名で許可される文字列ということです。・英数字(全角半角)、漢字、記号はアンダーバー(_)だけ使える、空白(スペース)は使えない・先頭には、数字やアンダーバー(_)は使えない、英文字か漢字で始める・使えない予約語がある・長さは半角で255文字までとはいえ、列タイトルとしては、なかなかそういうわけにもいかない(項目の説明的なタイトル等の)場合があると思います。そのようなときは、名前定義に使う名称を別の行に設定しておくことで対応できます。これが無いとエクセルのデータベース機能が使えなくなります。この2行を非表示にしておけば見た目は元のままです。変更することになります。以上で、前準備としての名前定義の完了になりますが、この準備は、先に書いた列挙体(Enum)列挙体は、数値限定のConst定数をひとまとめにして参照しやすくしたものになります、マクロVBAの中で数値を固定で記述することは、メンテナンスが大変になります。列位置3(C列)を参照する場合、VBA内で何度も3と記述しては、これを変更することが大変になります。構造体(Type)ユーザー定義型は、名前の通りユーザーが定義できるデータ型になります。普通の変数は、1つの値しか入れられませんが、ユーザー定義型は、複数の異なるデータ型を入れる事が出来ます。プログラミング言語での一般的な呼び方としては、構造体とも呼ばれます。列移動対応の時も同様になります。クラスを新規挿入Class1が作成されます。挿入していくと、2,3,と連番で作成されます。オブジェクト名:Class1これを変更します。オブジェクト名:clsColumns名前なので、命名規則の範囲内なら何でも良いのですが、プリフィックスとして「cls」「class」等を付けておくことをお勧めします。後で、「cl」と入力すると候補一覧が出て簡単に指定できるようになります。Explicitだけが書かれた白紙が出てきます、標準モジュール作成時と同じですね。名前定義の列数を取得するのは簡単です。シート.Range("名前定義の名前").Columnこれで取得できます。対象のシートを受け取るプロパティと、これを受け取って列数を返す関数(Function)を作成します。名前が無いとエラーになるので、エラー処理も入れておきます。Functionクラス作成ではカプセル化を意識します。カプセル化の重要な要素として隠蔽があります。むやみに内部を公開しないということです。基本的にはPrivateで作成し、外部に公開が必要なもののみPublicにします。外部とやり取りするための出入り口が公開(Public)のプロパティとメソッドになります。Worksheet)引数でシートのオブジェクトを受け取ります。これはSetだけなので、書き込み専用プロパティ(入口専用、値を受け取るだけ)ということです。Long引数で名前定義の名前を受け取ります。これで外部からこのクラスが使用可能になります。clsColumnsこのように1行で書いても構いません。違いはVBA内部処理の違いなので、特に気にする必要はありません。クラスの中で、公開(Public)されているものだけが入力支援に表示されます。それ以外は隠蔽されていて、外部からは扱えなくなっています。ここまでで、後は名前定義の名前によって列数を返すプロパティを作れば良い状態になりました。名前定義の名前を受け取り、列数を返すプロパティを作ります。LongこれはA列なら1を返します。これはGetだけなので、読み取り専用プロパティ(出口専用、値を返すだけ)ということです。Static変数について通常の変数は、プロシージャーやプロパティの終了とともに消えてしまいますが、Static変数は値を保持しています。次回呼ばれたときに、前回の値が入ったままの状態ということです。このプロパティにアクセスするたびに、getColumnを呼びRangeを参照してしまうと、とても処理速度が遅くなります。そこで、ここではStatic変数に値を入れることで、最初の1回だけgetColumnを呼び出すようにしています。これは、以下のようにすることもできます。Privateなモジュールレベル変数として定義、全列の列数を変数に格納するメソッドを実行し変数に値を入れておく。このように作成することも可能です、むしろそのほうが一般的かもしれません。列数が多く、多くの列をVBAであつかうのであれば、そのほうが良いでしょう。実際にその列を扱うときに取得するようにしたということです。変数を使った方法では、一つのフィールドに対する記述が3箇所に分散しています。これは、メンテナンスするときに面倒な作業となります。(変更なら置換すれば良いのですが、追加の場合には3箇所で追加作業が必要です。)今回の方法なら、一か所にまとまっているので、メンテ作業はしやすいので採用したということです。パフォーマンス(速度やメモリ消費)に関しては、今回は無視して作成しています。差異があるとしても、かなり僅かな差異なので、かなり大量の繰り返し処理をしなければ体感できる差異はないと思いますそのような必要性があるときは、個別に対応策を考える必要があります。入力支援にクラス名が表示されるのが確認できます。クラスの中で、公開(Public)されているものだけが入力支援に表示されます。それ以外は隠蔽されていて、外部からは扱えなくなっています。Subサンプルシートであれば、1が表示されます。顧客ID以外の全てのフィールド(列タイトル)のプロパティを作成します。Propertyこれで、全ての列名が入力支援に表示されます。数字が返されるので、Cellsの中でもどこでも、その数値が必要な場所に書くことができます。(どこでもといっても、定数値を書かなければならない場所には書けませんが)クラスの完成コード以下が、今回のクラスの完成VBAコードです。Function最後に今回作成したクラスですと、先に解説した構造体(Type)との違いがはっきりしません。いいますか、結果としての機能は同じです。一つの標準モジュールに構造体とFunctionを入れれば同じことになります。これだけなら、どちらが良いということはありません。他のクラスを作るのなら、ついでにクラスが良いのではないかというくらいでしかありません。今回作成したクラスは、表のフィールド数が多いと、やたら長くなるというのが欠点です。フィールド数分のプロパティが必要なので、これを全部タイピングするのは時間がかかります。カプセル化ができていないクラスということになりますし、それなら構造体を使ったほうが良いので、クラス化した意味が半減してしまいます。変数を公開してしまうと、外部からその変数の値が変更可能になってしまいます。これは極めて危険であり、カプセル化できていないということになります。プロパティの記述は単純作業ですが(なので)大変です。そこで次回は、この面倒なプロパティの記述を自動で作成するマクロVBAを紹介する予定です。Next)|VBA入門7.マクロって何?VBAって何?|VBA入門8.セルに文字を入れるとは(Range,Value)|VBA入門9.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説10.ひらがな⇔カタカナの変換|エクセル基本操作トップマクロVBAVBAクラス入門VBAクラスの作り方:列名の入力支援と列移動対応このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。GASスプレッドシート入門スプレッドシート応用GAS入門GAS応用トップマクロVBAVBAクラス入門VBAクラスの作り方:列名の入力支援と列移動対応このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。