• ベストアンサー

エクセルvba  (ByVal Target As Range)について

シートのイベントプロシージャーが Private Sub Worksheet_SelectionChange(ByVal Target As Range) End Sub となりますが (ByVal Target As Range)部分は何なのでしょうか? 何のためにあるのかわかりません。 Private Sub Worksheet_SelectionChange() End Sub としたらエラーが返ってきました。 理由を教えてください。 よろしくお願いします。

  • dfghhj
  • お礼率99% (432/434)

質問者が選んだベストアンサー

  • ベストアンサー
  • rukuku
  • ベストアンサー率42% (401/933)
回答No.6

こんにちは >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

dfghhj
質問者

お礼

試してみました! すごいですね。 ありがとうございます。

その他の回答 (5)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.5

最初のご回答にあるとおり、単純に変更のあったセルを教えてくれるもの 程度の説明が良い気がします。これは、理屈じゃなくて、   「そのように作られているもの」 と理解した方が良いでしょう。そして、実際に使ってみることです。理屈は 使ってさえいれば、あとからついてきますので。言葉で理解しようとしても 時間がかかるだけです。ただし、   Target ≠ ActiveCell ですよ。イコールではありません。 ActiveCell はどのような操作であっても必ず1つですよね? 仮に複数の セルが選択されていたとしても。 対して、例えば A1:C10 の範囲を選択した場合、Target には A1:C10 セル が参照されてきます。つまり   Target = Range("A1:C10") ですね。アクティブセルは A1 かもしれない、けど選択されたセルは A1:C10。   A1 ≠ A1:C10 ですから、アクティブセルと同意ではありません。

dfghhj
質問者

お礼

Targetは複数ですね 覚えます。 ありがとうございます。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんにちは。 最初に、あまり、そのような疑問は持たない方がよいです。聞いても良く分からないと思います。これを理解するために、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 から送られてきたものを、受け取る規定の引数=レセプタだと思います。 こんな話ではさっぱり分からないと思いますが……。

dfghhj
質問者

お礼

まずイベントドリブン型がなんだかわからないので調べてみます。 一生懸命回答いただいたのに理解できないくてすいません 汗 ありがとうございます。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

