アプリ版:「スタンプのみでお礼する」機能のリリースについて

ThisWorkbookのコードを書く場所や
Sheetのイベントプロシージャーが実行されるところに

Sub test()
MsgBox "あああ"
End Sub

と書いて実行するとメッセージボックスが表示されます。
クラスモジュールとフォームのイベントプロシージャーを書くところではできませんでした。

ということはSUBプロシージャーは
標準モジュールでなくてもいいのでしょうか?

A 回答 (3件)

こんにちは


 標準モジュールに書けば、ブック中のどのシートでも使えるプロシージャになると思います。
 一方、Sheetに書くとそのシートからフォーカスが他のシートに移ったとたんにエラーとなることで判るようにSheetの中でしか使えませんよね。
 プロシージャを標準モジュールに書いて保存するときに「*.xla」に指定してアドインでエクセルに組み込むとどのブックでも使用できるプロシージャになります。

 ということで、プロシージャーを書く場所で使用時のスコープ(有効範囲)が変わります。
    • good
    • 0
この回答へのお礼

なるほど。
ありがとうございます。

お礼日時:2009/07/03 21:34

Subは、標準モジュール内だけとは限りませんよ。


各シートでのイベントプロシージャは、そのVBAのソースコードを見てみると「Private Sub」という記述があると思います。Subは、「Public Sub」の省略系です。
これらのプロシージャの意味は、その名のとおり、局所的なものと、公のものであるという意味で、A88No8さんが書かれているように、それぞれ影響範囲(スコープ)が異なります。

Privateは、その名のとおり、局所的なスコープになり、シートで宣言している場合には、そのシートのみで有効なプロシージャとなります。Publicは、公のものではありますが、エクセルのVBAでは、標準モジュール以外(シートやフォームなど)での宣言は、PrivateもPublicも同じく扱われるはずです。(つまりは、シートやフォーム内のプロシージャからしか呼び出せない)
    • good
    • 0
この回答へのお礼

難しいですがよく読んで理解してみます。
ありがとうございます。

お礼日時:2009/07/03 22:49

こんにちは。



>クラスモジュールとフォームのイベントプロシージャーを書くところではできませんでした。

標準モジュール
Public myClass As Class1
Sub SetClass()
Dim myClass As New Class1
myClass.test1 'myClass オブジェクトのメソッドになる
End Sub

Class1

Sub test()
MsgBox "あああ"
End Sub

'これで通ります。
------------------------------
'UserForm モジュール
Private Sub CommandButton1_Click()
 Call test2
End Sub

Sub test2()
MsgBox "あああ"
End Sub

---------------------------------

>SUBプロシージャーは標準モジュールでなくてもいいのでしょうか?

Excelの場合は、オブジェクトが複数あるのが建前なので、SUB/Function プロシージャは、標準モジュールに書くのが基本的です。それ以外の場所に書くときは、それそれの必要性によって書きます。標準モジュール以外に対して、何でもよいわけではありません。

簡単にいうと、親オブジェクトの違いということになります。シートモジュールなどは、その直接の親オブジェクトの配下で動くことになっていますから、そのままにすると、親オブジェクトに直結しています。例えば、Cells(1,1) と書いても、標準モジュールの場合は、Activesheet ですが、シートモジュールは、書いたモジュールのシートが親オブジェクトになっています。シートモジュールで省略すれば、その範囲が限られてしまいます。

シートへのイベントなど、基本的には、そのシートしか使わないので、Private とつきますが、他の場所から呼び出さないということを理由にしているからです。他から呼び出して、不都合があるかどうかは、個人で使う分にはあまり大差はないと思います。

-------------------
シートモジュール側にPrivate が付いていなければ、
 Worksheets("Sheet1").Test1
 または、
 'Call Worksheets("Sheet1").Test1

で、Sheet1のマクロをどこからでも呼び出せます。

エラーになるのは、親オブジェクトを考慮していないから、不整合が起こるからです。
シートモジュールに、

 With ActiveSheet '←標準モジュールでは、親オブジェクトを考えなくてよい
 MsgBox .Cells(1, 1).Value
 End With
--------------------
シートを替えても、このようなコードですと、元のシートモジュールの親のシートのセル情報しか得られない。

MsgBox Cells(1,1).Value

--------------------

ThisWorkbook は、そのブックの玄関のようなもので、Open, Before_Close など、必ず、起動するとき、終了するときに、そこを通っていきますから、それを利用してあげればよいのです。標準モジュールは、家族が集まる、居間のようなもので、そこは、シート・モジュールを直接名指ししなくても、動きます。

また、クラスモジュールは、計画表や設計図のようなところです。設計図だけでは何も起きません。一度、イスンタンスを作ってあげないと動きません。

なお、Sub の前につける Private キーワードは、よそのモジュールから呼び出せませんが、シートモジュールにつけるPrivate ステートメントは、Option Private Module と書く方法は、標準モジュールにつけるもので、他のプロジェクトから呼び出せないようにするものです。

しかし、私の不勉強かもしれませんが、変数に関しては、Private/Public とか、そのモジュールのみに範囲を指定するとか、全体に対して、範囲を拡大するとか、標準モジュールに書く場合に、スコープに関係していますが、プロシージャに関しては、単に、マクロのCall (呼び出し)に関係するものだと解釈しています。
    • good
    • 0
この回答へのお礼

なかなか難しいので勉強してみます。ありがとうございます。

お礼日時:2009/07/04 14:55

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!