[[20130527014647]] 『複数のコマンドボタンの内容を一つにまとめる』(もんもん) ページの最後に飛ぶ

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

 

『複数のコマンドボタンの内容を一つにまとめる』(もんもん)

コマンドボタンA、B、Cがあります。
Aの内容はモジュールAに、Bの内容はモジュールBに、Cの内容はモジュールCに書いています。
モジュールAからCを一つにまとめ、すべてのコマンドボタンに同じマクロを登録し、コマンドボタンAを押した時にはAを、同様にBにはBを、CにはCを作動させる、ということは可能でしょうか?エクセル2003です。


 どこに配置したコマンドボタンなのでしょう?

 シートですか? それともユーザーフォームですか?
 投稿内容からですと、シートのそれ でしょうか?

 だとしたら、そのコマンドボタンは フォームのボタンでしょうか?
 もし、コントロールツールボックスのコマンドボタンを使っていたなら、
 フォームのボタンに変更してください。

 配置した三つのボタンには、同じプロシジャー名を登録してください。

 一つのプロシジャーで 押されたボタンによって処理を分けるためには、
 プロシジャーに押されたボタンが何なのか? が分かれば可能ですね!!

 仮に三つのボタンに登録したプロシジャー名がMacro1 だとすると、

 Sub macro1()
    Dim btnnm As String
    If TypeName(Application.Caller) = "String" Then
       btnnm = Application.Caller
       MsgBox btnnm
    End If
 End Sub

 このようにApplication.Callerプロパティを使うことでわかります。

 これを使って、処理を分けると良いと思いますよ。

 ボタンがユーザーフォームなら、クラスモジュールを使うことになります。
 こっちは、ちょっと大変ですが・・・。

 以上です。

 ichinose


 今回の目的はどういった理由からでしょうか。
 A,B,C がまったく異なる処理であれば、現在の状態のほうが自然だと思いますし、
 A,B,C が対象が異なる程度で殆ど同じ処理であれば、もう一歩進めて同じコードで複数
 処理をするようにした方が管理がしやすいですし、D や E が増えたときにも変更が楽だと
 思います。

 判断が付かず、コード量がたいしたことでなければ、提示してみてはどうでしょうか。
 (Mook)

 コントロールツールボックスのコマンドボタンと仮定して、
 
 Private Sub CommandButton1_Click()
     Call test("1")
 End Sub

 Private Sub CommandButton2_Click()
     Call test("2")
 End Sub

 Private Sub CommandButton3_Click()
     Call test("3")
 End Sub

 Private Function test(ByVal strFunc As String)
     MsgBox "Commandbuttun" & strFunc & "が押されました" '共通の処理
 End Function
 
私なら上記のように差のある部分だけ各コマンドボタンで処理して
引数だけ関数に渡して、関数で共通処理。
 
(みやほりん)

皆様、ありがとうございます。
ボタンはフォームボタンを使用しています。
以下にコードを表示します。

 Sub マクロA()
    If Intersect(Selection,Range("範囲")) Is Nothing Then Exit sub
  If Selection.Count <>  Intersect(Selection,Range("範囲")).Count Then Exit sub
    For Each r In Intersect(Selection,Range("範囲"))
        If r.Formula = "" Then r.Value  = "A"
    Next
 End if 

です。Aの部分がB,Cと変わります。作業内容は全く同じで、押すボタンによって選択範囲に何を入れるのかが変わっています。

現状、ボタンAにモジュールAを、ボタンBにモジュールBを入れているため、モジュールとボタンの数が同数あります。今後、上記内容のボタンが20まで増える予定です。これだとモジュールの数が多くなり、内容を少し変更するときに、20個も書き換えなければなりません。

なので、20のボタンに1種類のマクロを登録するが、ボタンAにはボタンAの仕事、BにはBの仕事、というようにしたいのです。

