Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


468 / 2272 ツリー ←次へ | 前へ→

【11549】エクセルのイベント取得 pon 10/3/26(金) 18:20 質問[未読]
【11550】Re:エクセルのイベント取得 YU-TANG 10/3/27(土) 12:18 回答[未読]
【11551】Re:エクセルのイベント取得 pon 10/3/28(日) 15:05 質問[未読]
【11552】Re:エクセルのイベント取得 YU-TANG 10/3/28(日) 15:42 質問[未読]
【11553】Re:エクセルのイベント取得 pon 10/3/28(日) 18:16 質問[未読]
【11554】Re:エクセルのイベント取得 YU-TANG 10/3/29(月) 8:16 回答[未読]
【11555】Re:エクセルのイベント取得 pon 10/3/29(月) 12:44 お礼[未読]

【11549】エクセルのイベント取得
質問  pon  - 10/3/26(金) 18:20 -

引用なし
パスワード
   よろしくお願い致します
エクセル2003
WINXP

希望の動作

アクセスのデータシートフォームの
左端にあるレコードセレクタ部分のダブルクリックで
サーバー上の指定のエクセルブックを開きます

開いたブックで
 セル値変更時
 ブック保存時
 等のイベントを取得して、特定データを取得したいと思っています
 
参考HP
◆ WithEventsキーワードとは
tp://chaichan.web.infoseek.co.jp/vbtips/VBMemo2007012701.htm

Microsoft Excel 11.0 Object Library を参照設定

-----------------------------------------------------
Class1モジュール

Option Compare Database
Option Explicit

Private WithEvents xlsApp  As Excel.Application
Private bokWork       As Excel.Workbook
Private shtSheet      As Excel.Worksheet


Private Sub Class_Initialize()

  Set xlsApp = CreateObject("Excel.Application")
  Set bokWork = xlsApp.Workbooks.Open("\\sv_hoge\fuga.xls")  
  
  xlsApp.Visible = True
  
  Set shtSheet = bokWork.Worksheets(1)
  
  bokWork.Activate
  Debug.Print bokWork.Name
  
  shtSheet.Activate
  Debug.Print shtSheet.Name
  
End Sub

Private Sub Class_Terminate()

End Sub


Private Sub xlsApp_SheetChange(ByVal Sh As Object, ByVal Target As Excel.Range)

  MsgBox Sh.Name ’取得できません

End Sub

Private Sub xlsApp_WorkbookOpen(ByVal Wb As Excel.Workbook)

  MsgBox Wb.Name  ’取得出来ました

End Sub


-----------------------------------------------------
標準モジュール
Sub TG_BK_open()

  Dim objClass1 As Object
  Set objClass1 = New Class1
  
End Sub



標準モジュール TG_BK_open
を実行すると
ブックは開き
xlsApp_WorkbookOpen は取得できましたが

xlsApp_SheetChange Sh.Name は取得できませんでした


ブックの保存時
セルの変更時
を取得するにはどうすればよいでしょうか

また
ブックの上書き保存後のアクセス側の処理は別途必要でしょうか


エクセルブックのマクロブックの分離もままならない
クラスモジュールもほとんど?
のレベルです

アドバイスよろしくお願い致します

【11550】Re:エクセルのイベント取得
回答  YU-TANG  - 10/3/27(土) 12:18 -

引用なし
パスワード
   こんにちは、YU-TANG です。

変数の有効期間を理解されていないのが原因ではないでしょうか。
一度 VBA のヘルプで「変数の有効期間の概要」を検索して読んでみると
参考になると思います。

プロシージャ内で宣言された変数の寿命はそのプロシージャの実行中だけ
ですから、提示されたコードの objClass1 は一瞬で解放されてしまいます。
これが原因です。

対策として、たとえば objClass1 をモジュールレベルで宣言するように
してはいかがでしょうか。
もっとも「kb408871」で検索すると出てくるような話もあるので、
いかなる状況でも保証できるものではありませんが。

それでは。

【11551】Re:エクセルのイベント取得
質問  pon  - 10/3/28(日) 15:05 -

