こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

VBAのクラスのインスタンス化のタイミングについて

こんにちはvbaのクラスのインスタンス化について質問があります。

私は普段使えないイベントを使用するときにクラスモジュールに
WithEventsを使ってイベントを作成し

それをプロシージャからインスタンス化して
作成したイベントを有効にするという手法をよく使います。

Excelのように最初からワークブックにイベントがある場合は、
ワークブックを開いたと同時にWorkbook_Openプロシージャから
クラスをインスタンス化して作成したイベントを有効にするということが可能なのですが、

CATIAやInventorなど、一部のアプリケーションでは、
最初から使えるイベントが見つからず、
Subプロシージャでインスタンス化する方法しかみつかりません。

しかし、Subプロシージャを実行させるためには、
ボタンなどユーザー側に何らかのアクションとってもらうしかなく、
自動化するために作成したイベントなのに、そのイベントを有効にするために
ユーザーにボタンを押してもらうという矛盾した構成になってしまいます。

クラスをインスタンス化する方法はSubプロシージャに記述するしかないのでしょうか?

自分がよく使っているコードを下に記述します。
下の例は、Excelで新しくブックを開いたときにメッセージを出すプログラムです。

アプリケーションレベルのイベントをクラスモジュールで作成しています。
これを有効にするためには標準モジュール内の
Event_ONプロシージャを実行しなければなりません。
モジュールを実行する前まではいくら新しいブックを開いてもメッセージは出ません
これをどのうようにしたらいいかご教授ください。

Excelの例
Classモジュール「Class1」に記述
--------------------------------------------------------------------
Private WithEvents APP As Application

Private Sub APP_NewWorkbook(ByVal Wb As Workbook)
MsgBox "新しいブックが開かれました"
End Sub

Private Sub Class_Initialize()
Set APP = Application
End Sub
--------------------------------------------------------------------

標準モジュール「Module1」に記述
--------------------------------------------------------------------
Dim CLS As class1
Public Sub Event_ON()
Set CLS = New class1
End Sub
--------------------------------------------------------------------

投稿日時 - 2015-05-20 12:28:14

QNo.8978516

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

#1-2です。

> InventorやCATIA

設問をきちんと理解せずにお応えしてしまっていたようです。
質問を読むことは日頃から大事に考えているつもりなのですが、
他所の別件の質問と混同してしまっていたみたいです。
すみません。
InventorやCATIAに関して、私にお答えできることは、ありませんでした。
申し訳ありません。大変失礼いたしました。

投稿日時 - 2015-05-25 17:15:23

ANo.2

#1です。
編集ミスがありましたので、訂正です。

誤)
Classモジュール「Class1」に記述
--------------------------------------------------------------------
Public Sub Event_ON()
  If CLS Is Nothing Then
    Set CLS = New class1
  End If
End Sub
--------------------------------------------------------------------

正)
標準モジュール「Module1」に記述
--------------------------------------------------------------------
Dim CLS As class1
Private Sub Event_ON()
  If CLS Is Nothing Then
    Set CLS = New class1
  End If
End Sub
--------------------------------------------------------------------

以上のように訂正をお願いします。
失礼しました。

投稿日時 - 2015-05-20 19:02:08

ANo.1

こんにちは。

通常は、

ThisWorkbookモジュール「ThisWorkbook」に記述
--------------------------------------------------------------------
Private Sub Workbook_Open()
  Application.OnTime Now, "Event_ON"
End Sub
--------------------------------------------------------------------
のようにします。
普通にEvent_ONをCallしても良さそうですが、
Excelブック側の各種インスタンスが揃い、必要な再計算などが終った後に、
(例えばAuto_Open等、他のイベントトリガーを優先させて、その後ろにおキューを置く)
他のプロシージャとは独立して実行させる為に、
application.OnTime メソッドを使う方がトラブルフリーになります。
これで、ブックを開けば、Event_ONが実行されるようになります。
もしも、作業中(ブックが開いている間)に、
  ●VBE画面でリセットボタンを押す
  ●デザインモードに切り替える
  ●エラー処理を逃れたエラーダイアログから[終了]を選ぶ
等の状況によって、VBProjectがリセットされた場合は、
CLSのインスタンスも解放されてしまいます。
こういった場合の復旧まで考慮に入れるなら、

Classモジュール「Class1」に記述
--------------------------------------------------------------------
Public Sub Event_ON()
  If CLS Is Nothing Then
    Set CLS = New class1
  End If
End Sub
--------------------------------------------------------------------
のように書いておいて、

ThisWorkbookモジュール「ThisWorkbook」に記述
--------------------------------------------------------------------
Private Sub Workbook_WindowActivate(ByVal Wn As Window)
  Application.OnTime Now, "Event_ON"
End Sub
--------------------------------------------------------------------
等、、
運用に合わせて適当な既存のタイミング(トリガ)を、
Workbook_Openの代りに、選んでみて下さい。

因みに、以上の例に合った形にするなら、
Private Sub Event_ON()
のようにスコープを変更した方が、紛れがなくなり、ベターです。

以上です。

投稿日時 - 2015-05-20 14:04:03

お礼

返事が遅くなりまして申し訳ありません。
Excelの場合は、「WindowActivate」のように最初から使えるイベントがあるので問題はないのですが、
InventorやCATIAの場合、デフォルトで使えるイベントの中にイベントが存在しておりません。
そこで、デフォルトのイベント以外で自動でインスタンス化する方法を探しておりました。
ほかにもEXCELの場合においてもイベント以外のやり方はいろいろあるようなので、
InventorやCATIAでも同様の方法がないか探してみます。

解答ありがとうございました。

投稿日時 - 2015-05-25 15:08:04

あなたにオススメの質問