
終了時に独自で保存をしたいのですが、
下記のコードだと1回目でキャンセルすると
2回目以降の呼び出し時に全く実行されません。
どこか悪いのかご教示ください。
また、もしご存じであれば
BeforeClose() と Auto_Close() の違い
ThisWorkbook と Me の違い
を教えてください。
よろしくお願いいたします。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim iAns As VbMsgBoxResult
iAns = MsgBox("'" & Me.Name & "' への変更を保存しますか?")
Select Case iAns
Case vbYes
Call WriteFile
ThisWorkbook.Close savechanges:=False
Case vbNo
ThisWorkbook.Close savechanges:=False
Case vbCancel
Cancel = True
End Select
End Sub
No.4ベストアンサー
- 回答日時:
こんにちは。
> ですが、vbYesとvbNoのとき、なぜかMsgBoxの表示後にExcelの保存確認
> ダイアログまで表示されてしまい、有効に機能していないようなのです。
> 他の何かがまずいのでしょうか。
最初の処理では、イベント機能が有効になっていてWorkbook_BeforeClose
により処理されますが、WriteFileを行ったことにより、イベント機能が
無効になってしまって、Workbook_BeforeCloseではなく、通常の閉じる処理
になっている、ということはないですか?
もしそうなら、WriteFileの処理の方で
ThisWorkbook.Saved = True
Application.EnableEvents = True
というような処理を追加されてみては如何でしょうか?
という事であれば、
もし、ThisWorkbook.Saved = Trueならメッセージを出さずにブックを閉じる
という処理も必要になるかもしれませんね。
ご回答ありがとうございます。
原因はご指摘のイベント機能関連のようでした。
流れとしては
Application.EnableEvents = False
中略
ThisWorkbook.Saved = True
中略
Application.EnableEvents = True
となっていました。コメントアウトすることで正常に動作しました。
イベント内部でこのようなことをするべきでないということでしょうか。
イベント等についてもっと勉強する必要があるようです。
この度はどうもありがとうございました。
おかげさまで解決できました。
No.3
- 回答日時:
>ですが、vbYesとvbNoのとき、なぜかMsgBoxの表示後にExcelの保存確認ダイアログまで表示されてしまい、
>有効に機能していないようなのです。
>他の何かがまずいのでしょうか。
vbNoの時もとなると、正直に言って解りませんm(_ _)m
#Sub Auto_Cose()に何か書いてたりしないですよね。
新規Book&シンプルなコードで試してみると
'ThisWorkbookModule
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim iAns As VbMsgBoxResult
Debug.Print Me.Saved
iAns = MsgBox("'" & Me.Name & "' への変更を保存しますか?", vbYesNoCancel)
Select Case iAns
Case vbYes
Call test
Me.Saved = True
Case vbNo
Me.Saved = True
Case vbCancel
Cancel = True
End Select
Debug.Print iAns, Cancel, Me.Saved
End Sub
Private Sub test()
MsgBox "test"
Me.Save
End Sub
(結果)
False
6 False True
False
7 False True
False
2 True False
意図した通り動作すると思います。
本番コードに関しては、ブレイクポイント設定してデバッグしてみてください。
ご回答ありがとうございます。
原因はイベント機能関連のようでした。
検証用のコードまで載せていただいて、ありがとうございました。
おそらくend-uさんの思いもよらないようなヘマをしてたんでしょうね、私。 ^^;
また機会がありましたらよろしくお願いいたします。
No.2
- 回答日時:
こんにちは。
書いていたらすでに回答が……(^_^;)
MmsgBoxの引数Buttonsが指定されていないので
Select Case でiAnsを場合分けできないのと、
BeforeCloseイベントの中にCloseメソッドを入れたら
またイベントが発生してしまうというところが修正ポイントです。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim iAns As VbMsgBoxResult
iAns = MsgBox("'" & Me.Name & "' への変更を保存しますか?", vbYesNoCancel)
If iAns = vbYes Then Call WriteFie
Select Case iAns
Case vbYes, vbNo
Cancel = False
Case vbCancel
Cancel = True
End Select
End Sub
こっちもだらだらと書いてしまいました……。
> BeforeClose() と Auto_Close() の違い
ですが、記述されたブックが他のブックから操作されたかによって
動作が違います。
Auto_OpenやAuto_Closeは、そのブックを自分で開いた時のみ実行されます。
WorkbookOpenやBeforeCloseは、他のブックから操作された時にも実行されます。
例えば、A、B、Cのブックがあって、BにAuto_Closeによる処理を記述し、
CにBeforeCloseによる処理を記述していたとします。
その時、AからBを閉じる命令を実行してもBのAuto_Closeは実行されません。
しかし、AからCを閉じる命令を実行するとCのBeforeCloseが実行されます。
他のブックのマクロを操作する方法としてRunメソッドがありますが、使うのなら
ヘルプで調べてみてください。
> ThisWorkbook と Me の違い
ですが、私もあまり詳しくありませんが、プロパティとキーワードである、というの
がまず違いますね。
ThisWorkbookは、マクロコードが書かれたそのブックを指すプロパティです。
Meは、そのコードが実行されているクラスや構造体を参照するためのキーワードです。
マクロを記述する時、前者はどこでも使用できますが、後者は、クラスとして成り
立っているThisWorkbookモジュールやUserForm1モジュール内では使用できますが、
標準モジュールでは使えません。
つまり、Meキーワードは、ThisWorkbookモジュール内では、Thisworkbookクラスを
参照している、UserForm1モジュールでは、UserForm1クラスを参照している、とい
うことぐらいしかわかりません。
私自身、単一のUserFormを使う場合は、Meキーワードを使う事がありますが、
ThisWorkbookモジュールではMe、標準モジュールではThisWorkbook、って使い分ける
ことはしたことがありません。(混乱してしまいますから。)
この回答への補足
>MmsgBoxの引数Buttonsが指定されていないので
すみません・・・簡略化している際に誤って省いてしまったようです。
実際にはvbYesNoCancelが付いていました。
end-uさんにも回答していることですが、
ThisWorkbook.Saved = True
にしてもそれが有効化していないことに頭を悩ませている状態です。
何か思い当たることがあればご教示お願いいたします。
>Auto_OpenやAuto_Closeは、そのブックを自分で開いた時のみ実行されます。
>WorkbookOpenやBeforeCloseは、他のブックから操作された時にも実行されます。
解りやすいご説明ありがとうございます。
今回のケースではどちらでも問題ないことを知り、安心しました。
>私自身、単一のUserFormを使う場合は、Meキーワードを使う事がありますが、
>ThisWorkbookモジュールではMe、標準モジュールではThisWorkbook、って使い分ける
>ことはしたことがありません。(混乱してしまいますから。)
たしかにあちこち眺めてたら混乱しそうですね。
ThisWorkbookはMeであまり代用しないほうが統一されて良さそうです。
No.1
- 回答日時:
>...1回目でキャンセルすると
>2回目以降の呼び出し時に全く実行されません。
状況が今ひとつ掴めませんが、そのコードでは上手くいかないのは確かです。
Workbook_BeforeCloseは文字通り、Close前処理ですから
コード内でCancel = Trueしなければ、処理が終わればCloseします。
BeforeClose内でCloseメソッドを書く必要はありません。
と、いうよりCloseメソッドを書くとイベント連鎖が発生する事になりますので書きません。
こういう場合、
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim iAns As VbMsgBoxResult
iAns = MsgBox("'" & Me.Name & "' への変更を保存しますか?", vbYesNoCancel)
Select Case iAns
Case vbYes
Call WriteFile
Me.Saved = True
Case vbNo
Me.Saved = True
Case vbCancel
Cancel = True
End Select
End Sub
このように書きます。
SavedプロパティをTrueに変更すれば、そのBookは変更なしと判定されて
保存せずに閉じる事(ThisWorkbook.Close savechanges:=False)ができます。
#余談かもしれませんが、今回のケースではBeforeSaveイベントでCall WriteFileを利用すれば
#Close時は既定の動作で対応できるような気がします。
#(Sub WriteFileの中身と運用がわからないので確実ではないです。深追いするつもりもありません)
>BeforeClose() と Auto_Close() の違い
BeforeCloseはイベントプロシージャで、Auto_Closeは自動実行マクロです。
Excel95以前からある自動実行マクロに対して、BeforeCloseイベントは97から追加されたものです。(多分)
違いなどは↓など参考にしてみてください。
『■ イベントプロシージャを活用しよう!』
http://home.att.ne.jp/zeta/gen/excel/c04p59.htm
>ThisWorkbook と Me の違い
半分パス。(専門家の方のレスをお待ちください)
ThisWorkbookはThisWorkbookプロパティでMeはMeキーワード。
ThisWorkbookはThisWorkbookを指しますが
MeはThisWorkBookモジュールやFormモジュール、Classモジュール内のプロシージャ内で書くと
それぞれのクラス、インスタンスを指します。
#これ以上うまく伝える自信なしm(_ _)m
この回答への補足
ご回答ありがとうございます。
>BeforeClose内でCloseメソッドを書く必要はありません。
>と、いうよりCloseメソッドを書くとイベント連鎖が発生する事になりますので書きません。
言われてみるとその通りですね。。
Me.Saved = True に直したら、2回目以降もうまくいきました。
ですが、vbYesとvbNoのとき、なぜかMsgBoxの表示後にExcelの保存確認ダイアログまで表示されてしまい、
有効に機能していないようなのです。
他の何かがまずいのでしょうか。
>『■ イベントプロシージャを活用しよう!』
>http://home.att.ne.jp/zeta/gen/excel/c04p59.htm
違いが分かりました。単独で使用する際には特に違いはないようですね。
>MeはThisWorkBookモジュールやFormモジュール、Classモジュール内のプロシージャ内で書くと
>それぞれのクラス、インスタンスを指します。
個々のインスタンス自体を指すのですね。ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- Visual Basic(VBA) 【変更】ファイルを閉じてダイアログで保存した時、更新したシートだけの処理の実行をする 5 2022/03/26 18:31
- Visual Basic(VBA) 【追加】ファイルを閉じてダイアログで保存した時だけ処理の実行をする 3 2022/03/23 15:43
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- Visual Basic(VBA) ExcelのVBAコードについて教えてください。 1 2023/08/10 14:24
- Visual Basic(VBA) Excel vbaについての質問 3 2023/04/18 16:14
- Excel(エクセル) Excelのマクロコードについて教えてください。 1 2022/03/27 10:47
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) エクセルのVBAでダブルクリックでチェックを入れたあと 1 2022/10/26 20:30
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
このQ&Aを見た人はこんなQ&Aも見ています
-
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
Excel マクロ 閉じるボタン
Visual Basic(VBA)
-
マクロのBeforeCloseイベントについて教えて下さい。 ブック1とブック2を同じエクセルで2つ
Visual Basic(VBA)
-
-
4
[Excel2000]auto_closeを止めさせるには
Excel(エクセル)
-
5
モーダルフォームとモードレスフォーム
Visual Basic(VBA)
-
6
VBA:ユーザーフォームのマルチページに色を付けたい。
Word(ワード)
-
7
【Excel VBA】マクロでExcel自体を終了させたい
Excel(エクセル)
-
8
エクセルVBA ブックを閉じる前に確認メッセージを表示したい
Excel(エクセル)
-
9
エクセルVBAでUserFormを起動した時
Excel(エクセル)
-
10
'ユーザーフォーム右上隅の[×]ボタンを表示しない
Visual Basic(VBA)
-
11
エクセルのvbaにて thisworkbookに記載のマクロを他のブックにマクロにて自動コピー出来る
Excel(エクセル)
-
12
【VBA】マクロの入ったファイルと同じフォルダに,出力したファイルを保存するコードについて
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルVBAでNumLockキーの状...
-
vbaでmsgboxの位置を指定
-
VBAが得意な方 助けてください...
-
Excel:アドイン(ThisWorkbook)...
-
別シートのマクロを実行する方法
-
Application.Runエラー(1004)
-
Access終了時にマクロまたはVBA...
-
Access マクロで次の検索の設...
-
シート保護を掛けたまま並べ替...
-
エクセルVBAで数式バー再表示後...
-
マクロが登録できません
-
今日の日付の範囲を指定して印...
-
AccessでExcelファイルを印刷
-
イベントプロシージャからマク...
-
エクセル ルーチンマクロ
-
ウィンドウサイズ・場所のレジ...
-
マクロでショートカットキーを...
-
アクセスのマクロについて
-
エクセルのマクロ
-
ExcelのVBAでDisplayalertsで警...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vbaでmsgboxの位置を指定
-
エクセルVBA フォームShowでオ...
-
エクセルVBAでNumLockキーの状...
-
【Excel】BeforeCloseを毎回呼...
-
Excel:アドイン(ThisWorkbook)...
-
エクセルのダブルクリックで
-
VBAが得意な方 助けてください...
-
VBAでフォームにおけるコマンド...
-
Pic16f690でpwm信号を作る。c言...
-
ワークシートのコピーVBAでうま...
-
HULFT完了コードについて
-
フォームを作成すると同時にイ...
-
VBAに関して、プロシージャが大...
-
別シートのマクロを実行する方法
-
Application.Runエラー(1004)
-
エクセルのマクロボタンが編集...
-
Access終了時にマクロまたはVBA...
-
エクセルVBAで、ボタンの文字を...
-
シート保護を掛けたまま並べ替...
-
InputBox内の表示について
おすすめ情報