• 締切済み

(エクセルVBA)セルを左クリックしたら実行させるには?

エクセルVBA初心者です。 下のように、同じシート内のコードとして2つのサブプロシージャがある状態なのですが、 シート内のどこかのセルを左クリック→指示(1) シート内のどこかのセルを右クリック→指示(2) のようにするにはどうしたらいいのでしょうか? (この状態だと、右クリックすると選択範囲が変わったことが優先的に認識されて指示(1)のほうが実行されてしまうようです。) 説明不足かもしれませんが、何を説明していいのか分からないので、補足が必要だったら言ってください。すみませんがよろしくお願いします。 --------------------------------------------------------------- Private Sub Worksheet_SelectionChange(ByVal Target As Range) 指示(1) End Sub --------------------------------------------------------------- Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) 指示(2) End Sub ---------------------------------------------------------------

みんなの回答

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

補足、修正 同様の内容がありましたので、以下は修正します。 ×現在は、日本語がなくなりました。この内容は、プログラマーズガイドという本のダイジェスト版です) ×http://msdn.microsoft.com/en-us/library/aa189065(office.10).aspx    ↓ http://msdn.microsoft.com/ja-jp/library/cc326739.aspx VBA コードを最適化する

shuffle2
質問者

お礼

大変参考になりました。 どうもありがとうございました。 お礼が遅くなり、大変失礼いたしました。

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

こんばんは。 直接の回答ではありませんが、一般的なアドバイスをさせていただきます。これは押し付けがましいので、不愉快になったら、申し訳ありません。もし、よかったら、私の経験的なものですが、納得するものだけを採用してくださったら良いかと思います。 ・暗黙のプロパティは、書かないほうがよいです。  Cells(1,1) や Range("A1") と書くと、自動的に.Value プロパティが選択されますが、8年くらい前のテキストには、それでよかったのですが、入れたほうがよいです。Office TANAKAの田中亨氏のサイトでは、曖昧な書き方になっていますが、おそらく、内容が古いままになっているのだろうと思います。別に、VBAのスピードを上げることと、暗黙のプロパティでよいということは、直接関係ありません。 今回は、関係がありませんが、もし英語が読めるのでしたら、以下のサイトを参考にしてください。非常にためになります。(以前は、日本版がありましたが、現在は、日本語がなくなりました。この内容は、プログラマーズガイドという本のダイジェスト版です) http://msdn.microsoft.com/en-us/library/aa189065(office.10).aspx    いろんなコードを書いていると、Value, Value2, Text という、使い方によってプロパティの違いを付ける必要がある時があります。   ・わたし流の書き方では、Borders は、Array(8,9,10,11) などとして、数値でループさせます。( For Each --- In Array(***) ) ・ここの掲示板では、区別の付かない人がほとんどですが、Sheets と Worksheets の違いは、つけたほうがよいです。ふだん、その違いでトラブルが発生することはありませんが、区別は付けたほうがよいです。 ・VBAエキスパート試験などには良く出てくる内容ですが、  Dim a, b, c, d As Integer  というような書き方は、新しい VB.Net の書き方で、VBAでは使われません。a, b, c までは、Variant 型です。すべて、Integer にする場合は、    a As Integer, b As Integer, c As Integer, d As Integer という書き方にします。  ・長いコードは、標準モジュールにおいて、ローカルモジュールから Call させます。   それは、ローカルモジュールとグローバルモジュールのメモリ負担の分散だと、私は思っています。多少みにくくなりますし、かなり大きなシステムですと、補助ツールが必要になってしまいます。(例:COMアドイン:MZ-Tools 3.0 http://www.mztools.com/index.aspx ドイツ)     ・Range("A1").Value = Empty と IsEmpty(Range("A1").Value) =True の違いは分かりますか?私は、ワークシートのセルでは、最近は、Range("A1").Value ="" と書いています。理由は、Variant 型には、Empty値, Null値 などがありますが、それは、VBAネイティヴで使うものものだと考えているからなのです。スタイルは自由ですが、私は差別化して使っています。   ・イベントの引数のTarget は、ほとんどは、ActiveCell と同等です。ただし、Target.Count =1 とするか、または、Target.Cells(1) で、ActiveCell と同じになります。通常は、引数、Target を利用させます。  ・私は、通常は、Win32 APIは避けて使っています。それは、新しい資料がなく、元は、C言語からで、なかなか本当に理解できないのです。また、代表的なWebサイトはなくなってしまいました。今後、.Net Framework に以降することが決まっているのと、WMI スクリプト が応用できるので、使えるものは、なるべくそちらを使うようにしています。しかし、.Net Framework は、Office 2003 以降ですが、Office 2007 でもまだ完全対応していません。しかし、次の次世代のOffice は、対応していくことは間違いありません。  

