最終更新日:2020-12-21オブジェクト変数とは何かVBAを使い始めてからある程度進むとオブジェクト変数を必ず使い始めることになります。オブジェクト変数をどうやって使ったらよいのか、オブジェクト変数とはどういうものなのか・・・ここの理解で苦しんでいることが多々あるようです。VBA入門は現在137回までありますが、オブジェクト変数については第52回.オブジェクト変数とSetステートメントででてきます。基本構文→セルの扱い→VBA関数→オブジェクト全体としてはこのような進み方になっていて、かなり基本的な部分、初歩的な段階ででてきます。この段階ではオブジェクトを入れる変数と言うのがある、こくらいの認識なのは仕方ない事です。VBAである程度の事を自動化するだけなら、オブジェクトを入れる変数がオブジェクト変数であり、Setステートメントを使って変数に入れる。この程度の理解でもほとんど困ることは無いでしょう。思った通りに動作しないことも出てきて、オブジェクト変数って何なんだろう?という疑問が出てくることになります。今回はオブジェクト変数についてより少し詳しく説明していきます。そもそも変数とは何かプログラムにおいて、扱うデータを入れて必要なときに利用するために用意した入れ物で、その入れ物に付けた名前が変数名になります。入れ物と表現しましたが、変数には、文字や数値と言った値だけでなく、オブジェクトも入れられます。オブジェクトを入れる変数を特にオブジェクト変数と呼びます。変数の入れ物としての大きさは数値であればデータ型ごとにバイト数が決まっています。Integerは2バイト、LongやSingleなら4バイト、Doubleなら8バイトそれぞれ大きさが決まっているので、あらかじめ決められた大きさの変数(入れ物)を用意する事が出来ます。これに対して、文字列型のStringは文字列の長さが決まっていないので、あらかじめ決められた大きさの変数を用意することができません同様にオブジェクト変数も、あらかじめ決められた大きさの変数を用意できません。固有オブジェクト型(オブジェクトの種類、つまりクラス)これらは変数に入れるものの大きさが決まっていませんし、VBA実行中にも大きさが変わります。Stringは、文字列長が様々です。・空文字列の処理方法による速度比較Object型やVariant型は、そもそも何が入るか分かりません。固有オブジェクト型は決められたオブジェクト(クラス)であっても、その中で保有するデータ量は様々です。簡単な例としては、Workbookオブジェクトの大きさがまちまちなのは自然に理解できることと思います。これらの変数は、どのような入れ物(変数)を用意するのでしょうか。オブジェクト変数にオブジェクトは入っていないもし仮にオブジェクト変数に直接オブジェクトを入れるとしたら、さまざまな不都合が起きます。Range("A1")を複数のオブジェクト変数(例えば、変数Aと変数B)に入れた場合、それぞれの変数(変数Aと変数B)ごとにオブジェクトが存在してしまう事になります。変数A変数Aと変数Bにそれぞれオブジェクトが入っているとしたら、同じRange("A1")が2つ存在する?片方の変数のValueを変更したら、もう一方の変数のValueはどうなるの?もちろん、Range("A1")は1つしか存在しませんし、変数BのValueを変更すれば変数AのValueも変更されます。実際のオブジェクトは1つしか存在しないという事です。変数Aと変数Bには何が入っているのかという事になります。オブジェクト変数には、オブジェクトそのものが入っているわけではありません。オブジェクトがどこにあるかのを示す情報が入っています。これは、Windowsのファイルのショートカットを作る事と似ています。ショートカットは複数作れますが、ファイルそのものは同じ1つのファイルです。Windowsのショートカットはファイルそのものではありません、ショートカットにはファイルの場所を示す情報(ファイルのフルパス)が入っているのです。オブジェクト変数には、オブジェクトのメモリアドレスが入っています。2つの変数に同じオブジェクトを入れた場合、それぞれの変数の中にはオブジェクトの同じメモリアドレスが入ります。オブジェクト変数のメモリアドレスオブジェクト変数には、オブジェクトのメモリアドレスが入っていると言いましたが、実際に確認してみましょう。変数のメモリアドレスを確認するには、以下の関数を使います。変数のメモリアドレスを返します。ObjPtr関数オブジェクトのメモリアドレスを返します。実際にVBAを実行して見てみましょう。※Windows10+Excel2019(64bit)※メモリアドレスは実行のたびに変わります。VarPtr関数の戻り値は、変数そのもののメモリアドレスですので当然別々になります。ObjPtr関数の戻り値で、オブジェクトのメモリアドレスが同じであることが確認できます。これは自作したクラスでも同じです。適当にクラスを作ってやってみます。ちなみに、クラスモジュールだけ挿入すればクラスのインスタンスは作成できます。ObjPtr(変数B)ObjPtr関数の戻り値を見ると同じオブジェクトを指していることが分かります。それぞれにNewした場合は、別々のオブジェクトになります。ObjPtr(変数B)別々のオブジェクトであることが分かります。別々に定義したからといって、別々のオブジェクトが作成されるわけではありません。Range("A1")この場合のObjPtrは別々の値になりますが、Range("A1")が複数あるわけもなく、これらはさらにその先で管理されていて、同じオブジェクトにたどり着くようになっています。Newで作ることの出来ないクラスに関しては、このように特殊な管理がされていると考えてください。Is演算子によるオブジェクトの比較Is演算子は、2つのオブジェクト参照変数を比較するために使用されます。ThenObject1とobject2の両方が同じオブジェクトを参照する場合はTrueになります。それ以外はFalseになります。固有オブジェクト型)の初期値はNothingです。Is演算子による比較は参照が同じかどうか判定をします、つまり、ObjPtr関数の取得値の比較と同じ意味になります。FalseRangeブジェクトの場合は注意が必要です。FalseRangeが特殊であることが分かります。typename指定された型との間で型と互換性があるかどうかを確認します。演算子は、objectexpressionの実行時の型がtypenameと互換性があるかどうかを調べます。互換性は、typenameの型のカテゴリに依存します。VBAでの型の判定は、通常はTypeName関数で行います。TypeName関数は、引数で指定された変数に関する情報を文字列で返します。ユーザー定義型の変数を除く、任意のバリアント型(Variant)の変数を指定します。Implements(インターフェイス)使用時には、TypeName関数での判定とTypeOf演算子での判定で違いが出ます。Implementsを指定したクラスの場合、TypeName関数は、Implementsとは関係なくそれぞれのクラス名が返されますが、TypeOf演算子は互換性を確認するので元のクラスと同一判定されます。オブジェクト変数を使う時の注意点ByValでもオブジェクトの中は変更されるByRefは参照渡し、つまり、変数そのものを渡しています。ByValは値渡し、つまり、変数の中の値を渡しています。言い換えると、ByRefは、VarPtrを渡しています。ByValは、ObjPtrを渡しています。Subこの結果は、test_subと出力されます。ByValだからと言って、オブジェクトの中身を渡せるわけはなく、あくまでオブジェクトのアドレスを渡しているという事です。オブジェクトのアドレスを受け取れば、そのオブジェクトに対する操作はByRefと同じ結果となります。Subこの結果は、$A$1と出力されます。呼び出された中でオブジェクト変数に別のオブジェクトを入れたとき、呼び出し元のオブジェクト変数がいれかわるかどうかだけになります。Withを使ったときの勘違いWithは単なる表記の省略ではありません。コレクションの1要素であるオブジェクトをWithで使う時は注意が必要です。Sub記述が長いので、Withでまとめてみましょう。Sub上記2つのVBAでは結果が違ってきます。前者のtest3_1では、$A$1$A$1後者のtest3_2では、$A$1$A$2それぞれに見れば、結果は当たり前に見えるかもしれません。Withが単なる表記の省略として考えてしまうと、上記のような書き直しの間違いを起こす可能性があります。Withで捉えたものは、その時点のRange("A1")のオブジェクトです。行挿入によって、Withで捉えたオブジェクトはコレクションの中で位置がずらされます。Withの中では常にWithで捉えたオブジェクトを参照します。Withにコレクション内のオブジェクトを指定する場合は、With内では、そのオブジェクトのコレクション内での位置をずらすような記述はしないようにしましょう。記述時点ではそれが正しい処理であったとしても、後々のトラブルの元になります。Nothing)されたときにオブジェクトは破棄されます。'これでClass1は破棄されます。Subただし、当り前ではありますが、RangeオブジェクトやWorksheetオブジェクトが破棄されることはありません。オブジェクト変数の最後にオブジェクト変数の挙動をしっかり理解できるようになるには、相応の学習時間が必要かもしれません。これを理解できずには自在にVBAを使いこなすことはできません。一度理解してしまえば、その挙動は至極当たり前に思えてきます。当たり前の挙動と思えるようになるまでは、オブジェクト変数を扱う時は常にその挙動に注意してVBAを書き進めるようにしてみてください。以下はオブジェクト関数に関する記事にになります、あわせてお読みください。見るTRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)無効な前方参照か、コンパイルされていない種類への参照です。Case)|VBA入門9.メッセージボックス(MsgBox関数)|VBA入門10.マクロとは?VBAとは?VBAでできること|VBA入門ホームマクロVBA応用編マクロVBA技術解説オブジェクト変数とは何かこのサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。アクセスランキングサイトマップ事業案内お問い合わせホームマクロVBA応用編マクロVBA技術解説オブジェクト変数とは何かこのサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。