プロが教えるわが家の防犯対策術!

エクセル2000です。
http://odn.okwave.jp/qa3608360.html の関連質問ですが、これだけでも結構ですのでなにとぞご教示ください。

標準モジュールに以下の3つのマクロを書きました。

Sub text_表示()
MsgBox "表示させました。"
End Sub

Sub text_非表示()
MsgBox "非表示にしました。"
End Sub

Sub 保存()
ActiveWorkbook.Save
End Sub

ThisWorkBookモジュールにこう書きました。

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call text_表示
Application.OnTime Now, "text_非表示"
End Sub

これで、手動でBOOKを保存すると、まず、MsgBox "表示させました。" そして MsgBox "非表示にしました。" が実行され、当然ながら書いたとおりの働きをします。
ところが、Sub 保存() でマクロからBOOKを保存すると、MsgBox "表示させました。" だけが実行され、MsgBox "非表示にしました。"は実行されません。
どうして、Application.OnTime Now, "text_非表示"は無視されたのでしょうか?

A 回答 (3件)

ユーザー定義関数をワークシートで使った場合、その関数内に Excel を


操作するコマンド(OnTime なども)無視されますので、それに似た
Excel の制限事項なのかと考えました。

#2 の回答は、全然無関係のことだったのかもしれませんね。
すみません。

> そこから先のコマンドで行なった結果は保存したくないからなのです。

BeforeSave イベント内で

  Cancel = True

として一度保存をキャンセルし、必要なタイミングで自前で保存処理を
行うのではダメなのですか?

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
  Cancel = True
  Range("A1").Value = "保存される"
  Application.EnableEvents = False
  ThisWorkbook.Save
  Application.EnableEvents = True
  Range("B1").Value = "保存されない"
  ThisWorkbook.Saved = True
End Sub
    • good
    • 0
この回答へのお礼

何度も有難うございます。

> 一度保存をキャンセルし、必要なタイミングで自前で保存処理を
> 行うのではダメなのですか?

(^0_0^)ナルホド  目からウロコが・・・・。
素晴らしい解決策です。
KenKen_SPさま、いつも有難うございます。

お礼日時:2007/12/21 13:14

仕様でしょう。



プログラムでブックを保存する場合、BeforeSave イベント内に記載された
メニューコマンドは無視されるようです。

恐らく、別スレッドで保存コマンドが実行(非同期)されるようですから
保存中にブックに変更があっては困るからではないかと。(推測・未確認)
それで、そのような可能性のあるコマンドは無効化されるのでしょうね。

 # Msgbox は大丈夫なんですね。まあ、ブックに変更を与える可能性は
 # ありませんが、、中途半端だ。

機械翻訳
http://support.microsoft.com/kb/898511/ja?spid=1 …
原版
http://support.microsoft.com/kb/898511/en-us

余談: 上記 URL の回避策を引用
この問題を回避するために、手動でブックを保存します。

( ゜д゜)ポカーン
    • good
    • 0
この回答へのお礼

有難うございます。

> プログラムでブックを保存する場合、BeforeSave イベント内に記載された
> メニューコマンドは無視されるようです。

メニューコマンドとはApplication.OnTime Now,で実行させるマクロという意味でしょうか?
標準モジュールの方をMsgBoxではなく以下のように変えて

Sub text_表示()
Cells(2, 2) = "表示"
End Sub

Sub text_非表示()
Cells(3, 3) = "非表示"
End Sub

ThisWorkBookモジュールも

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call text_表示
Call text_非表示
End Sub

にすれば、マクロでブックを保存する場合でも両方とも実行されます。
Application.OnTime Now,でやるからいけないのでしょうが、Application.OnTime Nowを使うのは、そこから先のコマンドで行なった結果は保存したくないからなのです。

お礼日時:2007/12/21 11:14

>どうして、Application.OnTime Now, "text_非表示"は無視されたのでしょうか?



「Application.OnTimeが有効なのは、ユーザー関数を実行していない時だけだから」です。

手動で保存した場合、タイマーが有効になるのは、Workbook_BeforeSaveを抜けた直後です。そして、その瞬間は、まだ「Now」です。つまり、Sub text_非表示()が即座に呼ばれます。

ユーザー関数のSub 保存()で保存した場合、タイマーが有効になるのは、Sub 保存()を抜けた直後です。そして、その瞬間は、もう「Workbook_BeforeSaveの中でApplication.OnTimeで指定したNowを過ぎている」のです。

試しに、そのまま24時間放置してみましょう。「23時間59分59秒+限りなく1秒に近い時間後」の「Nowと同じ時刻になった瞬間」にSub text_非表示()が呼ばれる筈です。

「殆どの場合、Application.OnTimeにNowを指定すると、指定の時刻は24時間後になる」と言う事を覚えておきましょう。

なお「処理が遅いパソコン」を使用した場合、手動でBOOKを保存した場合も「Workbook_BeforeSaveを抜けた直後には、もうNowの時刻を過ぎている」ので、Sub text_非表示()が呼ばれるのは24時間後になります(質問者さんのパソコンが「偶然、間に合うだけの処理速度性能を持っていただけ」の話で、どのパソコンでも間に合うとは限りません)
    • good
    • 0
この回答へのお礼

さっそく有難うございます。
Workbook_BeforeSaveの中でApplication.OnTimeで指定したNowを過ぎているなら、ずらせばいいんですよね?
ためしに10秒後としてみました。
手動ではそうなりました。ところがSub保存()では相変わらず作動しません。
どうしてでしょうか?

コード↓

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call text_表示
Application.OnTime Now + TimeValue("00:00:10"), "text_非表示"
End Sub

お礼日時:2007/12/19 16:55

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