shuffle2
質問者

お礼

大変参考になりました。 どうもありがとうございました。 お礼が遅くなり、大変失礼いたしました。

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

こんにちは。 ここの掲示板では、多くは質問は仕事や家庭で、実用で使うためのものと想定して解答しています。ですから、実験コードなど、それ以外の目的の時は、あらかじめ、最初におっしゃっていたほうが良かったです。マインスイーパということを言わないと、回答者をミスリードさせることになってしまいます。 それに、マインスイーパを良く観察したほうがよいです。どういう構造になっているのか、きちんと観察していれば、私たちが書いていたようなコードにはなりません。まず、できる・できないをお聞きになって、設計の方法からお尋ねになったほうがよいです。まったく違った状態にあるものを似せるほど難しいものはありません。 マインスイーパは、そのボタンひとつひとつが、コントロール(Active X)であり、右クリック、左クリック・イベントを持ったものです。そのクリックによって表示を変えたりします。VBAでも、同じようなものは可能です。しかし、VBAの上級の知識を持っている必要があります。探せば、コードもVB系で手に入ったはずです。(VBAの上級レベルでも、他の言語では初級レベルです。)

shuffle2
質問者

お礼

大変参考になりました。 どうもありがとうございました。 お礼が遅くなり、大変失礼いたしました。

shuffle2
質問者

補足

大変申し訳ありませんでした。最初から伝えるべきでした。次回以降質問するときには、回答者の皆様のミスリードを招かないようもっと気をつけます。 もともと、自分の仕事で使うような初級のVBAは学習し終わったので、今度はマインスイーパなどの複雑そうなコードを、Active Xを使わずに書くことはできないかな~?などと思い、始めたことでした。 現段階で、↓のような状態にあるのですが・・・ (キケンなものは含まれていませんが、自己責任で実行してください。) http://www.dotup.org/uploda/www.dotup.org0289.xls.html 今のところ、右クリックで旗を立てることは出来ません。 あと、爆弾以外の全部のパネルを開いてもゲームが終了したことを伝える機能はまだ入れていません。

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

こんばんは。 BeforeRightClick イベントとSelectionChange イベントとは、もともと、その目的の趣旨が違いますから、等価のアクションの意味を持たせることはできません。勘違いされている方が多いと思いますが、必ずしも、SelectionChange イベントが先に立って、次に、BeforeRightClick イベントに来るということでもありません。クリックされる側が、純粋のControl オブジェクトなら、こんなことはないのですが。 以下の場合は、SelectionChangeで、マウスを監視しているだけです。右クリック・イベント自体は、あくまでも、ダミーで、右クリックを押したときに、Cancel を入れるためだけです。#1さんのおっしゃるとおり、Excelワークシートのセルには、クリックイベントはありませんから、厳密には、無理があります。 'シートモジュール Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)  Cancel = True End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim fL As Long Dim fR As Long Dim LR As Integer  If GetAsyncKeyState(vbKeyRButton) < 0 Then   LR = 0  Else   LR = 1  End If  ColorChange Target, LR End Sub Function ColorChange(rng As Range, LR As Integer) If rng.Count > 1 Then Exit Function If rng.Value = "" Then Exit Function '文字がないときは、除外 If rng.Interior.ColorIndex = 3 Then   rng.Interior.ColorIndex = xlNone   If LR = 1 Then    rng.Font.ColorIndex = 6   Else    rng.Font.ColorIndex = 5   End If End If End Function なお、私個人ならは、単に、Ctrl +1 , Ctrl+2 のショートカットを作っているでしょうね。

shuffle2
質問者

お礼

