[[20101209011132]] 『Rangeオブジェクトの既定のプロパティについて』(ichinose) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『Rangeオブジェクトの既定のプロパティについて』(ichinose)

[[20101203205934]]

 ↑ここで興味深いご質問に投稿している過程でふと沸いてきた疑問です。
 というか、きちんと理解しないまま、今日まで来てしまったので
 皆さんにご質問することにしました。

 (このリンク先長いです。ここを読まなくても問題を理解していただけるよう
 精一杯記述しますので、よろしくお願いします。
 もちろんリンク先は、それは興味深い内容ですが・・・)。

 Rangeオブジェクトの既定のプロパティって、何なのでしょうか?

 Helpで、RangeオブジェクトからCellsプロパティを調べると
 「Item プロパティは、Range オブジェクトに対する既定のプロパティであるため、
 Cells の後に続けて行および列のインデックスを指定できます」

 とあって、Itemプロパティが既定のプロパティである記述されています。

 確かに

 Range("a1:c2").item(1,2) は、
 Range("a1:c2")(1,2) と記述できるので間違いないことなのでしょうが・・・。

 HelpでItemプロパティを更に調べると、
 「オブジェクトを返すプロパティです。セル範囲 (Range オブジェクト) を返します。」

 expression.Item(RowIndex, ColumnIndex)
 書式は↑で、RowIndexは、必須入力であると記述されています。

 又、既定のプロパティを検索してみると、
http://vba-range-cells.seesaa.net/article/158086978.html

