和風スパゲティのレシピ

日本語でコーディングするExcelVBA

RangeオブジェクトとRangeプロパティの違い

Rangeオブジェクトと、Rangeプロパティの違いを解説します。

同じところ

どちらも「セル」または「セル範囲」を扱います。

違うところ

一言で言ってしまえば、「Rangeオブジェクトを取得する、たくさんあるプロパティの中のひとつがRangeプロパティ」です。

もっと詳しく

↑の説明でわかる人はあまりこのページに来ないと思いますので、
詳しく説明していきます。


知ったからと言ってすぐに実務に活きるような話ではないので、
分からない部分は読み飛ばしながら、気楽に読んでください。


結構難しい話なので、見通しが立てやすいように先に最終目標から。

Range("A1").Value = 1
  • これってRangeオブジェクトですか?
  • それともRangeプロパティですか?

というのを説明するために、順を追って説明していきますね。

オブジェクト.プロパティ

まずはオブジェクトとプロパティが何なのかを簡単に。


このコードを見てください。

Worksheets(1).Name = "集計表"

何の変哲もない、シート名を変更するコードです。


このコード中の「.」に注目してください。


「.」は「の」と読むと理解しやすいです。
実際に↑の例でも、「第1シートの名前」と訳すことができます。


この「.」がプログラミングの世界ではかなり重要で、
「誰」の「何」を扱うかを指定する際、

.= "集計表"

という風に書けるように、すべての機能が整備されています。


プログラミングの世界では、この「誰」をオブジェクト「何」をプロパティと呼びます。


例えば↑の例

Worksheets(1).Name = "集計表"

を、きっちりした用語で書くと、

「Worksheetオブジェクト」である第1シートの、
「Nameプロパティ」に"集計表"を代入した。

と表現します。


ここまではOKですかね?

プログラミングをやる上では、この「オブジェクト」と「プロパティ」は重要なので、この機会に覚えてしまってください。


別に難しく考えなくていいです。

「誰の何」を、

オブジェクト.プロパティ

と書けるように、多くのプログラミング言語は作られていますよ。

というだけの話です。

セルを表すオブジェクト = Rangeオブジェクト

ここで本題のRangeに移りましょう。

Range("A1").Value = 1

このコードを↑の通り解釈すれば、Range("A1")はオブジェクトで、Valueがプロパティですね。


さて、さっきの「ワークシート」は「Worksheetオブジェクト」という名前のオブジェクトでしたよね。


じゃあ「セル」ってなんていう名前のオブジェクトなんでしょう?



この答えがまさに「Rangeオブジェクト」です。


まずここが紛らわしいポイントの第1弾なのですが、

「Cellオブジェクト」が集まって、「Cellsコレクション」ではないのです。
「Cellオブジェクト」が集まって、「Rangeオブジェクト」でもないのです。

1個のセルでも、長方形のセル範囲でも、飛び飛びのセルをカンマでつないだ複数セルでも、どれも「Rangeオブジェクト」なのです。


「Rangeオブジェクト」が集まったものも、「Rangeオブジェクト」なわけです。
「Rangeオブジェクト」の中には、たくさんの「Rangeオブジェクト」がいます。


ということで、ひとまず「セルやセル範囲ならなんでもRangeオブジェクト」です。
 

Cells(1, 1)

もRangeオブジェクトですし、

Range("A1")
Range("A1:C3")

も、もちろんRangeオブジェクトです。


これでひとつ謎が解けましたね。

Rangeオブジェクトを取得するプロパティたち

じゃあもう一つの謎、「Rangeプロパティ」って何なのでしょう?


正確ではない、ちょっと乱暴な説明になりますが、

Range("A1")

このコードの中で使った、

Range(      )

この関数っぽいものがRangeプロパティです。


Rangeプロパティの引数に、"A1"を渡して取得したA1セルが、Rangeオブジェクトと言うことです。


ここがめっちゃ紛らわしいんですよ。
名前が一緒だから最初はすごい混乱するんです。