引用なし
パスワード
   ▼YU-TANG さん:
ありがとうございます

自宅環境は
アクセスエクセル2007
vista home

>変数の有効期間を理解されていないのが原因ではないでしょうか。
あやふやな理解のままでした

-----------------------------------------------
変数の有効期間の概要

クラス モジュールでは、クラスのインスタンスが存在する限り、
値を保持します。モジュール レベルの変数は、値がリセットされるまで
メモリ リソースを消費するので、必要な場合のみ使用することを
お勧めします。
-----------------------------------------------
なんてありました

>プロシージャ内で宣言された変数の寿命はそのプロシージャの実行中だけ
>ですから、提示されたコードの objClass1 は一瞬で解放されてしまいます。
>これが原因です。

クラスモジュールのデバッグ方法に自信が無かったのですが
ツール/オプション/全般/エラートラップ/クラスモジュールで中断
にチェックしたので、デバッグは問題ないと思います

ステップ実行してみると

Class_Initialize の End Sub が終了すると 
Class_Terminateが実行されてイベントが終了してしまいます

>対策として、たとえば objClass1 をモジュールレベルで宣言するように
>してはいかがでしょうか。


Private WithEvents xlsApp  As Excel.Application
Public bokWork       As Excel.Workbook
Public shtSheet      As Excel.Worksheet
を標準のジュールに移動してみたのですが


Private WithEvents xlsApp  As Excel.Application

コンパイル エラー:
オブジェクト モジュールでのみ有効です。
となってしまいます

結果的には
Public bokWork       As Excel.Workbook
Public shtSheet      As Excel.Worksheet
を標準モジュールに

Private WithEvents xlsApp  As Excel.Application
は、クラスモジュールのままとなってしまいました


結果的に修正コードは

クラスモジュール

Option Compare Database
Option Explicit

Private WithEvents xlsApp  As Excel.Application
'Private bokWork       As Excel.Workbook
'Private shtSheet      As Excel.Worksheet


'Private WithEvents bokWork  As Excel.Workbook
'Private WithEvents shtSheet As Excel.Worksheet


Private Sub Class_Initialize()
'Public Sub Class_Initialize()


  Set xlsApp = CreateObject("Excel.Application")
  Set bokWork = xlsApp.Workbooks.Open("\\sv_hoge\fuga.xls")
  
  xlsApp.Visible = True
  
  Set shtSheet = bokWork.Worksheets(1)
  
  bokWork.Activate
  shtSheet.Activate


End Sub

Private Sub xlsApp_SheetActivate(ByVal Sh As Object)

  MsgBox Sh.Name
  'MsgBox shtSheet.Name

End Sub

Private Sub xlsApp_SheetChange(ByVal Sh As Object, ByVal Target As Excel.Range)

  MsgBox Sh.Name
  'MsgBox shtSheet.Name

End Sub

Private Sub xlsApp_WorkbookOpen(ByVal Wb As Excel.Workbook)

  MsgBox Wb.Name
  'MsgBox bokWork.Name


End Sub


標準モジュール
Option Compare Database
Option Explicit

'Private WithEvents xlsApp  As Excel.Application
Public bokWork       As Excel.Workbook
Public shtSheet      As Excel.Worksheet


Sub TG_BK_open()

  Dim objClass1 As Object
  Set objClass1 = New Class1
 
End Sub

として TG_BK_open では エラーは出ませんがやはり
ブックの操作イベントは取得できませんでした

原因は
>Private WithEvents xlsApp  As Excel.Application
>は、クラスモジュールのままとなってしまいました
にあると思うのですが

>対策として、たとえば objClass1 をモジュールレベルで宣言するように
>してはいかがでしょうか。
とするためには
どのような記述をすればよいのでしょうか


また
bokWork.Name
shtSheet.Name
のような取得がうまく出来ません
これはどのように記述すればよいのでしょうか

よろしくお願いいたします


