解決済みの質問
シートのイベントプロシージャーが
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
となりますが
(ByVal Target As Range)部分は何なのでしょうか?
何のためにあるのかわかりません。
Private Sub Worksheet_SelectionChange()
End Sub
としたらエラーが返ってきました。
理由を教えてください。
よろしくお願いします。
投稿日時 - 2009-06-26 00:00:40
こんにちは
>Target=ActiveCell
>と言う認識でよろしいでしょうか?
#5でKenKen_SPさんが説明されていますが、補足です。
セルを一つだけ選択したときには、
Target=ActiveCell
と考えても問題ありません
しかし、複数の範囲を選択したときは、
Target=ActiveCell
はなりません。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
では
Target=Selection
です。
注!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
では
Target=Selection
成り立っていますが、そうでない場合もあります。
Selectionは「選択されている物」という意味です。
そのために、場合によって内容が異なります。
例えば、オートシェイプが選択されているときには、Selectionは選択されているオートシェイプになります。
以下のコードを試してみてください。
上段にTargetのアドレス
中段にActiveCellのアドレス
下段にSelectionのアドレス
が表示されます。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
MsgBox Target.Address & Chr(13) & ActiveCell.Address & Chr(13) & Selection.Address
End Sub
投稿日時 - 2009-06-28 11:17:44
お礼
試してみました!
すごいですね。
ありがとうございます。
投稿日時 - 2009-06-29 23:02:35
5人が「このQ&Aが役に立った」と投票しています
ベストアンサー以外の回答(5件中 1~5件目)
最初のご回答にあるとおり、単純に変更のあったセルを教えてくれるもの
程度の説明が良い気がします。これは、理屈じゃなくて、
「そのように作られているもの」
と理解した方が良いでしょう。そして、実際に使ってみることです。理屈は
使ってさえいれば、あとからついてきますので。言葉で理解しようとしても
時間がかかるだけです。ただし、
Target ≠ ActiveCell
ですよ。イコールではありません。
ActiveCell はどのような操作であっても必ず1つですよね? 仮に複数の
セルが選択されていたとしても。
対して、例えば A1:C10 の範囲を選択した場合、Target には A1:C10 セル
が参照されてきます。つまり
Target = Range("A1:C10")
ですね。アクティブセルは A1 かもしれない、けど選択されたセルは A1:C10。
A1 ≠ A1:C10
ですから、アクティブセルと同意ではありません。
投稿日時 - 2009-06-28 05:51:38
お礼
Targetは複数ですね
覚えます。
ありがとうございます。
投稿日時 - 2009-06-29 22:56:14
こんにちは。
最初に、あまり、そのような疑問は持たない方がよいです。聞いても良く分からないと思います。これを理解するために、C言語を勉強する、そうすると別の疑問が出てくる、また、オブジェクト指向の考え方を分からなくてはならない、と堂々めぐりになってしまいます。そういう私も、はっきり言って、このレベルは分かりません。
ただ、私の知っている範囲で初心者とか関係なく回答します。それは、私も初心者の頃があって、誠実に回答してくれない人たちがいました。自分が、分からないとしても、本物かそうでないかぐらいは分かりましたから。
こうしたものは、アプリケーションのクラス(設計図)の中にあるのだと思います。ExcelのCのコードを見たわけではありませんし、イベント・ドリブン型を作るプログラムの勉強をしたことがありません。それと、VBAでは、不安定ですが、まったく違う作り方をするからです。また、イベント・ドリブン型のクラスは、「お仕着せ」ですから、加工できません。
(ByVal Target As Range) 自体は、ByValは、値参照の引数の用語です。変数 Targetは、特に予約語ではないし、任意だけど、ユーザー変数と差別化をし、その変数名をイベント・ドリブン型の変数名として扱います。なお、ユーザーが、このTargetを変数で使うのはルールには外れています。その変数を、相手(アプリケーション)側の変数型を維持せずに、そのまま引数として取り込まないという、意味です。
Private Sub Worksheet_SelectionChange()
本来なら、クラスから、仕組まれてなければ、これはエラーになるはずがありません。エラーになるのは、Worksheet オブジェクトの中に、そういうクラスの仕組みがあるからです。
Private Sub MyWorksheet_SelectionChange() では、エラーが出ません。しかし、
'--------標準モジュール--------------
Public myClass As Class1
Sub Auto_Open()
Set myClass = New Class1
Set myClass.MyWorksheet = ThisWorkbook.Worksheets(1)
End Sub
'---------クラスモジュール(Class1)-------------
Public WithEvents MyWorksheet As Worksheet
Private Sub MyWorksheet_SelectionChange(ByVal Target As Range)
MsgBox Target.Address
End Sub
'--------------------------------------------
こうすれば、同じように、MyWorksheet は、イベント・ドリブン型となります。シートに組み込んだからです。Worksheet_SelectionChangeとは別の存在になります。なお、ByVal の部分を、ByRef(参照渡し)に書き換えても、これは、大元のアプリケーション側のクラスの設定ですから、エラーが発生します。理由は、Worksheet のクラスにはそのようなイベント・ドリブン型はないからです。
-------------------------------------
これはエラーが発生します。
Dim Target As Range 'モジュールスコープ
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Set Target = Target '外に出せない(変数名を変えればTest1には来る)
Call Test1
End Sub
Sub Test1()
MsgBox Target.Address 'Target は来ていない
End Sub
--------------------------------------
これなら、通ります。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Call Test1(Target)
End Sub
Sub Test1(Target As Range) 'Target を引数にする
MsgBox Target.Address
End Sub
--------------------------------------
どういうプログラムで送られているのか、私にはわかりません。
ByVal なのだから、Target のデータ型は、Range 型ではないかもしれないと思うので、
----------------------------------------
エラー発生
Private Sub Worksheet_SelectionChange(ByVal Target As Variant)
Private Sub Worksheet_SelectionChange(Target As Variant)
-----------------------------------------
ByVal というのは、相手から送られてきたデータ型を無視して、こちらの型にあわせるという意味と、相手から送られてきたデータを外に直接出さないということです。
Target は、単なる単語で、予約語でも何でもありませんから、
Target を myRng に換えてみました。
-----------------------------------------
これは通ります。
Sub Worksheet_SelectionChange(ByVal myRng As Range)
MsgBox Time
End Sub
------------------------------------------
これでも、コードが通ります。Private を付けておけば、よそからプロシージャを呼び出されることがありません。
結論としては、(ByVal Target As Range)は、Worksheetオブジェクトに仕組まれたクラスの中に、イベント・ドリブン型のコードがあるもので、Application から送られてきたものを、受け取る規定の引数=レセプタだと思います。
こんな話ではさっぱり分からないと思いますが……。
投稿日時 - 2009-06-26 11:01:57
お礼
まずイベントドリブン型がなんだかわからないので調べてみます。
一生懸命回答いただいたのに理解できないくてすいません 汗
ありがとうございます。
投稿日時 - 2009-06-29 22:00:21
こんなの自然にわかると思っていたが。
選択が変わったとき、
(1)変わったという事実も伝えてほしいのはもちろん
(2)どのセルで変わったか教えてほしいものだ
この(2)の役割を果たしてくれるのが ByVal Target As Range
で As Range はRange 易しく言うと内容はセルで知らせますと言うこと。MsgBox Target.Addressを入れてみると、数量的な目に見える形でセルの場所を表示できるようになる。
Private Sub Worksheet_SelectionChange()
End Sub
ここ()内(引数部分という)はユーザーが触るものでない。
この仕組みを作ったのはエクセルシステムでユーザーじゃない。他のイベントでこんな引数を返してほしいなあ、という場合も有るが、普通の技量ではどうしようもない。ユーザーが作るSUB、Functionプロシージァーなら自分で決めるのだから、ニーズによる。
質問者が作ったもので、引数を入れても入れなくても動くようにもかけるが質問者にとってずっと先のニーズだろう。
>ByValは概念的にByRefと対になっているが、VBAの上級に熟練するまでは、自分がプロシージュアーを作る場合のことで、ニーズが少ないだろう。気になるなら、GoogleでByRefで照会して記事を読むこと。
http://homepage1.nifty.com/CavalierLab/lab/vb/byvalbyref.html
など多数。
投稿日時 - 2009-06-26 09:54:06
お礼
よく読んでみます。ありがとうございます。
投稿日時 - 2009-06-28 18:36:49
こんばんは
>(ByVal Target As Range)部分は何なのでしょうか?
例えば、以下のプログラムを試してみてください。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
MsgBox Target.Address
End Sub
Targetには新たに選択させたセル(または範囲)が格納されます。
これによって、選択されたセルによって処理を変えることができます。
例えば
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Target.Value = "AAA"
End Sub
としておくと、選択したセルにAAAが表示されます。
Target.Row
Target.Column
Target.Address
などを使えば、特定の場所が選択されたときにだけ実行されるプログラムを作成できます。
>Private Sub Worksheet_SelectionChange()
>End Sub
>としたらエラーが返ってきました。
これは、
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
と「ByVal Target As Range」も含めて1つの「決まり文句」だと思ってください。
投稿日時 - 2009-06-26 00:31:14
お礼
ありがとうございます。
こういう使い方をするのですね。
Target=ActiveCell
と言う認識でよろしいでしょうか?
投稿日時 - 2009-06-28 00:42:57
OKWaveのオススメ
おすすめリンク