- 締切済み
EXCEL:他のソフトを使っている間に自動保存する
EXCEL2003です。 ブックは開けっ放しにしておいて、他のアプリケーション(例えばブラウザなど)を使っている間に一定時間が経過すると(例えば3分)自動で保存させたいと思っています。 他のアプリケーションが何になるかは特定でないので、EXCELのマクロで自分自身がアクティブでなくなったことを拾って、そこから一定時間、自分がアクティブにならなかったら自動的に保存する、というVBAを作りたいと思っています。 アドバイスを頂きたいのはアプリケーションレベルで「自分自身がアクティブでなくなったこと」をどうやって拾うか、ということです。 Microsoftサポート(http://support.microsoft.com/kb/213566/ja)やMSDNを参照して、EXCELアプリケーションのイベントを拾おうとしてみたのですが、ブックの切り替えのイベントは拾えても、EXCEL自身がアクティブでなくなったことは拾えないようです。 何か良い方法はないでしょうか。(参考になるURLがあったら教えてください)
お礼
皆さんの回答を参考にして作ってみました。 本来はある程度時間が経過した後に保存されるようにしたかったのですが、手に負えなさそうそうなので、EXCELがアクティブでなくなったときに保存されるようにということで良しとしました。 以下のモジュールをブック内に作成して、ブックのOpenイベントででもDeactiveSaveStartをコールしてもらえれば、あとは放ったらかしでOKです。 EXCELがディアクティブになったとき(他のアプリがアクティブになったとき)に裏で保存されます。(ブックに変更が無いときはスルーします) Option Explicit Public n_hWnd As Long '新しいウィンドウのハンドル Public p_hWnd As Long '元のウィンドウのハンドル 'ウィンドウメッセージ定数 Public Const GWL_WNDPROC = -&H4 'ウインドウプロシージャのアドレスを変更する 'クラス名・キャプションからウィンドウのハンドルを取得する Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 'ウィンドウに関する情報を取得する Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long '指定されたウィンドウの属性を変更する Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long '指定されたウィンドウプロシージャにメッセージ情報を渡す Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Function DeactiveSaveStart() As Integer 'サブクラス化を開始する Dim hWnd As Long Dim strWndCpt As String 'すでにフックされているときは終了する If p_hWnd <> 0 Then Exit Function End If 'ウィンドウハンドルを取得する strWndCpt = Application.Caption hWnd = FindWindow(vbNullString, strWndCpt) 'メッセージフックを開始する p_hWnd = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf DeactiveSaveProc) If p_hWnd = 0 Then DeactiveSaveStart = 0 'フック失敗 Else DeactiveSaveStart = 1 'フック成功 n_hWnd = hWnd End If End Function Public Sub DeactiveSaveStop() 'サブクラス化を終了する Dim lngRet As Long 'サブクラス化されていない場合 If p_hWnd = 0 Then '何もしない Exit Sub End If lngRet = SetWindowLong(n_hWnd, GWL_WNDPROC, p_hWnd) p_hWnd = 0 End Sub Public Function DeactiveSaveProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 'ウインドウプロシージャにメッセージを渡す前にそれを横取りして必要な処理を実行する Dim intFlagActive As Integer Const WM_ACTIVATE = &H6 Const WA_INACTIVE = 0 If Msg = WM_ACTIVATE Then intFlagActive = wParam And &HFFFF& If intFlagActive = WA_INACTIVE Then 'アクティブでなくなったら保存する If Not ThisWorkbook.Saved Then Application.StatusBar = "保存中..." ThisWorkbook.Save Application.StatusBar = "" End If End If End If 'デフォルトウィンドウプロシージャを呼び出す DeactiveSaveProc = CallWindowProc(p_hWnd, hWnd, Msg, wParam, lParam) End Function