(3)値の取得および設定が可能で、バリアント型 (Variant) の値を使用するようです。

 値の取得や設定もできるらしい。

 いったいどういうことなのでしょうか?

 疑問1

 本来なら、
 Range("a1") の既定プロパティは、item(1) で表せる Rangeオブジェクト
 では、Item(1)というRangeオブジェクトの既定のプロパティは、item(1) で表せる Rangeオブジェクト。

 range("a1").item(1).item(1)・・・・、いつまでたっても値がでてこないはずですが、

 でも、

 sub test()
  Range("A1").Value=1
    msgbox range("a1").item(1).item(1)
 end sub

 新規ブックの標準モジュールにて、上記を実行すれば、1と値が表示されます。
 Itemプロパティで取得したRangeオブジェクトの既定のプロパティは、特別にValueを
 返すのでしょうか?

 疑問2

 Sub test2()
    Dim a As Variant
    Dim b As Variant
    Range("a1:b2").Value = [{1,2;3,4}]
    a = Range("a1:b2").Value
    b = Range("a1:b2")
    MsgBox "変数 aは、" & TypeName(a)
    MsgBox "変数 bは、" & TypeName(b)
    Erase a, b
 End Sub

 上記のtest2を実行すると

 変数aは、Variant()
 変数bは、Variant()

 と表示され、配列要素も同じ値を持ちます。

 これを見ると、Rangeオブジェクトの既定のプロパティは、Valueプロパティではないか?
 と思える結果が表示されます。

 でも、Item プロパティは、Range オブジェクトに対する既定のプロパティなのです。
 いったいどういうことなのでしょうか?

 b = Range("a1:b2")

 を既定のプロパティ Itemを使って省略しないでを記述すると、どうなるのでしょうか?

 教えてください。

 実は、オブジェクトブラウザでRangeを調べた結果、私なりの結論らしきものはでました。
 でも、皆さんのご意見もお聞きしたく投稿をしました。

 よろしくお願いします。

 ichinose

  

 

   


 こんにちは。 さっそくですね・・・
 私なりの現時点での考察を。

 >b = Range("a1:b2") 
 >を既定のプロパティ Itemを使って省略しないでを記述すると、どうなるのでしょうか?

 たぶん、そのまま書こうとすると

 b = Range.Item("A1:B2")

 こうなると思いますが、これではそもそも「コンパイルエラー」になります。
 そこで

 b = ActiveSheet.Range.Item("A1:B2")

 とするとコンパイルは通りますが、実行すると
 「実行時エラー'450':引数の数が一致していません。または不正なプロパティを指定しています。」
 となります。

 ん?・・・ItemはRangeのプロパティではない?
 結果

 b = Range(Cells.Item(1, 1), Cells.Item(2, 2))

 のようにしないとaと同じにはなりませんでした。(他にも方法あるかな?)
 ItemプロパティはRangeオブジェクトのプロパティなのに?

 で、私も先日から調べていましたがichinoseさんと同じようにオブジェクトブラウザとヘルプで
 あれ? と思う事が。

 RangeもCellsもItemも「Rangeオブジェクトを返します」とありますね。
 で、オブジェクトブラウザにはRangeオブジェクトのメンバーにRangeプロパティがあったんですね。

 で、今までの認識を覆すような私なりの考えてる事は

 Range("a1:b2") のような書き方って、それ自体がRangeオブジェクトのインスタンスを生成している
 ように見えますが、実はExcel.Activeworkbook.ActiveSheetに対するRangeプロパティを取得している
 だけなんじゃないか? で、返された結果がRangeオブジェクトなだけで・・・

 とすると

 Sub test5()
    Range("a1:b2").Value = [{1,2;3,4}]
    Range("A3:B3") = Range(Cells.Item(2, 1), Cells.Item(2, 2))             'Empty
    Range("A3:B3") = Range(Cells.Item(2, 1), Cells.Item(2, 2)).Value       '値
    Range("A3:B3").Value = Range(Cells.Item(2, 1), Cells.Item(2, 2))       'Empty
    Range("A3:B3").Value = Range(Cells.Item(2, 1), Cells.Item(2, 2)).Value '値
    Range("A3:B3") = Range("A2:B2")             'Empty
    Range("A3:B3") = Range("A2:B2").Value       '値
    Range("A3:B3").Value = Range("A2:B2")       'Empty
    Range("A3:B3").Value = Range("A2:B2").Value '値
 End Sub

 こんな結果になるので、私の解釈としては
 左辺はRangeオブジェクト、右辺のRangeはRangeプロパティの返り値
 なので右辺のRangeの規定のプロパティは存在しない?

 でも、そうすると・・・
 >a = Range("a1:b2")
 これって、なぁに? と疑問がループしちゃいます。

 う〜ん・・・難しい。
 もう少し考えてみます。

 (momo)

 こんにちは。
 >疑問1
  >新規ブックの標準モジュールにて、上記を実行すれば、1と値が表示されます。
  >Itemプロパティで取得したRangeオブジェクトの既定のプロパティは、特別にValueを
  >返すのでしょうか?

 range("a1").item(1)はヘルプに記載のようにRangeオブジェクトであり
 MsgBox Range("a1").Item(1, 1)
 は、MsgBoxの引数promptに渡されるときに値(value)が文字列へ変換されるのではないでしょうか。
 どのように渡される(代入)かは仕様だと思います。

 >疑問2
  >上記のtest2を実行すると
  >変数aは、Variant()
  >変数bは、Variant()
  >と表示され、配列要素も同じ値を持ちます。

 b = Range("a1:b2")のRange("a1:b2")はプロパティが記述されていないのでRangeオブジェクト、
 Variantのbへ代入されるのでVariant()となる仕様では。
 MsgBox "変数 bは、" & TypeName(b) & " " & TypeName(Range("a1:b2")) 

 >b = Range("a1:b2") 
 >を既定のプロパティ Itemを使って省略しないでを記述すると、どうなるのでしょうか?

 Rangeオブジェクトを渡すならそのまま、
 既定メンバを渡すなら b = Range("a1:b2").[_Default]()
 これはValueプロパティの処理を行うことになるので b = Range("a1:b2").Value
 と同じことだと思います。

 以下サイトを参考にしました。
 E10C001  Rangeの既定メンバとプロパティの省略 