もんもん


 まず勘違いしていると思われるのは、マクロはモジュール内に複数記述できますので、
 プロシージャを増やしてもモジュールを増やす必要はありません。

 で、実装方法ですが ichinose さんの方法を採用すれば、下記のようにできますし、

 Sub 共通マクロ()
    If Intersect(Selection,Range("範囲")) Is Nothing Then Exit sub
  If Selection.Count <>  Intersect(Selection,Range("範囲")).Count Then Exit sub

    Select Case Application.Caller
    Case "ボタンA" : 設定値 = "A"
    Case "ボタンB" : 設定値 = "B"
    Case "ボタンC" : 設定値 = "C"
    Case Else
        MsgBox "クリックしたボタン名が定義されていません。"
        Exit Sub
    End Select

    For Each r In Intersect(Selection,Range("範囲"))
        If r.Formula = "" Then r.Value  = 設定値 
    Next
 End if 

 みやほりんさんの例なら、サンプルがそのまま応用できると思いますが、下記のように
 呼び出し側だけボタン数プロシージャを用意し処理の引数で渡すこともできます。

 Sub ボタンA()
     共通マクロ "A"
 End Sub

 Sub ボタンB()
     共通マクロ "B"
 End Sub

 Sub 共通マクロ( 設定値 )
    If Intersect(Selection,Range("範囲")) Is Nothing Then Exit sub
  If Selection.Count <>  Intersect(Selection,Range("範囲")).Count Then Exit sub

    For Each r In Intersect(Selection,Range("範囲"))
        If r.Formula = "" Then r.Value  = 設定値
    Next
 End if 

 いずれにせよ、モジュールは分ける必要もなく、一つで済むと思います。
 (Mook)

ありがとうございます。
ちなみにボタン名(フォームのボタン)は自分で確認や設定できるのでしょうか?
(探したのですが見つかりませんでした)
できるとすればどのように確認・設定を行えばよろしいでしょうか?

もんもん


 名前の確認変更は、ボタンを右クリックすると名前ボックスで表示・編集ができます。
 (Mook)

 >一つのプロシジャーで 押されたボタンによって処理を分けるためには、
 >プロシジャーに押されたボタンが何なのか? が分かれば可能ですね!!

 と Application.Callerを調べて、
 なんとか質問者さんにある程度完成されたコードの提示を期待していたのですが・・・。
 まっ、それはよしとしましょう!!

 ボタン名と設定文字列の情報をコード内に持ってしまうと
 ボタンを増やすたびにコードの修正が必要になってきます。
 又、ボタンの設定文字列の変更なんて事象が発生した場合もコードの修正が必要になってしまいます。

 コードの修正を頻繁に行えば、その分バグの発生率も増加します。
 この情報を何とかして、外にだす方法を考えてみてください。

 シートに内部情報としてそのボタン名と設定文字列の情報を持つという方法もあるでしょうね。

 外に情報を持っていれば、ボタンの増加や設定文字の変更によるコード変更は不要になります。

 一例です。

 新規ブックの標準モジュールに

 '===============================================================================
 Option Explicit
 Sub 準備()
    Dim r As Range
    With ActiveSheet
       .Range("b10:i20").Name = "範囲"
       Set r = .Range("b2")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .ShapeRange.AlternativeText = "A"
          .OnAction = "登録マクロ"
       End With
       Set r = .Range("c2")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .ShapeRange.AlternativeText = "B"
          .OnAction = "登録マクロ"
       End With
       Set r = .Range("d2")
       With .Buttons.Add(r.Left, r.Top, r.Width, r.Height)
          .ShapeRange.AlternativeText = "C"
          .OnAction = "登録マクロ"
       End With
    End With
 End Sub
 '===============================================================================
 Sub 登録マクロ()
    Dim ボタン名 As String
    Dim 設定文字 As String
    Dim rng As Range
    Dim crng As Range
    On Error Resume Next
    Set rng = Application.Intersect(Selection, Range("範囲"))
    On Error GoTo 0
    If Not rng Is Nothing Then

       If TypeName(Application.Caller) = "String" Then
          ボタン名 = Application.Caller
          設定文字 = ActiveSheet.Shapes(ボタン名).AlternativeText
          For Each crng In rng
             If crng.Formula = "" Then crng.Value = 設定文字
          Next
       End If
    End If
 End Sub

手順

 適当なシートをアクティブにして、準備 を実行してみてください。

 アクティブシートのセルB2,C2,D2にボタンが作成されます。

 ここでは、「範囲」というセル範囲は、b10:i20に設定しました。

 これを踏まえて、適当なセル範囲を選択後に、セルB2,C2,D2に作成されたボタンをクリックしてみてください。

 セルB2,C2,D2に配置されたボタンの設定文字列は、 それぞれ A,B,Cです。

 それぞれのボタンの設定文字列は、ボタン自身に設定しています。
 これは、準備 というプロシジャーを解析していただければ、わかると思います。

 ボタンへの設定文字の登録は、もちろん、手動操作でも簡単にできますから、
 調べてみてください。これだとボタンの増減でコードの変更は不要だと思います。

 検討してみてください

 ichinose


コメント返信:

[ 一覧(最新更新順) ]


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