これは↓の例を見ると、ちょっと整理できるかもしれません。

  • パスタを料理する
  • 料理を運ぶ
  • お母さんに電話する
  • お母さんの電話を買う

などと同じだと思ってください。


「名詞」と「動詞」に同じ単語が使われるのは珍しくないですよね?
それと一緒のことです。


料理(Rangeオブジェクト)を作ることを、
料理する(Rangeプロパティ)というわけです。


先ほどの説明の通り、
セルを表すオブジェクトは、Rangeオブジェクトしかありませんが、
セル(Rangeオブジェクト)を取得するプロパティはたくさんあります↓

Cells(1, 1)
Rows(1)
Columns(1)
Cells(1, 1).Risize(2, 2)

これらはみんな、Rangeオブジェクトを取得するプロパティたちです。


これも料理に例えると、「煮る」「焼く」「切る」みたいに、
「料理」を作る方法がたくさんあるような感じです。


そしてその中でもRangeプロパティは万能で、
↑のプロパティを全部自分でやってしまいます。

Range("A1")
Range("1:1")
Range("A:A")
Range("A1:B2")

 
これだけ万能だと仕方がないですね。

「煮る」「焼く」「切る」全部自分でやれるんですから、
紛らわしいですが「料理する」という、名詞そのものを名乗ることを許してあげましょう。


とこんな感じです。


最初の説明に書いた、

Rangeオブジェクトを取得する、たくさんプロパティの内の、
 もっとも万能なやつがRangeプロパティ

が、なんとなくでも伝わったでしょうか?


※ 「一番万能だったからRangeを名乗るのを許された」は私の妄想というか例えです。
  実際にMicrosoftさんがどう思ってRangeを名付けたのかなんて、もちろん私にはわかりません。

プロパティって右側なんじゃないの?

さて、これでRangeオブジェクトとRangeプロパティの説明はできたわけですが、
まだ一つ謎が残っています。

なぜこれをRange「プロパティ」と呼ぶのでしょうか。


一番最初の説明に戻りますと、

オブジェクト.プロパティ

これで「誰」の「何」でしたよね?


RangeプロパティもCellsプロパティも、
「プロパティ」というからには「何」にあたるわけです。


でも、

Range("A1").Value = 1

を見ると、Rangeはプロパティなのに左側にあります。


なぜでしょう?



答えは単純で、「ActiveSheet.」が省略されているからです。


Rangeプロパティは、より正確には
WorksheetオブジェクトのRangeプロパティ
ということです。


これが紛らわしいポイント最終章ですね。

オブジェクト.プロパティと、事は単純な話ではないのです。


「オブジェクトA.○○○○○B.プロパティC」とつながっているときは、

  • BはAにとってはプロパティ
  • BはCにとってはオブジェクト

というわけなんですよ。


これは家族に例えるとわかりやすいのですが、
オブジェクトとプロパティは、親子と表現されることもあります。

というか実際に、Parent(親)を使うと、

Range("A1").Parent

で親オブジェクトであるワークシートを取得できます。


それで、オブジェクトをプロパティのお父さんだとするじゃないですか。
でもお父さんだって、おじいちゃんから見れば息子ですよね?

それとおんなじ話です。


Valueのお父さんであるA1セルも、Worksheetの息子ですからね。

Worksheetおじいちゃんだって、Workbookひいおじいちゃんの息子です。

最終的には、家系図をたどったご先祖様である、Excel藩のApplicationオブジェクト大名から続く由緒正しいお家柄なわけです。


今回の話では、Worksheetオブジェクトの子であるRangeオブジェクトをRangeプロパティによって取得して、さらにその子であるValueプロパティに値を代入していたということです。

これですべての謎は解けたでしょうか?

まとめ

  • セルやセル範囲を扱うオブジェクトを「Rangeオブジェクト」と呼ぶ
  • Rangeオブジェクトを取得するためのプロパティが、親であるWorksheetオブジェクト内にたくさん用意されている
  • その中で一番万能なのが、オブジェクトと同じ名前のRangeプロパティ

