dポイントプレゼントキャンペーン実施中!

エクセルファイルを右上バツ印にて閉じる時、通常「上書き保存しますか?」というメッセージが出ます。
本来、「No」を選択するべきところ、誤って「Yes」としてしまうミステイクを防ぐ為、上書き保存の再確認メッセージを出したいと思っています。
みなさんに教えてもらい、以下のようなVBAを組みました。

-------------------------------------
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim lngSave As Long

lngSave = MsgBox("間違いありませんか?本当に上書き保存しますか?", vbExclamation + vbYesNo, "保存確認")
If lngSave = vbYes Then:

End Sub

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

ほぼやりたいことは出来るようになっているのですが、2点、合点がいかないところがあります。

①1回目のメッセージに対し、YESを選択し、2回目の「本当に上書きしますか?」に対し、NOとした時、NOとしているにもかかわらず、保存してしまっています。
なぜでしょう?
上のVBAには、「NOを選択した時、保存をキャンセルする」という式が無いように思うのですが・・・?

②「保存しますか」メッセージが2,3回繰り返されることがあります。保存のイベント→確認メッセージ→YES→保存へ→確認メッセージ→YES・・・・・・と、このままエンドレスで続くのかと思わせる動きです。
はじめに組んだ時、終わりの行はThenの次に、ThisWorkbook.Saveとなっていました。そのせいでしょうか?
上のようにしてからは発生してないかもしれません・・・。あやふやですみません。

アドバイスお願いします。

A 回答 (9件)

No,4,7です。


ThisWorkbook.Saved は、開いたまま編集がされていない
或いは、上書き保存した後のままであるかどうかです。
ThisWorkbook.Saved がFalseの場合は、閉じる際に上書き保存しますかと聞いてきます
ThisWorkbook.Saved が Trueの場合は、そのまま閉じられます。
なので、 Falseの場合、無理やり True にしてしまえば
上書き保存しますか と聞かれないまま閉じてしまいます。
    • good
    • 0
この回答へのお礼

あ、なるほど。Saveが過去形なんですね。
保存したものと変わっている、というPCの認識を、保存していたものと同じと思わせる、ということですね。

お礼日時:2015/11/05 01:54

No.3 のWindFaller です。



No.5 のnicotinism 様の
>BeforeCloseだとBeforeSaveイベントよりも前に発生するようなので
ご指摘いただいて、ありがとうございます。

そのまま、終了(X)をクリックすることは考えていませんでしたね。
私自身、考えてみると、いきなり、右上隅の終了(x)は押していないことに気が付きました。
終了(X)をクリックをしても、同じような仕様にしました。単なる思いつきですから、しばらく様子を見てみようと思います。

'//
'標準モジュール
Public Sub ClosingMacro()
 Dim lngSave As VbMsgBoxResult
 Dim msg As String
 Dim i As Long
 msg = "本当に、"
 Application.EnableEvents = False
 Cancel = True
 Do
  lngSave = MsgBox("間違いありませんか?" & Application.Rept(msg, i) & "上書き保存しますか?", vbExclamation + vbYesNo, "保存確認")
  If lngSave = vbNo Then
   GoTo EndLine
  End If
  i = i + 1
 Loop Until i >= 2
 ThisWorkbook.Save
EndLine:
 Application.EnableEvents = True
End Sub
'ThisWorkbook モジュール
'------
Private Sub Workbook_BeforeClose(Cancel As Boolean)
 If ThisWorkbook.Saved = False Then
  Call ClosingMacro
 End If
End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
 If ThisWorkbook.Saved = False Then
  Call ClosingMacro
 End If
End Sub
    • good
    • 0

NNO,4です。


Private Sub Workbook_BeforeClose(Cancel As Boolean)
If ThisWorkbook.Saved = False Then ThisWorkbook.Saved = True
End Sub
として、ファイルを閉じる、×マークを押しても上書き保存はさせない。

上書き保存をしたい人は、閉じる前に上書きを操作、実行させる。
必要であれば、クイックアクセスツールバーに
上書き保存 を表示させておく。
或いは、上書き保存のボタンを配置する。
ここまですると、誤って上書き保存されるかも。
    • good
    • 0
この回答へのお礼

その方法でやることにしました。
ありがとうございました。

>If ThisWorkbook.Saved = False Then ThisWorkbook.Saved = True

ちなみに上のコード、解説お願いしてもいいですか?
「ファイルを閉じる⇒保存がNOの時、保存がYES」・・・ではないですよね?

お礼日時:2015/11/04 20:09

ANo.2です。



> Cancelは、「(何もしなければ)キャンセルしない」というコードという事ですか?
> すると、Cancel=Trueは「キャンセルしない」という意味になりますか?

違います。逆です。先の回答で例示したとおりで、Cancel = True で保存キャンセルするという意味です。詳細は以下の公式解説をあたってください。

