[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ブレークポイントを設定する/しないの動作の違いについて』(ラビット)
初めまして。
先週からExcel VBAを始めて2週目の初心者です(^^;
現在、ちょっとしたツールを作っているのですが、
ある所で分からないところがありまして、調べても分からなかったので、
ご存知の方がいらっしゃたらと思い、表題の件で、質問致します。
先ず、実現したい機能が
(1)シートに挿入されている、コマンドボタンクリック時のみ
ツールを終了する。 (2)開いているBookが自分のみの場合は、Excel本体を終了し、 他にBookを開いている場合は、自分のBookのみ閉じる。 (3)編集内容を破棄するかどうか、 Excelの保存確認メッセージを表示させない。 です。
自ら調べつつ、(ほぼ)実現出来たのですが、
ある状況下では、意図した結果になりません。
ソースコードを以下に示します。
'*************
' Module1
'*************
' CloseFlag
Public ShouldClose As Boolean
'************
' Sheet1
'************
Private Sub BTN_Close_Click()
If Not MsgBox("Are you Sure?", vbYesNo) = vbYes Then GoTo End_Proc End If
' CloseFlag On Let ShouldClose = True
If Application.Workbooks.Count = 1 Then ● Call Application.Quit End If Call ThisWorkbook.Close
End_Proc:
End Sub
'******************
' ThisWorkbook
'******************
Private Sub Workbook_Open()
' Initialize global variables Let ShouldClose = False
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Saved = True If Not ShouldClose Then ★ Call MsgBox("Click [Close] Button!", vbCritical) Let Cancel = True Else Let Cancel = False End If
End Sub
上記を自分のブックのみ開いて、
Sheet1の[Close]ボタンをクリックすると、
(1)〜(3)を満たすように動作するのですが、
Call Application.Quitにブレークポイント(●の箇所)を
設定して、同様にクリックして実行して、
止まった●から、ステップイン実行すると、
Workbook_BeforeCloseイベントの
Call MsgBox("Click [Close] Button!", vbCritical)(★の箇所)
以下が実行されてしまいます。
★が通ったということは、グローバル変数の[ShouldClose]の値が
Falseになっているということなので、
・Application.Quitが実行されることで、グローバル変数の値が破棄された
と考えました。
そうすると、
ブレークポイントを設定しないで実行したときに、
★を通らなかったのは、実現機能的には正常ですが、
コード的には、異常なのではないかと思いました。
(たまたま、自分の環境下ではこうなるのではないかということ)
質問が後回しになり申し訳ありませんが、
「皆様の環境下でも、同様のことが起きるでしょうか?」また、
「今回のような、ブレークポイントを設定した場合と、しない場合の
動作の違いは、何故起こるのでしょうか?」
以上、宜しくお願い致します。
補足:
確実な対策として、グローバル変数を使用せず、
セルに、終了フラグのOn,Offを書き込むようにすれば、
解決ですが、上記のことが気になります。
< 使用 アプリ:Excel2007 & Excel2010、使用 OS:Windows7 >
>今回のような、ブレークポイントを設定した場合と、しない場合の >動作の違いは、何故起こるのでしょうか?」
深く読んでいませんが、これじゃないですか?
[VBA] Public 宣言された変数の有効期間 http://support.microsoft.com/kb/408871/ja
(半平太) 2016/09/25(日) 11:04
ご回答ありがとうございます。
リンク先の記事を読みました。
こちらが答えだと思います。
原因はさておき、
「Public 変数がアプリケーション終了時まで有効であることを期待する VBA マクロの実装は、
推奨されません。」ということですから、解決方法に示される、
「非表示にしたワークシートに値を記述します。」にコード変更するようにします。
意図しないことが想定される非推奨の話を、
これ以上追究するのはやめようと思います。
これからも、勉強して参ります。
ありがとうございました。
(ラビット) 2016/09/25(日) 11:29
あれ? ちょっと私の認識と違うのですけど、
ブレークポイントで一旦マクロの動作を止めると、 予期しない初期化が起こるかも知れない、と言うだけなんですけど。
途中で止めたりしなければ、普通に動かないとおかしいです。
(そう言う質問じゃないのかもよく分からないです)
(半平太) 2016/09/25(日) 16:10
私の書き方が悪かったですね。すみません。
表題に設定した、
『ブレークポイントを設定する/しないの動作の違いについて』
は解決致しました。
>ブレークポイントで一旦マクロの動作を止めると、
>予期しない初期化が起こるかも知れない
ということなのだと思います。
その意味を込めて、「こちらが答えだと思います。 」
と書きました。
一方で、プロシージャの先頭にキャレットを置いて、
[F8]を叩いて確かめるような場合でも、意図しない
ことが起きてしまうことは、作法として良いのかと思った次第です。
====================
(
この"意図しない"ことが起きる組み合わせが、
「デバッグモードとApplication.Quit」の気がしています。
試しに、Workbook_BeforeCloseイベントには何も記述せず、
以下のプログラムを
(1)ステップインで1行ずつ実行すると、2番目のMsgBoxは表示されず
(2)一気(F5等)実行させると、2番目のMsgBoxは表示される。ただ、
第1パラメータのBookのパスは取得出来ない。
Private Sub CommandButton1_Click()
Call MsgBox(ThisWorkbook.Path, vbSystemModal) Call Application.Quit Call MsgBox(ThisWorkbook.Path, vbSystemModal)
End Sub
このようなことがあり、また、
リファレンスも殆ど無いので、
今後、同様の質問が挙がったときのために
備忘録として書いておきます。
)
(ラビット) 2016/09/25(日) 18:06
今度は、もう少し真面目に読んでみました m(__)m
>この"意図しない"ことが起きる組み合わせが、 >「デバッグモードとApplication.Quit」の気がしています。
試しにこんなコードでテストしてみると
Public ShouldClose As String
Sub ボタン1_Click() Call MsgBox(ThisWorkbook.Path, vbSystemModal, ShouldClose) Call Application.Quit Call MsgBox(ThisWorkbook.Path, vbSystemModal, ShouldClose) End Sub
Private Sub Workbook_Open() Let ShouldClose = "死んでないよ" End Sub
>2番目のMsgBoxは表示される。ただ、 >第1パラメータのBookのパスは取得出来ない。 でも、オープンして、直ぐ ボタン1をクリックすれば、 2番目のMsbBoxのタイトルでも、 "死んでないよ" と出ます。
つまり、グローバル変数は保持されます。 ・・けど「確実ではないですよ」と言う意味で推奨されないレベルになっている話だと思います。
一方、Call Application.Quit は、そんなグローバル変数の値保持とか言う レベルの話ではないと思われます。
もともと、自分自身が動いている存在基盤をQuitしても、まだその先のステートメントが 実行されることの方が、よっぼど不思議と言える仕様です。
多分、実際のニーズに合わせるために、何とかそれを成立させる奥の手を使っているんでしょうが、 デバッグモードにされると、その奇策も通じなくなるということだと思います。
あと、ちょっとした感想なんですけども
>Private Sub Workbook_Open() > Let ShouldClose = False >End Sub 自然体の(手操作による)ブックオープンを想定するなら、 わざわざFalseを設定する必要はないと思います。初期値がFalseのハズですから。
> If Not ShouldClose Then >★ Call MsgBox("Click [Close] Button!", vbCritical) > Let Cancel = True > Else > Let Cancel = False > End If これもCancelは、元々Falseですから、Elseは必要ないと思います。
(半平太) 2016/09/25(日) 19:51
ご指摘ありがとうございます。
Let Cancel = Falseの方は、明らかに無駄ですね(^^;
ご提示頂いたサンプルを、私も実行しましたが、
同様の結果が得られました。
>自然体の(手操作による)ブックオープン
という表現が気になったので、調べてみたら、
他のブックからマクロを使って、Workbook_Openが
記述されたブックを開くと、自動実行され、
Auto_Openの場合は、自動実行されないんですね。
また一つ勉強になりました。
ここの学校は参考になる情報が多いので、
今後も利用させて頂きますゆえ、宜しくお願い致します。
(ラビット) 2016/09/25(日) 22:11
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.