>もっとも「kb408871」で検索すると出てくるような話もあるので、
>いかなる状況でも保証できるものではありませんが。
----------------------------------------------------
[VBA] Public 宣言された変数の有効期間
tp://support.microsoft.com/kb/408871/ja
ほとんどの場合、プロシージャ終了後も値は保持されますが、意図しないタイミングで保持されていた Public 変数の値が破棄され、使えていた変数の値が突然使えなくなる場合があります。そのため、Public 変数がアプリケーション終了時まで有効であることを期待する VBA マクロの実装は、推奨されません
----------------------------------------------------
なるほどです
勉強になりました ありがとうございました

あわせて、上記に遭遇しないようなアプローチの方法等ありましたら
紹介頂けると嬉しいです
よろしくお願いいたします

【11552】Re:エクセルのイベント取得
質問  YU-TANG  - 10/3/28(日) 15:42 -

引用なし
パスワード
   こんにちは、YU-TANG です。

> >対策として、たとえば objClass1 をモジュールレベルで宣言するように
> >してはいかがでしょうか。
>
>
> Private WithEvents xlsApp  As Excel.Application
> Public bokWork       As Excel.Workbook
> Public shtSheet      As Excel.Worksheet
> を標準のジュールに移動してみたのですが

すみませんが、意味がまったく分かりません。
objClass1 という宣言をモジュールレベルに移動することをお勧めした
ことと、この xlsApp 等の宣言を標準モジュールに移動されたこととの
関連はいったい何でしょうか?


> あわせて、上記に遭遇しないようなアプローチの方法等ありましたら
> 紹介頂けると嬉しいです

その KB に書いてありますが、

> なお、モジュールの編集、プロジェクトの構造の変更、コンパイルエラーの発生、参照設定の変更、デザインモードへの切り替え、コントロールを削除して [元に戻す] を実行するなどのタイミングで変数が破棄される場合があります。

これらの行為を (実行中には) しない、ということです。
また実行時エラーはすべてトラップします。トラップし忘れた実行時エラー
によって、変数が破棄されるケースが (経験則的に) あります。

それでは。

【11553】Re:エクセルのイベント取得
質問  pon  - 10/3/28(日) 18:16 -

引用なし
パスワード
   ▼YU-TANG さん:
ありがとうございます

>すみませんが、意味がまったく分かりません。
>objClass1 という宣言をモジュールレベルに移動することをお勧めした
>ことと、この xlsApp 等の宣言を標準モジュールに移動されたこととの
>関連はいったい何でしょうか?

クラスモジュールの理解が足りないのと
頭が固くてみたいなでした

再度の書き込みを頂いて

標準モジュールの宣言を
Option Compare Database
Option Explicit

'Private WithEvents xlsApp  As Excel.Application
'Public bokWork       As Excel.Workbook
'Public shtSheet      As Excel.Worksheet

Dim objClass1 As Object

として、希望の操作がかないました
うう うれぴー ♪
ありがとうございました

下記動作確認してみました


Private Sub xlsApp_SheetChange(ByVal Sh As Object, ByVal Target As Excel.Range)

  MsgBox Sh.Name
  MsgBox Target.Address

End Sub

Private Sub xlsApp_WorkbookBeforeClose(ByVal Wb As Excel.Workbook, Cancel As Boolean)

  MsgBox Wb.Name
  
  Set shtSheet = Nothing
  Set bokWork = Nothing
  Set xlsApp = Nothing
  

End Sub

Private Sub xlsApp_WorkbookBeforeSave(ByVal Wb As Excel.Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)

  MsgBox Wb.Name
  MsgBox Wb.ActiveSheet.Name

End Sub

動作的には
CreateObjectしているので
別途エクセルが先行して開いていても問題は無いと考えています
また
xlsApp_WorkbookBeforeClose

  Set shtSheet = Nothing
  Set bokWork = Nothing
  Set xlsApp = Nothing
しているので、エクセルのお化けも残らないようです
ブックの×ボタンで閉じられても大丈夫でした

Q1)
以上確認してみたのですが
他に確認すべき事項とか注意事項ありますでしょうか
アドバイスありましたらよろしくお願いいたします