https://goo.gl/Uau2ek

・・・ってことは、私の最初のYes/Noの解釈が逆ですね・・・選択肢がYesだと保存したくないのであれば、次が正解となります。混乱させてしまってごめんなさい。

If lngSave = vbNo Then Cancel = True
または
If lngSave <> vbYes Then Cancel = True
    • good
    • 0

#3さんへ


保存したいときに無限ループに陥ってしまいませんか?
BeforeCloseだとBeforeSaveイベントよりも前に発生するようなので
簡単に済むような。
    • good
    • 1

>本来、「No」を選択するべきところ、誤って「Yes」としてしまうミステイクを防ぐ為・・・


この辺りをもう少し深く原因を調べると他の方法があると思うのですが
一例ですが
担当者によって、上書き出来る人と出来ない人を分けたい
ファイルに、読み取り、書き込み それぞれのパスワードを設定
開く時点で、上書き保存できるかできないか決めてしまう。
http://azby.fmworld.net/usage/windows_tips/20050 …
この辺りは如何でしょうか。

或いは、上書き保存ボタン と 上書き無終了ボタンを設置して
×では終了できなくするとか。
    • good
    • 0
この回答へのお礼

>ファイルに、読み取り、書き込み それぞれのパスワードを設定
>開く時点で、上書き保存できるかできないか決めてしまう

各人、上書きする必要もあるので、こちらの方策は難しいです。

>上書き保存ボタン と 上書き無終了ボタンを設置して
>×では終了できなくするとか。

これはアリですね。
「上書きせずに閉じる」ボタンを設置するというのも考えてみたいと思います。
ありがとうございました。

お礼日時:2015/11/03 20:14

こんにちは。



前の方々のお話は、それぞれは正しいのですが、自分なりのコードを書いてみました。
それと、他にも書き方はあるでしょうけれども、今の話のベースで考えてみました。

'//
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
 Dim lngSave As VbMsgBoxResult
 Dim msg As String
 Dim i As Long
 msg = "本当に、"
 Application.EnableEvents = False 'これを入れないと、Yes を選択時に、Saveに戻らされる。
 Cancel = True 'これを入れないと、手動の'Save'の命令自体は生きています。
 Do
  lngSave = MsgBox("間違いありませんか?" & Application.Rept(msg, i) & "上書き保存しますか?", vbExclamation + vbYesNo, "保存確認")
  If lngSave = vbNo Then
   GoTo EndLine '←これをEnd Sub にすると、イベントは、False のままになる
  End If
  i = i + 1
  Loop Until i >= 2 '2度、本当にを出すなら、3を入れます(w)
 ThisWorkbook.Save
EndLine:
 Application.EnableEvents = True 'イベントを戻しておく。
 '' MsgBox ThisWorkbook.Saved '確認用:保存が完了したら、True
End Sub
    • good
    • 0
この回答へのお礼

難しいですね。ほんとに素人同然なんで目が丸くなってしまいました。
興味深いワードもいろいろあるので、一つずつ調べてみようと思います。
ありがとうございました。

お礼日時:2015/11/03 20:08

保存されてしまう理由は、はっきりしています。



Workbook_BeforeSaveイベントの引数に、Cancel as Booleanが指定されていますよね。この引数に対してTrue/Falseを指定することで、セーブを行うかどうかを変えられるんですが、今のコードではCancelに一切手を触れていないため、そのまま保存されてしまいます。

CancelのデフォルトはFalse(保存キャンセルしない)なので、以下のようにすれば、保存されなくなります。

If lngSave = vbYes Then Cancel = True
    • good
    • 0
この回答へのお礼

ありがとうございます。
質問させてもらいたいのですが。

>CancelのデフォルトはFalse(保存キャンセルしない)なので、

すみません。
Cancelは、「(何もしなければ)キャンセルしない」というコードという事ですか?
すると、Cancel=Trueは「キャンセルしない」という意味になりますか?

>If lngSave = vbYes Then Cancel = True

「Saveするとき、Yesを選択したら、キャンセルしない」という理解でよろしいでしょうか?

お礼日時:2015/11/03 18:15

1. 仰る通り、IngSave にvbNo が返った時の処理がありません。


ThisWorkbook.Close とかで閉じてみては。

2、イベントが繰り返し発生しないように
Application.EnableEvents=False
の追記とか。
ただし、どっかでTrueに戻しとかないと、イベンドリブんが効かなくなるので注意。

ちょっといまPC無いとこなんで、ざっくりですみません。
    • good
    • 0
この回答へのお礼

実は、はじめはCloseで行ったんですが、Officeが出すポップアップ(上書きしますか?)よりも先に「本当に保存しますか?」が出てしまうので、Saveに変えたんです。

>Application.EnableEvents=False

こういうコードがあるんですね。勉強になります。
ありがとうございました。

お礼日時:2015/11/03 17:46

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

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A