• ベストアンサー

エクセルでWorkbook_BeforeSaveイベントについての疑問

エクセル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_非表示"は無視されたのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.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

merlionXX
質問者

お礼

何度も有難うございます。 > 一度保存をキャンセルし、必要なタイミングで自前で保存処理を > 行うのではダメなのですか? (^0_0^)ナルホド  目からウロコが・・・・。 素晴らしい解決策です。 KenKen_SPさま、いつも有難うございます。

その他の回答 (2)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

仕様でしょう。 プログラムでブックを保存する場合、BeforeSave イベント内に記載された メニューコマンドは無視されるようです。 恐らく、別スレッドで保存コマンドが実行(非同期)されるようですから 保存中にブックに変更があっては困るからではないかと。(推測・未確認) それで、そのような可能性のあるコマンドは無効化されるのでしょうね。  # Msgbox は大丈夫なんですね。まあ、ブックに変更を与える可能性は  # ありませんが、、中途半端だ。 機械翻訳 http://support.microsoft.com/kb/898511/ja?spid=1743&sid=434 原版 http://support.microsoft.com/kb/898511/en-us 余談: 上記 URL の回避策を引用 この問題を回避するために、手動でブックを保存します。 ( ゜д゜)ポカーン

merlionXX
質問者

お礼

有難うございます。 > プログラムでブックを保存する場合、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を使うのは、そこから先のコマンドで行なった結果は保存したくないからなのです。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

>どうして、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時間後になります(質問者さんのパソコンが「偶然、間に合うだけの処理速度性能を持っていただけ」の話で、どのパソコンでも間に合うとは限りません)

merlionXX
質問者

お礼

さっそく有難うございます。 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