お礼が大変遅くなってしまい申し訳ありません。 GetAsyncKeyStateという関数について初めて知りました! これでうまくいきそうな気がしますが、まだ使いこなせなそうなので、GetAsyncKeyStateについてよく勉強してからチャレンジしてみようと思います。 No.4さんへのお礼にも書きましたが、実は遊び半分でエクセルでマインスイーパを作っていたらこんな問題に出くわしてしまった次第です。ですのでなるべくマウス1つで動くような、そのまんまなマインスイーパを作ろうと、無駄に努力しているところでしたが、これで完成するかもしれません。どうもありがとうございました。

  • don9don9
  • ベストアンサー率47% (299/624)
回答No.4

指示(1)と指示(2)を実行するための条件が共通であるなら (例題「セルの色が赤であれば」のように) セルが条件を満たしているかどうかのフラグを別に定義し、 SelectionChangeイベントで 1.まず、フラグをOFFにする 2.セルが条件を満たしている場合、指示(1)を行う 3.フラグをONにする BeforeRightClickイベントで 1.フラグがONの場合、指示(2)を行う 2.フラグをOFFにする というふうに組み立ててみてはどうでしょうか。 質問者様の挙げた例だと、以下のようなコードになります。 Private Flg As Boolean '←フラグ Private Sub Worksheet_SelectionChange(ByVal Target As Range) Flg = False 'フラグをクリア If Target.Interior.ColorIndex = 3 Then 'セルの背景が赤の場合 Target.Interior.ColorIndex = xlNone '背景を無色にする Target.Font.ColorIndex = 6 'フォントを黄色にする Flg = True 'フラグを立てる End If End Sub Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) Cancel = True If Flg = True Then 'フラグが立っている場合 Target.Font.ColorIndex = 5 'フォントを青にする End If Flg = False 'フラグをクリア End Sub 厳密に言えば 左クリック時→指示(1)を実行する 右クリック時→指示(1)を実行した後、指示(2)を実行する (例で言うと、右クリック時は一旦黄色にした後、青にする) ということになりますので、 指示(1)(2)の内容次第では使えない方法かもしれませんが…

shuffle2
質問者

お礼

お礼が大変遅くなってしまい申し訳ありません。 なるほど、私の挙げた例の場合、確かに教えていただいた方法で出来そうです。知恵を絞っていただきありがとうございました。 ただ・・・実は今回作成しているのは、Windowsに付属の単純なゲーム「マインスイーパ」です。このゲームをエクセルで再現してみようと思い、VBAの勉強がてら、楽しみ半分で作っているものです。(最初から言えばよかったのですが・・・。) マインスイーパをそのまま再現しようとすると、 左クリック時・・・ そのセルが爆弾だったら、背景を赤にして”◎”を入力し、他の爆弾セルにも”◎”を入力する。 そのセルが爆弾の隣だったら、背景を白にして周囲にある爆弾の個数を入力する。←A そのセルが爆弾の隣でなかったら、背景を白にして、周囲の8セルも背景を白にする。←B 周囲の8セルについてAとBの作業を繰り返す。 右クリック時・・・ そのセルの値がemptyなら”☆”(旗のマークの代わり)を入力する。 そのセルの値が”☆”なら”?”を入力する。 そのセルの値が”?”ならemptyにする。 という複雑な命令を実行させなければなりません。 う~ん、ムリなのでしょうか・・・。

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

こんにちは。 >多分私はまだまだ慣れや経験がないせいで、代案を思いつくことができないのでしょう・・・。 ご質問者さんに、そうしようとは言っておりません。今の私のVBAのある程度は、掲示板のベテランの方たちから教わったことです。そういうことは、順番に伝わっていくものだと思いますし、また、私なども提供できるものがあるかと思います。 >デフォルトである「背景色なし」の状態 >任意のセルを左クリックしたとき、そのセルの背景色が赤なら、文字色を黄にして背景色xlNoneにする。 >任意のセルを右クリックしたとき、そのセルの背景色が赤なら、文字色を青にして背景色xlNoneにする。 これは、単なるロジックの問題ではないでしょうか。クリックのどちらでも、背景色を消して、文字の色を変えるということではありませんか? 文字の色を赤にした後は、背景色は関係なくなってしまいますが、結局は背景色を消してしまうことなら、赤の文字色なら、青に変えることでも同じことではないでしょうか。 Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)   Cancel = True   If Target.Interior.ColorIndex = 3 Then    Target.Interior.ColorIndex = xlNone   End If   If Target.Font.ColorIndex <> 3 And _     Target.Font.ColorIndex <> 5 Then     Target.Font.ColorIndex = 3   ElseIf Target.Font.ColorIndex = 3 Then     Target.Font.ColorIndex = 5   Else     Target.Font.ColorIndex = 1 '最後は黒に戻す   End If End Sub

