- ベストアンサー
Excelシート内セル記述の違いについて・VBA
ワークシート内コードの記述で、 シート上のテキストボックスの値を変えています。 テキストボックスのChangeイベントで動かしていますが、起動した際や、他シートからテキストボックスのvalueを変えたりしています。 1.テキスト1.value = activesheet.range("a1") 2.テキスト1.value = me.range("a1") 3.テキスト1.value = range("a1") 3にすると上手く動かない場合があるので現在は2で記述しています。 1~3の違いはなんでしょうか・・
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>range("a1")とすると、activesheetのrangeになるのか、sheet1のrange("a1")になるのか・・ ActiveSheetです。Range("A1") は ActiveSheet.Range("A1") を省略した記述方法ですね。したがって、1と3は同意ですから、3の記述で「うまくいかない」のであれば、1の記述も「うまくいかない」はずです。 うまくいかない理由は、恐らくコードの実行過程で他シートを Activate する場合があり、 ActiveSheet が変わってしまうからではないですか? ctrlzr さんや Wendy02 さんのご指摘のとおり、シートを明示的に指定すれば良いと思います。 2の記述についてですが、シートモジュール下では、こう解釈されています。例えば、Sheet1にコードを記述した場合、 Me.Range("A1").Value は WorkSheets("Sheet1").Range("A1").Value と同意になります。したがって、2の方法ではOKなのです。Me キーワードの是非については、良くわかりませんのでコメントできません。 ただし、私も基本的に余計なトラブル回避およびコードの可読性向上の意味からシートを明示的に指定する記述をお勧めします。 EX) Worksheets("Sheet1").Range("A1").Value
その他の回答 (5)
- Wendy02
- ベストアンサー率57% (3570/6232)
tonjiruさん、こんにちは。 >有難うございます。色んなご意見があるんですね。 あまり、言葉に翻弄されないでくださいね。自分で試して、実証してみるのが一番です。 ExcelのVBAは、あるレベルになると、必要な部分とそうでない部分が分かるようになります。少なくとも、シート・オブジェクトの代わりのMeキーワードを、Me.Range("A1").Valueと書かなくてはならない場面は、少なくとも、Excel・VBAでは、そんなに多くは登場しないはずです。(私は知りません)Meキーワードは、Excel・VBAに関する限りは、通常、Class や Userformモジュールでしか使いません。 以下は、ご自分で、試してみてください。 >同じく「sheet1のシートモジュールで」 >range("a1")とすると、activesheetのrangeになるのか、sheet1のrange("a1")になるの >か・・ 例えば、 Sheet1モジュールに、以下のように書いて、 Sub test_1() MsgBox ActiveSheet.Range("A1").Value End Sub 標準モジュールに、このように書いて、Sheet1のプロシージャを呼び出してみます。 Sub calling_test() Sheet1.Select Call Sheet1.test_1 Sheet2.Select Call Sheet1.test_1 Sheet1.Select False Sheet2.Select False Call Sheet1.test_1 Sheet1.Select End Sub そうしたら、最初は、Sheet1のA1で、次に、Sheet2 のA1 ですね。最後は、Sheet2 ですね。 では、Sheet1モジュールに書いた以下のプロシージャの場合は、どうなるでしょうか? 次に、そのシートモジュールで書かれたものを、コピーして、次のように換えてみます。 Sub test_2() MsgBox Range("A1").Value End Sub これで、この答えはおわかりになったように、Sheet1のA1を指し示していますね。 これに、Me.Range("A1").Value と「Meキーワード」をつけても同じ結果です。 具体的に、オブジェクト名を付けないで、「Range("A1")」として使う特殊な例では、代表的なのはシートモジュールに設置するイベントプロシージャです。これは、通常、シートに属すイベントですから、Rangeの前のオブジェクト名が必要ありません。 また、シートモジュール上で、Sheet2のA1を示す方法としては、あまり芳しくはありませんが、 Sheet2.Select 'Worksheets("Sheet2").Select '一応、1行目と同義 MsgBox Range("A1").Value というようにすることも出来ますね。 ここで、一番の前提になるのは、何が良いとかではなくて、そのモジュールの使い分けなのです。ThisWorkbookにしか書けないもの、標準モジュールにしか書けないもの、クラスモジュール、UserFormモジュール、シートモジュールと、それぞれは、それぞれに即したプロシージャ特有のコードや書き方があります。 該当するシート・モジュールで、 >2.テキスト1.value = me.range("a1") >3.テキスト1.value = range("a1") すくなくとも、これは、同義であって、Meを付けたからエラーが出ないなんていうことは、私には考えられません。もし、エラーが出るとすれば、同じようにエラーが出るはずです。そして、また、該当するシートモジュール以外では、このような書き方が適用するとは思えないのです。 そのプロシージャのコードの単独の一行では、それが良い悪いなど分かりません。もし、気になるようでしたら、全体のコードを見せてもらわないと分からないのです。
お礼
詳しいご説明有難うございます。 me.はなんとなくAccsessのフォームをいじってた癖で必要なのかなと思っていたのですが、プロシージャによって書き方が異なるんですね。 とても参考になりました。
- Wendy02
- ベストアンサー率57% (3570/6232)
シートモジュールで、Meキーワードを、本当に使用しなければならないのでしょうか。 シートモジュールに書くコードは、限定的な意味を持ちます。ある程度、Excel VBAを書く人間だったら、多くの一般的に使うコードは、Excelの場合は、標準モジュールに書き込みます。ですから、そのプロシージャ内で、必要な場合、Worksheets、Sheets など、明示的にオブジェクトを入れます。あたりまえですが、オブジェクトを持たない標準モジュールでは、Meキーワードは使えません。 >シート上のテキストボックスに、 TextBox1.Value = Range("A1").Value これが悪いわけではなくて、書き込むモジュールの問題です。これを見て、エラーにならないで、値が表示するには、どこのモジュールに書くべきか、すぐ分かるレベルの人だったら、Me が何を指すのか分かるでしょうし、また、何をしたらエラーになるかも分かるはずです。また、シートモジュール内に、Meが必要か不要なのかも分かるはずなんですね。
補足
有難うございます。色んなご意見があるんですね。 えーと、つまりは 「sheet1のシートモジュールで」meを使用すると me.range("a1")=worksheets("sheet1").range("a1") と同じ意味になる? 同じく「sheet1のシートモジュールで」 range("a1")とすると、activesheetのrangeになるのか、sheet1のrange("a1")になるのか・・ そこのところはどうなんでしょう?? お答えを読み返してもよく分からなかったのものですみません。 ちゃんとすべてのコードを記述すればこんな問題は起こらない、という意見もごもっともです。
- ctrlzr
- ベストアンサー率29% (18/62)
Wendy02さん 質問者さん #一般的には書かなくて済むものは、書かないようにするのは、VBAではふつうだと思います。 そうなんですよね。ふつうなのが困ったところです。 書かないでハマることはあっても、書いてハマることはありえません。 これを機会に書くようにしてみてください。 #書かないプログラマーがいたんですが、 #ほんとに勘弁してください!て感じでした #直す私の方が大変^^;
- Wendy02
- ベストアンサー率57% (3570/6232)
この場合のRangeオブジェクトは、どこに属しているか、というと、Worksheetですよね。だから、Worksheetの配下(メンバ)として書きますね。 (オブジェクト・ブラウザで確認してみてください) どこのシートのメンバにあるのか明確なら、省いてよいですし、そうでないなら、書かなくてはなりません。Me はオブジェクトを持つモジュール自身を指し、UserFormや他のモジュールから実行する場合は、Meの代わりに対象オブジェクトを明示的(explicit)に指定します。 今回のようなWorksheetメンバのRangeの前に、特定のシートのRangeオブジェクトを指すために、Me を書くことができるのは、シート・モジュール下でしかありません。その時に、Me を書いても書かなくてもよいのですが、一般的には書かなくて済むものは、書かないようにするのは、VBAではふつうだと思います。 だから、特定の場所を指し示すために、他のモジュールからでは、 Worksheets("Sheet1").TextBox1.Value = Worksheets("Sheet2").Range("A1").Value と明示的に書かざるをえないのです。
- ctrlzr
- ベストアンサー率29% (18/62)
1.テキスト1.value = activesheet.range("a1") アクティブ(選択した前面)シートのA1 2.テキスト1.value = me.range("a1") ワークシート内コードの記述とのことなので、そのシートのA1 3.テキスト1.value = range("a1") 不明(アクティブシートかコードを記述したシートの何れか) コードを書くときは、所有者を明示するのは必須です。 (なにも省略しない) おすすめは、 テキスト1.value = me.range("a1").value(フォーマット付きなら.text) です。 activesheetも、ユーザー操作やコードで変わってしまうので、あまりお勧めできません。
お礼
最初に書くべきだったのですが・・・ Sheet1のテキストボックスで、 シートモジュールのテキストボックスchangeイベントでテキストボックスに入力されたものをrange("a1")に表示させています。(ここの書き方が疑問だったんです) Sheet2からテキストボックスの中身を変更したときにChangeイベントが動いてしまい、Sheet2の"a1"にデータが入ってしまいます。 というのが困った点でした。 で、「このシートの」という記述はあるのかなと思った次第なのであります。 サボり心がいけなかったのですね・・。 なるべく略さずシート名を書くようにします。 有難うございました。