Q2)
あと
ブックが閉じられる前なら上記のようにちゃんとイベントは取得できているのですが
ローカルウインドウには何も表示されていません

この状態で(ブックが開いている状態で)
イミディエイトウインドウで開いているブック名とか
取得したいと ?Class1.xlsApp.Wb.Name してみましたが
実行時エラー '424':
オブジェクトが必要です。
となってしまいます

この辺がクラスの使い方の肝のような気もしていますがよくわかりません
イミディエイトウインドウから開いているワークブック名を取得する
ことは出来ますでしょうか?


>> あわせて、上記に遭遇しないようなアプローチの方法等ありましたら
>> 紹介頂けると嬉しいです
>その KB に書いてありますが、
特に、記述先等は無いのですが
どこかのQAでみかけた、変数の値は保証されるものではない
が頭にあって
別途アプローチもあるのかなと思った次第でした

>これらの行為を (実行中には) しない、ということです。
>また実行時エラーはすべてトラップします。トラップし忘れた実行時エラー
>によって、変数が破棄されるケースが (経験則的に) あります。
詳細な解説ありがとうございました
完成後の状態であればこのような状況に遭遇しないと思います


ちょっと感激したのは
開くブックにはコードは無いので
開く時にマクロを有効にする を出さないで
ブックのイベントが取得できたことです
当然といえば当然のような気もしますが・・・・・


Q1、Q2
他コメントあれば、アドバイスよろしくお願いいたします

【11554】Re:エクセルのイベント取得
回答  YU-TANG  - 10/3/29(月) 8:16 -

引用なし
パスワード
   こんにちは、YU-TANG です。

> 他に確認すべき事項とか注意事項ありますでしょうか

ありません。

> ローカルウインドウには何も表示されていません

それはコード実行中に値を確認するためのウィンドウです。
コード実行中でなければ何も表示されません。そういうものです。
どこかプロシージャの中でブレークポイントまたは Stop とかで
止めると表示されると思います。

> 取得したいと ?Class1.xlsApp.Wb.Name してみましたが
> 実行時エラー '424':
> オブジェクトが必要です。

ブレーク中なら、

?bokWork.Name

とかで取れるはずです。

?Class1

は、クラスを指定していますからダメです。
クラスは設計図みたいなものですから、参照する実体がありません。
インスタンス (objClass1) の方を指定しないといけません。
しかも、インスタンスを指定したところで、現状 xlsApp は外部公開
されていないので、外からアクセスできません。
その形で取得・参照したいなら、xlsApp を Public なり Friend なりで
公開する必要があります。そして、公開したとしても xlsApp に Wb など
というメンバはありませんから、ちゃんと存在するメンバを指定しないと
いけません。

それでは。

【11555】Re:エクセルのイベント取得
お礼  pon  - 10/3/29(月) 12:44 -

引用なし
パスワード
   ▼YU-TANG さん:
お手数おかけします


>それはコード実行中に値を確認するためのウィンドウです。
>コード実行中でなければ何も表示されません。そういうものです。
ありがとうございます
>そういうものです。
こういうアドバイス助かります
了解です


>クラスは設計図みたいなものですから、参照する実体がありません。
・・
>その形で取得・参照したいなら、xlsApp を Public なり Friend なりで
詳細な解説ありがとうございます
わかり易いです
頂いたアドバイスでクラスの理解を深めるよう勉強したいと思います


追記
短絡的に
>質問[NEW] pon - 10/3/28(日) 18:16 -
>CreateObjectしているので
>別途エクセルが先行して開いていても問題は無いと考えています
と思ったのですが
指定ブックを開いたあと新規ブックが開かれる等
面倒が出そうなので

Class_Initialize時
GetObjectで確認、無ければCreateObjectし

xlsApp_WorkbookBeforeClose時は
当該ブックの時だけ実行

で、希望の操作がかないそうです


YU-TANG さん

色々ご教示ありがとうございました
今後もよろしくお願い致します

468 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078193
(SS)C-BOARD v3.8 is Free