shuffle2
質問者

補足

少し違うように思います。 >結局は背景色を消してしまうことなら、赤の文字色なら、青に変えることでも同じことではないでしょうか。 いいえ、No.2の補足で書いた内容を書き換えると 背景色が赤であるセルが選択された時、 まず背景色を消す。  それが左クリックによる選択であったならば、   文字色を黄に。  あるいはそれが右クリックによる選択であったならば、   文字色を青に。 (背景色が赤以外であった場合は何もしない) ということになります。が、私には「それが左クリックによる選択であったならば、」を表すような「If ~ then」が思いつきませんでした。 なので代案として、「SelectionChange」と「BeforeRightClick」を使って2つのサブプロシージャに分けてみたら、右クリックの場合も「SelectionChange」として認識されてしまうため困ってしまった、というわけです。 適切な回答なのに解釈が間違っていたらごめんなさい。

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

こんにちは。 別に、SelectionChangeとRightClick の共存は、コードの書き方で解決はしますが、大事なことは、「何をするのか」ということです。右クリックと左クリックで範囲を選択するのか、まったく別のマクロの処理をするのか、とか。 >「右クリックの場合は終了」 どうやら、関連性があるようにも思えるのですが、右が先で、左が後だとか、どちらに優先性があるのか、そういうことが分からないですね。 もうVBAも10年以上、多くの人たちに研究尽くされていますから、だいたいのことは、可能かどうかは分かります。思いつきは良いけれども、また、その代案というか、ある程度決まったパターンというのもあるかと思うのです。入門レベルの人ほど、難問が多いように思います。

shuffle2
質問者

補足

多分私はまだまだ慣れや経験がないせいで、代案を思いつくことができないのでしょう・・・。申し訳ないですが以下の通りということでよろしくお願いします。 各サブプロシージャ内にある指示は100行以上の複雑なものになってしまっているので、自分なりに簡単な例にして提示してみます。 前提:エクセルのデフォルトである「背景色なし」の状態から、ある条件のセルだけ背景色が赤に変更されている状態からスタートします。 任意のセルを左クリックしたとき、そのセルの背景色が赤なら、文字色を黄にして背景色xlNoneにする。 任意のセルを右クリックしたとき、そのセルの背景色が赤なら、文字色を青にして背景色xlNoneにする。 以上のことをしたいのですが、右クリックしても、セルが選択されたことが優先されてしまい、文字色は黄になってしまいます。

  • marbin
  • ベストアンサー率27% (636/2290)
回答No.1

直接の回答ではないです。 >SelectionChange これはいま選択しているセルから 別のセルを選択したときに発生するイベントです。 セルにはクリックイベントというのはありません。

shuffle2
質問者

お礼

迅速な回答ありがとうございます。 ”右クリックしたこと”が”選択範囲が変わったこと”よりも優先的に認識されてくれればいいのですが、何かしらの方法で出来ないものですかねぇ・・・。 たとえば、 Private Sub Worksheet_SelectionChange(ByVal Target As Range) のすぐ下の行に、「右クリックの場合は終了」みたいな文章を入れられればOKなのかな~と思うのですが・・・う~ん。