http://www2.aqua-r.tepm.jp/~kmado/kcolumn.htm
 (sasa)

 _Defaultなんていう非表示メンバがあるのですねぇ
 勉強になります。
 (momo)

 ichinoseさん
  その節は、ご教示ありがとうございました。
  ちょっとしたショックがあり、ようやく立ち直って、そろそろ
  あのトピックを新しい視点で読み返してみようと思っていた矢先です。
  
  土日までに理解しておけば間に合うであろう、と思っていたのですが。。
  まぁ、読み返したところで、今回のご質問の結果で変更を余儀なくされるでしょうから、
  無駄な抵抗 → 止めておいて方が省エネ

 sasaさん
  そっ、その参考サイト、もっと早く知りたかったです。
  Rangeオブジェクトの既定プロパティが非表示だったなんて、がっくしです。

  と云う事は、ヘルプ『既定プロパティはItem・・・云々』は真っ赤な嘘ってことですね。
  話が全然違ってきてしまう。^^
  
 ※ その記事では、EmptyになったのはXL2000からとなっていますが、
   前回の実験でXL97から起きていることは確認しています。
   また、ヘルプで確認すると、XL97でも非表示メンバーに _Default がありました。
   Itemの方の説明は「値のみ取得可能」となっています。

 そうなると、ますますこのアドバイスは嘘くさくなってきました。
            ↓
 >「Valueプロパティは、RangeオブジェクトのDefalutプロパティではない」

  (Valueが既定プロパティであったとしても)  
 「省略したらオブジェクトが渡り、即Empty処理になる」が正しそう。
  既定プロパティを云々すべきフェーズ(シーン)は生じない。

 > range("a1").item(1).item(1)・・・・、いつまでたっても値がでてこないはずですが、
 左辺に変数があれば値を渡す仕様であり、MsgBoxも値を要求しているので
 同様の処理がなされる、と考えます。

 何を要求されているか(値かオブジェクトか)を判断しているのは、
 プロシージャ解析プログラム(コンパラ?)だと思います。

 「値」を要求された場合の具体的処理は、
 RangeオブジェクトのValueプロパティ(get側)をCallする形に
 なっているであろうと推測します。
 それ以外は、オブジェクト(参照アドレス)を渡すのみ。

 疑問2は、左辺が変数で、値を要求しているから。
 これは私としてはすごくシンプルに考えております。

 > b = Range("a1:b2") 
 > を既定のプロパティ Itemを使って省略しないでを記述すると、どうなるの
 一番悩ましかったこの疑問は、Itemが既定プロパティじゃなかったので
 「疑問として成立しない」と云うことになります。

 (半平太) 2010/12/09 16:42

 皆さん、投稿ありがとうございます。
 momoさんへ
 >私も先日から調べていましたがichinoseさんと同じようにオブジェクトブラウザとヘルプで
 私は、昨日、非表示メンバを表示して、_Defaultを偶然にも発見したときは、
 霧が晴れた感じでした。
 選択したときに 「 Excel.Range の既定メンバ」と表示されているものね!!
 ただ、何故Itemプロパティだけ既定のプロパティと取り上げたのだろう
 なんて考えてたら、まだ検証が必要かなあ と慎重になっていましたが、

 sasaさんのご紹介の角田さんのサイトで説明されているなら、もう安心です。

 現状、Rangeオブジェクトは、既定のプロパティを2種類持っていることになりますね。

 これで半平太さんのスレッドの現象は私的には、納得です。

 sasaさんへ
 リンクありがとうございます。
 これで私も裏づけが取れました。
 _Defaultの発見で原理は解決です。ありがとうございます。

 調べてみると、結構の数のオブジェクトが、_Defaultというプロパティを持っていますね。
 現状は、規定のプロパティが一つの値又は、オブジェクトでも
 将来的に既定のプロパティの追加が出来るような設計になっているんですね!!
 助かりました。ありがとうございます。

 半平太さんへ
 >ちょっとしたショックがあり
 私も半平太さんのスレッドの最後の投稿で受け狙いで投稿した内容が
 原因で現在、妻とケンカ中・・・。さて、どこでしょうか?
 更迭された法相だって、受け狙いだったんだろうなあ、こういうタイプは損するなあ・・。

 それはともかく・・・、
 >「省略したらオブジェクトが渡り、即Empty処理になる」が正しそう。
 これ、例えば
 range("a1")=range("a2:c3")

 このような例のことですか?

 だとしたら、省略したらオブジェクトが渡り、既定のプロパティのValueが
 配列否かの何らかの場合わけはしているはずですよ!!
 配列だったら、Empty その他値があれば、代入 

 最後にもう一度おさらい・・・・。

 Rangeの既定のプロパティは、_Defaultである。

 _Defaultに引数を付ければ、Itemオブジェクトが返り、
 引数を付けなければ、Valueが返る。

 半平太さんが立てたスレッドがなければ、
 このRangeの既定のプロパティのことなど、Valueの認識でほとんど問題ないじゃない!! 
 まだまだ、_Defaultの存在を知ることが先になったかもしれません。

 この事を調べる機会を持たせてくれたスレッドに関わっていただいた方に
 感謝します。ありがとうございました。

 ichinose


 こんにちは〜 
 有意義なスレッドに感謝です。

 解決後のようですが、遅まきながらぼくも一言 m(_ _)m
 sasa さんのご紹介してくださったk窓さんのコラムで、もやもや立ち込めていた霧が
 一気に晴れ渡ってきた感じです、ありがとうございました。

 > 結論としてExcel.Rangeの既定メンバの省略に付いては、
 > 代入(=)の左辺はプロパティを省略しても良く、
 > 右辺及び左辺以外(引数等)は プロパティを省略出来ないということになります。
 >   r1 = r2.Value
 > これを既定メンバを省略した書き方で
 >   r1 = r2()
 > とする事が出来ます。ちょっとおしゃれです。
 > 
 > Sub range_cool()
 >   Dim r1 As Range, r2 As Range
 >   Set r1 = Range("a1:c3")
 >   Set r2 = Range("d1:f3")
 >   r1 = r2()
 > End Sub

 左辺はr1と書いても
    [Let] r1[.Value] = 
 の意味なんですね?

 ぼくのなかのまだ晴れない霧... としまして、以下の疑問が残ります。
 では 左辺 Rangeオブジェクトに 右辺Rangeそのものを代入できるのか? ってことです。

 Sub てすとkana()
   Dim r1 As Range, r2 As Range
   Set r1 = Range("a1:c3"): r1.ClearContents
   Set r2 = Range("d1:f3") : r2.Value = [{"D1","E1","F1";"D2","E2","F2";"D3","E3","F3"}]
   Set r1 = r2         '→ エラーにはならないが、なにも起こらない
   MsgBox r1.Item(r1.Count).Value 
 End Sub

 ワークシートをみていると、セルには値は表示されません。
 しかし r1内の各セルには値がコピーされているようです。

 これ どう説明したら??

 (kanabun) 2010/12/09(木) 21:10 頃


 > これ どう説明したら??

 あ、すみません。
 r1(の参照先)に r2の参照先と同じものがセットされる、ということで、
 なんの問題もないんですね

  失礼しました m(_ _)m

  (kanabun)  スレ汚し すみません m(_ _)m


 >原因で現在、妻とケンカ中・・・。さて、どこでしょうか?
 男が読むと、そうそう、そうだねって感じですよ。

 それにしても、奥さんもこんな頭の痛くなるやり取りをウォッチしているんだぁー。
 当家では考えられません。

 >>  (Valueが既定プロパティであったとしても)  
 >> 「省略したらオブジェクトが渡り、即Empty処理になる」が正しそう。
 >>  既定プロパティを云々すべきフェーズ(シーン)は生じない。
 >
 > 省略したらオブジェクトが渡り、既定のプロパティのValueが
 > 配列否かの何らかの場合わけはしているはずですよ!!
 > 配列だったら、Empty その他値があれば、代入

 私の説は、一部表現不備、一部は正しく、一部は不明、と考えます。

 <表現不備>
 即Empty処理になる。
 ↑
 「複数要素で構成されているか判断されて、複数ならEmpty処理になる」と云うべきでした。

 <正しいと思う部分>
  既定のプロパティがValueだとしても、オブジェクトで渡ってからの話なので、
  そこで(値)配列ですよと申告したところで、証文の出し遅れであり、Emptyにされてしまう。

  従って、例のアドバイス「valueは既定のプロパティではない(からEmptyになるんだ)」は正しくない。
  たとえ、valueが既定のプロパティだとしても、右辺で省略してしまってはEmptyになるしかない。

 <不明と思う部分>
  オブジェクトで受けたものを「左辺のvalueプロパティ(Let)」で処理する過程では、
  当該オブジェクトが複数かどうかだけが問題視されているとみています。

  受けたオブジェクトの既定のプロパティを作動させ、その結果が配列であるかどうかを
  見て判断しているとは(私的感覚では)考えにくいです。

 (半平太) 2010/12/09 22:34

 >複数要素で構成されているか判断されて、複数ならEmpty処理になる
 この複数要素って、指定オブジェクトのことですよね?
 例えば、

 range("a1")=range("a2:b2") 
 'この右辺が、range("a2:b2").Count>1
 '正確には、range("a2:b2").Areas(1).Count>1 
 ということですね?

 でも・・・。

 私が作成した Valueという既定のプロパティだけを持った
 Clsというオブジェクトでは、

 > もう一つ例
 >
 > Sub test3()
 >    Dim cls As New Class1
 >    cls.value = Array(1, 2, 3, 4)
 >    Range("a2").value = cls.value
 >    MsgBox Range("a2").value
 > End Sub
 > Sub test4()
 >    Dim cls As New Class1
 >    cls.value = Array(1, 2, 3, 4)
 >    Range("a2").value = cls
 >    MsgBox Range("a2").value
 > End Sub
 >
 > 例題として作成したClass1(既定のプロパティ付)で
 > test3,test4の結果が違いました。
 > test4では、Emptyが返ります。
 > やっぱり、既定のプロパティが配列か否かを見ているのかなあ

 test3では、セルA2には、1が入っています。

 オブジェクトが配列(複数)かが判断 ではないと思います。

 ichinose


 もう一つ、例が必要でしょうか?

 Sub test5()
    Dim cls As New Class1
    cls.value = 1
    Range("a2").value = cls
    MsgBox TypeName(Range("a2").value)
 End Sub

 既定のプロパティが配列でなければ、右辺にclsを指定しても
 Emptyにはなりません。

 右辺に指定できるオブジェクトは、Rangeオブジェクトだけではないですよね?

 ichinose


 やっぱり、前のトピックをおさらいしないとダメみたいです。 <(_ _)> (トホホ)

   > Sub test4()
   >    Dim cls As New Class1
   >    cls.value = Array(1, 2, 3, 4)
   >    Range("a2").value = cls
   >    MsgBox Range("a2").value
   > End Sub

  確かに、clsの既定プロパティをみていないと、Emptyは返せませんでした。

  私も、遅ればせながら『霧が晴れました。』\(^o^)/

  今回の ichinoseさんの質問も、私の為にやっていただいた様なものです。
  有難うございました。

 しっかし、当初、私レベルでは理解も程遠く且つ無価値にも思えた
 「既定プロパティを持つクラス cls 」が、今回、決定的な証明ツールに
 なってくれた訳で、あれがなければ、まだ推測の海域を漂っているのでは
 ないかと感じます。 感服しました。

 (半平太) 2010/12/09 23:59

 >kanabunさんへ
 せっかく投稿していただいたのに、コメントなしで失礼しました。
 昨夜のkanabunさんの投稿、きっとすぐに勘違いに気づかれるだろうと思い、
 見ていたら速かったですね、修正投稿・・・。
 たまに質問投稿すると、わかりますね、質問者の気持ちが・・・。
 何らかの投稿があると、うれしいものです。

 また。よろしくお願いします。

 ichinose


 ichinose さんへ、

 > せっかく投稿していただいたのに、コメントなしで失礼しました。

 とんでもございません。 
 お気遣いいただき恐縮しています。
 またレベルの低い「便乗」質問をしますので、そのときは叱ってやってください m(_ _)m

 今回はとくに、スレッドの質問文の書き方についてもとても勉強になりました♪
 ありがとうございました。

 (kanabun)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.