というお話でした。


Rangeはすごく難しいオブジェクトですが、
逆にこれさえわかれば、VBAのオブジェクトはオールOKみたいなものです。


初読で完全に理解するのは難しいかもしれませんが、
まあ気長に付き合っていきましょう。

RangeはVBAの主役ですから、いやでも長い付き合いになりますよ(´∀`)

おまけ:ひとつ嘘をついてるので訂正します

さて、今回の話は難しすぎて、どうしても簡単にせざるを得ない部分で、ひとつ嘘をついています。

今までの話をすべて終えた今なら、なんとなくわかると思うので、一応訂正しておきますね。

一応というくらいなので、実務には全く関係ない、厳密な用語の定義の話です。適当に読み流してください。


単刀直入にどこが嘘だったかというと、

Range("A1")

これがRangeオブジェクトだと言いましたが、
厳密にはこれは「引数に"A1"を渡されたRangeプロパティ」です。


「このプロパティによって取得されるオブジェクトがRangeオブジェクト」
ですので、そもそもRangeオブジェクトではない上に、コードが実行されるまではRangeオブジェクトを取得してすらいません。


そもそも実際にActiveSheetがどうなっているかわかるまでは、
どのオブジェクトを指すかすら、わかりませんからね。


この延長の話で、あたかも「プロパティ」という実物があるかのように「家族の話」をしましたが、実際に家族をなしているのは「オブジェクト」です。

つまり親子関係なのは、
「オブジェクト-プロパティ」ではなく、
「親オブジェクト-子オブジェクト」です。

「どの子供を持ってくるか指定するのがプロパティ」なので、
プロパティそのものは子供ではありません。


もっと言えば、Nameプロパティだって、そういう実物があるわけではなく、
シートの名前を格納している値を見に行くだけの、どちらかと言えば変数ではなく関数です。


例えばコード上に、

Workbooks("テスト.xlsx").Worksheets("集計表").Range("A1").Value

こう書いてあるとします。


もちろんExcelさんの内部では「オブジェクト-オブジェクト-オブジェクト-値」が実際に紐づいていますが、このコード自体は、
「オブジェクトを返すプロパティ.オブジェクトを返すプロパティ.オブジェクトを返すプロパティ.値を返すプロパティ」
です。オブジェクトそのものを指したコードはありません。


「オブジェクトA.○○○○○B.プロパティC」とつながっているときは、

  • BはAにとってはプロパティ
  • BはCにとってはオブジェクト

とも書いていましたが、こちらも厳密には、
「オブジェクトAを返すプロパティ.オブジェクトBを返すプロパティ.値Cを返すプロパティ」
という仕組みになっているだけで、Bは生まれも育ちもオブジェクトです。
B自身がプロパティそのものになることはありません。


  • Excel内部にはプロパティなるものは存在せず、すべてがオブジェクトと値
  • コード上に書いてあるものは、すべてがオブジェクトや値を参照するプロパティで、オブジェクトそのものをコード上で指定しているわけではない

というのがある程度現実に即した説明ですかね。

ここまでくると完璧に正しいことを言えているのか、正直私も自信がありません。
そんなに外れてないとは思いますが。


と、まあ一応訂正はしましたが、普通に話をしている上では、

Range("A1")

これはもうオブジェクトでいいと思いますよ。

これをオブジェクトを返すプロパティって言う必要があるかというと…


この話は、厳密には、用語の定義とは、レベルの話です。


原子は物質の最小単位とか言っておきながら、電子とか陽子とか出てきて、最後はリプトンだかレプトンだか紅茶が出てくるみたいな話に近いと思います。



ということで、嘘を訂正するといっておきながらやっぱり嘘で締めますが、

  • Range("A1") … オブジェクト
  • Range( ) … プロパティ

で、実務上はOKだと思います。

この違いを認識できることは、ちゃんと実務に役立ちます。


これ以上先の話は、学者様の領域と思っておいても、
別に困ることはないと思いますよ(´∀`)