こんなの自然にわかると思っていたが。 選択が変わったとき、 (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 など多数。

dfghhj
質問者

お礼

よく読んでみます。ありがとうございます。

  • rukuku
  • ベストアンサー率42% (401/933)
回答No.2

こんばんは >(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つの「決まり文句」だと思ってください。

dfghhj
質問者

お礼

ありがとうございます。 こういう使い方をするのですね。 Target=ActiveCell と言う認識でよろしいでしょうか?

  • nattocurry
  • ベストアンサー率31% (587/1853)
回答No.1

>(ByVal Target As Range)部分は何なのでしょうか? >何のためにあるのかわかりません。 それまでと違うセルが選択されたときに、このイベントが発生します。 そのときに、どのセルが選択されたのか知りたいですよね? 選択されたセルがTargetになります。 Range("A1") や Cells(1, 1) と同じように使えます。

dfghhj
質問者

お礼

ありがとうございます。

関連するQ&A

  • 標準モジュールで 『Sub test(ByVal Target As Range)』は動かない?

    選択されている複数のアドレスが知りたいので 標準モジュールに Sub test(ByVal Target As Range) Debug.Print Target.Address End Sub と書きました。 しかしF5ボタンを押しても何も起こりません。 デバッグ→コンパイルをしてもエラーになりません。 シートのイベントプロシージャーではなく 標準モジュールにした理由は イベント発生時ではなく、任意で起動させたいためです。 ためしに、 Sub test(ByVal Target As Range) Debug.Print Target.Address End Sub の下に、 Sub test2() Call test End Sub と書いたら、 「引数は省略できません。」 というエラーになりました。 何がダメなのかわかりません。 ご教授よろしくお願い致します。

  • エクセル デバッグできるのとできないのがある

    シートイベントについて教えてください。 シートモジュールに --------------------------------------------------------- Option Explicit Private Sub Worksheet_Activate() MsgBox "" End Sub Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) MsgBox "" End Sub Private Sub Worksheet_Change(ByVal Target As Range) MsgBox "" End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) MsgBox "" End Sub --------------------------------------------------------- と記載した時に、 F8で動かせるのは、Worksheet_Activateだけなのですがなぜでしょうか? ほかのイベントは、F8で実行させても、OSの音が鳴るだけで、マクロの実行はされません。 ご回答よろしくお願いします。

  • なぜ、ByVal Sh As Objectは

    NewSheetイベントについて質問なのですが、 なぜ、ByVal Sh As Objectは、Objectなのでしょうか? Sub Workbook_NewSheet(ByVal Sh As Worksheets) や Sub Workbook_NewSheet(ByVal Sh As Worksheet) にしたら、コンパイルエラーになります。 シートの方では、 Private Sub Worksheet_Change(ByVal Target As Range) のようにrange型で宣言しているのに、なぜシートはオブジェクト型で宣言するのでしょうか?

  • VBAでエラートラップがうまくいきません。

    VBAで次のようなプロシージャを実行してみました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)   If Target.Value = " " Then          ~コード~   END IF END SUB すると複数のセルが選択されるとエラーがでます。そこで次のようにしてみました。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)   On Error GoTo エラー処理   If Target.Value = " " Then     On Error GoTo 0           ~コード~   END IF   EXIT SUB エラー処理:   EXIT SUB END SUB ところがこれでもやっぱりIF文のところでエラーがでます。 当方初心者でなぜエラーがでるのかわかりません。 わかりやすくご教授ください。 よろしくお願いします。

  • エクセルVBA/イベント発生でコピペ不能はなぜ?

    シートに以下のマクロを設定すると、そのシート内ではコピーしたもののペーストが不能になります。 どうしてでしょうか? Private Sub Worksheet_SelectionChange(ByVal Target As Range) Target.Interior.ColorIndex = 6 End Sub

  • Excel  関数をまたいだTargetの使用

    excel2013 OS はwindows8を使用しています。 Excelのマクロで、以下のコードについて質問です。(コード内の・・・は省略の意) Private Sub Worksheet_Change(ByVal Target As Range) Dim ・・・・・・・      ・      ・  If Target.Value = ・・・・・    Call myfunction End If End Sub Sub myfunction() If 条件 Then Target.Offset(0,1).Value = "aaa" End If End Sub このマクロのPrivate Sub Worksheet_Change(ByVal Target As Range)を実行するとエラーが 出ます。エラーの内容は「オブジェクト変数またはwithブロック変数が設定されていません」 となり、 Target.Offset(,1).Value = "aaa" の行が黄色く表示されます。 myfuncton内で使用しているTargetが何なのかがわからないというエラーだと理解しています。 そこで私は以下の2つを試しました。 1つめはうまくいかず、2つめは何か2度手間のような感じがするのですが、正常動作する ようです。 そこで質問なのですが、Targetをプロシージャをまたいで利用したい場合に一般的に用いら れている手法などがあれば教えて頂きたいです。 1つめ・・Targetをプロシージャをまたいで使えるようにコードの一番上の部分 、つまり、Private Sub Worksheet_Change(ByVal Target As Range)の一行上の 部分にDim Target As Range と宣言してみました。が、これはうまくいきませんでした。 2つめ・・適当な(この場合e)変数を宣言し、プロシージャをまたいで使用する。 Dim e As Range Private Sub Worksheet_Change(ByVal Target As Range) Dim ・・・・・・・      ・      ・  If Target.Value = ・・・・・ Set e = Target    Call myfunction End If End Sub Sub myfunction() If 条件 Then e.Offset(0,1).Value = "aaa" End If End Sub 以上何か良い方法があれば教えて頂きたいです。また不明な点があれば ご質問ください     

  • エクセルVBAで Cancel=Trueの使い方

    Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$A$1" Then Exit Sub Cancel = True MsgBox "キャンセルしました" End Sub Private Sub Worksheet_Deactivate() Cancel = True MsgBox "キャンセルしました" End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) Cancel = True MsgBox "キャンセルしました" End Sub 以上のように使ってみましたが、どれも「キャンセルしました」とメッセージは出るものの、直前の操作(入力、シート切替、セル移動)はキャンセルされませんでした。 どこが間違っているのでしょうか?

  • コンパイルエラー Target.Range

    シート上のセルに値を入力したら、 入力した値をイミディエイトに表示させたいのですが Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) Debug.Print Target.Range End Sub こうすると、 コンパイルエラー 引数は省略できません。 になります。 .Range の部分がエラーになります。 原因と対策を教えてください。

  • Excel VBA イベントプロシージャを2つ記述する(基本です)

    基本的な事なのですが、Excelのイベントプロシージャで2つプログラムを作るにはどうやって記述すればよいのでしょうか? 具体的には、worksheetのchangeイベントで、セルC5の値を変えた時と、セルG7の値を変えた時の2通りのマクロを作成したいのです。 Private Sub Worksheet_Change(ByVal Target As Range) C5を変えた時の処理 End Sub Private Sub Worksheet_Change(ByVal Target As Range) G7を変えた時の処理 End Sub このように書けばよいのでしょうか?そうするとTargetがかぶっておかしくなる気がします。。 お願いします。

  • エクセルマクロ(VBA)で指定したセルが変化したときに実行するには?

    VBAでsheetの中のworksheet_changeなどでマクロを書くと、そのシー トの中のどのセルを変化させてもマクロが実行されるのですが、これ を、A1とc1とc2が変化したときだけ処理を実行させたいのです。 以下のマクロのどこかを編集すると、そのようなことが出来るのでし ょうか? Private Sub Worksheet_SelectionChange(ByVal Target As Range) ----実行する内容---- End Sub Private Sub Worksheet_Change(ByVal Target As Range) ----実行する内容---- End Sub

専門家に質問してみよう