関連するQ&A

  • エクセルマクロ(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

  • エクセル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 としたらエラーが返ってきました。 理由を教えてください。 よろしくお願いします。

  • どこが間違ってますか? (エクセルVBAです)

    質問をご覧くださりありがとうございます。 どなたか助けていただけないでしょうか。 以下のコードの場合、B2セルをダブルクリックすればシート(1)が開くと思っていたのですが、B2以外のセルをダブルクリックしてもシート(1)が開いてしまいます。 どこが悪いのでしょうか。 詳しい方がいらっしゃいましたら、どうか教えてください。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, cancel As Boolean) If Target = Range("B2") Then cancel = True Worksheets("シート(1)").Activate End If End Sub どうか、宜しくお願いいたします。

  • Excelシート上で右クリックができない

    Excelのシート上で右クリックをしても、ショートカットメニューが 表示されなくなってしまいました。 気になる点としては、下記のようなコードを記述し、ショートカット メニューを削除したことがあるのですが、影響はありますでしょうか? Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) For Each num In Application.CommandBars("Cell").Controls num.Delete Next End Sub 現在は、下記のようにしていますが、状況は変わりません。 ちなみに、下記コートをすべて削除しても状況は変わりません。 ブックを新規作成しても、表示されません。 シートの保護はしていません。 Windowsのデスクトップなどではショートカットメニュは表示されます。 VBE上でも表示されます。 Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)   Application.CommandBars("Cell").Reset 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 以上のように使ってみましたが、どれも「キャンセルしました」とメッセージは出るものの、直前の操作(入力、シート切替、セル移動)はキャンセルされませんでした。 どこが間違っているのでしょうか?

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

    シートイベントについて教えてください。 シートモジュールに --------------------------------------------------------- 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の音が鳴るだけで、マクロの実行はされません。 ご回答よろしくお願いします。

  • エクセル VBA セルの色をSheet1とSheet2の両方を変えたいのですが・・・

    最近困っているところが表題の通りなのですが Sheet1のB2を右クリックするとB2のセルの色を変えて Sheet2のB2のセルも色を変えたいというものです。 現状で Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean) Dim Rng As Range, myRng As Range Dim RngA As Range, myRngA As Range Set Rng = Range("B3:W3,b7:w8,b12:w12,d13:w13,d17:w18,d22:w23") Set myRng = Intersect(Target, Rng) If myRng.Interior.ColorIndex = xlColorIndexNone Then myRng.Interior.ColorIndex = 37 Else If myRng.Interior.ColorIndex = 37 Then myRng.Interior.ColorIndex = 45 Else myRng.Interior.ColorIndex = xlColorIndexNone End If End If Cancel = True End Sub とここまではあるのですが、これをどう改造すればSheet2の同じセルの色もかわるのでしょうか? 宜しくお願いいたします

  • Excel2000 VBA ダブルクリックで別シートの同番地セルへ移動

    sheet1とsheet2 の2つのシートがあります。 sheet1のA1セルをダブルクリックすると、sheet2のA1セルへ移動させたいのですが、 下記のコードで実行すると、 'Range'メソッドは失敗しました:'_WorkSeet'オブジェクト のエラーメッセージが表示されました。 どうぞアドバイスお願い致します。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)   Sheets("sheet2").Select   Range("Target.Address").Select End Sub

  • VBAにおけるセルの名前の参照方法

    現在、Aシート、Bシートがあり、BシートのA1セルに test という名前を付けました。(範囲はブック) Aシートが再計算されれば、BシートのA1セルをメッセージボックスで表示したいのですが、調べましたが、よくわかりませんでしたので、詳しい方教えてください。 範囲はブックになっているし、他に同じセルの名前もつけれないようになっているので、 このような記述で大丈夫かと思いましたがエラーが出でしまいました。 なぜでしょうか?やはりわざわざ毎回シート名から記述が必要なのでしょうか? Private Sub Worksheet_Change(ByVal Target As Range)      MsgBox (Range("test").Value) End Sub このようにシート名から書けば表示されました。 Private Sub Worksheet_Change(ByVal Target As Range)      MsgBox (Worksheets("B").Range("test").Value) End Sub

  • エクセルVBA ダブルクリックした左隣の値を返す方法

    いつもお世話になっております。 あるワークシートにおいて、 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, _ Cancel As Boolean) If ActiveCell.Column = 7 Then Target.Value = "希望" End If End Sub というマクロを記述することができました。 今度は、 G列のどこかのセルをダブルクリックすると、 同じ行のE列の値が、 ダブルクリックしたセルに入るようにしたいのです。 どのような記述をすればよいのか ご教示ください。

専門家に質問してみよう