[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『複数のコマンドボタンの内容を一つにまとめる』(もんもん)
コマンドボタン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.