関連するQ&A

  • VBAのWorkbook_BeforeSaveイベントについての疑問

    エクセル2000です。 前にも似たような質問をしたのですが理解ができていません。 ThisWorkbookモジュールに以下の記述をし、終了時保存する場合にはSheet2を表に出すようにしました。 Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Sheets("Sheet1").Range("A65536").End(xlUp).Offset(1).Value = Time() Sheets("Sheet2").Select MsgBox "保存します。" & ActiveSheet.Name Sheets("Sheet1").Range("B65536").End(xlUp).Offset(1).Value = Time() End Sub これで×を押して手動で終了すればそのとおりに働きます。ActiveSheet.Nameも当然Sheet2になります。 ところが、標準モジュールの下記の終了マクロ Sub 終了() ThisWorkbook.Close End Sub で終了しようとすると、A列セルにTime()は記録され、どういうわけかSheet2がSelectされず、MsgBox "保存します。" のメッセージが出て、B列セルにTime()が記録され、保存されます。 ActiveSheet.NameもSheet2ではありません。 つまり、Sheets("Sheet2").Select の部分だけが完全にスキップされてしまうのです。 どうしてでしょうか?

  • Private Sub Workbook_BeforeSaveについて

    エクセル2000です。 腑に落ちない現象が起きているので質問させてください。 Sheet1にテキストボックス(OLEオブジェクトのTextboxではありません)とボタンが貼ってあり、Visble=Falseで非表示にしています。それを保存する際には表示させたいので、BeforeSaveイベントで Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Sheet1.TextBoxes("テキスト").Visible = True Sheet1.Buttons("ボタン").Visible = True MsgBox "保存されちゃった!" End Sub と書いてみました。 手動で保存する場合には正しく、テクストボックスやボタンは正しく表示されます。もちろんMsgboxも出ます。 ところが、標準モジュールに書いた以下のコード、 Sub 保存() ActiveWorkbook.Save End Sub を走らせてみても、"保存されちゃった!"と、Msgboxは出ますが、肝心のテクストボックスやボタンが表示されません。 試行錯誤の結果、 Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Sheet1.Shapes("テキスト").Visible = True Sheet1.Shapes("ボタン").Visible = True MsgBox "保存されちゃった!" End Sub と書くと、標準モジュールから、ActiveWorkbook.Saveでも表示されることがわかりました。 どうしてでしょうか?

  • VBAのOnTimeの停止について

    下記コードで右上の×ボタン(エクセルアプリではなくbookを閉じる×です)でCLOSEした場合は停止されるのですが、 ThisWorkbook.Closeで閉じた場合MsgBox "timer cxl"は呼ばれるのですがタイマーがキャンセルできず10秒後に閉じたbookが勝手に開かれMsgBox "chk"が呼ばれてしまいます。 エクセルは2003、WIN10です。 どなたか何か原因や回避策があればご教授お願い致します。 //標準モジュール Public timer As Date Public timerFlag As Boolean Sub chk() timerFlag = False MsgBox "chk" End Sub //ThisWorkbook Private Sub Workbook_Open() timer = Now + TimeValue("00:00:10") timerFlag = True Application.OnTime timer, "chk" MsgBox "open" End Sub Private Sub Workbook_BeforeClose(Cancel As Boolean) If timerFlag Then Application.OnTime timer, "chk", , False MsgBox "timer cxl" End If MsgBox "close" End Sub

  • エクセルVBAの不思議な挙動?

    エクセル2003です。 ThisWorkbookには以下の記述があります。 Private Sub Workbook_BeforePrint(Cancel As Boolean) If ActiveSheet.Name <> "Sheet1" Then Exit Sub If Range("A1").Value = "" Then MsgBox "A1が未入力です" Range("A1").Select Cancel = True End If Application.OnTime Now(), "ページ移動" End Sub 標準モジュールには以下の記述があります。 Sub ページ移動() Sheets("Sheet2").Select Range("A1").Select End Sub Sub プリント() ActiveWindow.SelectedSheets.PrintPreview End Sub これでSheet1を開いた状態でツールバーから印刷プレビュー指示をすると、A1セルが入力済みであればプレビュー画面を出し、プレビューを閉じればSheet2が表示されます。 ところが、同じ状態でツールバーからではなく、マクロ Sub プリント を実行すると、プレビュー画面にはなりますが、プレビューを閉じてもSheet1のままです。 なぜ、 Application.OnTime Now(), "ページ移動" が、有効にならないのでしょうか?

  • Workbook_BeforeClose イベントで

    Win2000Pro SP-4、Office2000 SP-3使用しています。 ExcelVBAのブックを閉じる時のイベントで、オートフィルタの解除と再設定を行い、上書き保存するコードを記述いたしました。 しかし実行後ファイルを開いてみるとオートフィルタの解除だけされており、再設定がされておりませんでした。 上書き保存のコードを省くと再設定されていました。 標準モジュールに同じコードを記述して実行した場合も同様の結果になりました。 解決法がおわかりの方がいらっしゃいましたらお教えくださいませ。 以下のコードをThisWorkbook内に記述しました。 Private Sub Workbook_BeforeClose(Cancel As Boolean)  Application.ScreenUpdating = False    Worksheets(1).AutoFilterMode = False    Range("10:10").AutoFilter    Range("B11").Select    ActiveWorkbook.Close SaveChanges:=True  Application.ScreenUpdating = True End Sub よろしくお願いいたします。

  • エクセルシートの順繰り表示マクロについて

    エクセルにて随時更新されるデータを全画面表示し、3枚のシートを5秒置きに順繰り表示させるようマクロを組みました。始めは順調なのですが、数時間たつとフリーズしてしまいます。そもそもエンドレスのマクロプログラム実行に無理があるのでしょうか。 または下記のプログラムに問題があるのでしょうか。ご教授お願いします。 Sub Macro1() Sheets("Sheet2").Select Application.OnTime Now + TimeValue("00:00:05"), "Macro2" End Sub Sub Macro2() Sheets("Sheet3").Select Application.OnTime Now + TimeValue("00:00:05"), "Macro3" End Sub Sub Macro3() Sheets("Sheet1").Select Application.OnTime Now + TimeValue("00:00:05"), "Macro1" End Sub

  • エクセルVBAにて保存するとき

    Private Sub Workbook_BeforeClose(Cancel As Boolean) If MsgBox("エクセルを終了してもよろしいですか?", vbYesNo) = vbNo Then Cancel = True Exit Sub End If Application.DisplayAlerts = False Application.Quit End Sub Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) MsgBox "そのボタンでは保存できません。" & vbCrLf & _ "雛形は残しておきましょう" & vbCrLf & _ "" & vbCrLf & _ "ツールバーの「マクロなし出力」から保存できます。" Cancel = True End Sub という二つのマクロをThisworkbookにいれてあるんですが、 この二つを有効(今は2つ目を'でコメント状態にしてあるので保存可)にすると保存できなくて困っています。 二つを有効にした時はどのようにほぞんすればいいですか?

  • エクセル ブック(マクロを含む)を保存してとじると、また開きます。

    ブックに保護をかけた状態で保存してあります。 共有状態にあり、マクロを有効にしてもらいたいので、 (1)開くときに保護解除 (2)保存のときに、保護をかけて保存後、(まだ閉じるとは限らないので)保護解除 ということをやろうとし、以下のように書きました。 エクセルごとではなく、このファイルのみ終了しようとすると、 開いた後と上書保存後に保護を解除する為、 ファイルを終了する時には必ず「変更を保存しますか?」と訊かれ、 その時に「はい」を選択すると、一度はそのファイルが終了するのですが、 すぐに マクロを含むファイルを開くときに出るメッセージ「セキュリティ警告マクロ マクロ有効 マクロ無効 詳細」が出て、また開こうとします。 保存「いいえ」を選択すると、普通に終了します。 エクセルごとを終了すれば保存「はい」にしても、普通に終了します。 このファイルのみ終了する時、保存の確認で、「はい」を選び、普通に終了するには、何を直したらよいでしょうか? その前に、根本的に間違ってたりしますでしょうか・・・。 よろしくお願いします。 ThisWorkbookに、 Private Sub Workbook_Open() ActiveSheet.Unprotect Password:="(パスワード)" End Sub Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) ActiveSheet.Protect Password:="(パスワード)" Application.OnTime Now, "保護解除" End Sub 標準モジュールに、 Sub 保護解除() ActiveSheet.Unprotect Password:="(パスワード)" End Sub

  • エクセル デバッグできるのとできないのがある

    シートイベントについて教えてください。 シートモジュールに --------------------------------------------------------- Option Explicit Private Sub Worksheet_Activate() MsgBox "" End Sub Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) MsgBox "" End Sub Private Sub Worksheet_Change(ByVal Target As Range) MsgBox "" End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) MsgBox "" End Sub --------------------------------------------------------- と記載した時に、 F8で動かせるのは、Worksheet_Activateだけなのですがなぜでしょうか? ほかのイベントは、F8で実行させても、OSの音が鳴るだけで、マクロの実行はされません。 ご回答よろしくお願いします。

  • EXCEL VBA Workbook_BeforeSaveについて

    教えて下さい! 会社のホームページにある情報を公開していて、その中に更新時間も載せております。その公開している文章はEXCELを利用しHTMファイルで保存しております。ファイルは社内の共有ファイルサーバーに保存されており、複数にて共有しています。そのEXCEL HTMファイルを編集し、(上書き)保存をした際、その時の時間を更新日時としてあるセルに表示させております。自身でVBAを以下の組みました。 (保存前処理の他、開いた時の列幅処理+前回更新日時の表示も行っています) Option Explicit --------------------------------------------------------- Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Dim KOUSHINBI As Date KOUSHINBI = Now Range("E2").Value = KOUSHINBI End Sub --------------------------------------------------------------- Private Sub Workbook_Open() MSGDISP '前回更新時間の表示 Dim TODAY As Date, KOUSHIN As Date KOUSHIN = DateValue(Range("E2").Value) TODAY = Date If KOUSHIN <> TODAY Then Columns("B:D").ColumnWidth = 0 End If End Sub -------------------------------------------------------- '以下標準モジュールで Sub MSGDISP() Dim A As Date A = Worksheets("DAILY").Range("E2").Value MsgBox ("前回の更新日時は" & A & "です") End Sub --------------------------------------------- もちろん、 Workbook_BeforeSaveと Workbook_Openは「THIS WORKBOOK」モジュールに記載しております。 これを実行すると、BOOK OPENの処理は行われるのですが、保存時の更新日時の処理が全く起きてくれません。 新規でEXCELを作成し、Workbook_BeforeSaveのみの処理を記述すると上手く処理が行われます。何が原因なのでしょうか??

専門家に質問してみよう