Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
explorer.exeを実行し閉じるまで待つ方法について
投稿日時: 17/10/05 15:16:27
投稿者: ふぁんふぁn

その他関連のテクニックの「外部プログラムの実行と処理待ち(APIを利用した同期処理)|Excel VBA」を参考に、外部プログラムが終了するまで次処理を待つようにしたいのですが、電卓等で試すと処理が終わるまで次処理には進みませんが、"C:\Windows\explorer.exe "を起動するとPC(自身)を表示してすぐにマクロが終了してしまいます。
 
explorer.exe の終了を待機する事は出来ないのでしょうか。
 
電卓起動〜終了のサンプル
-----------------------------------------------------------------------------------------
eclare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
                                     ByVal dwMilliseconds As Long) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
                                             ByVal bInheritHandle As Long, _
                                             ByVal dwProcessId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'--- Win32 API 定数の宣言 ---
Public Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
Public Const INFINITE As Long = &HFFFF
 
Sub WaitRun1()
    Dim TaskId As Long 'タスクID
    Dim hProc As Long 'プロセスハンドル
 
    ' 外部プログラムの実行
    TaskId = Shell("C:\WINDOWS\SYSTEM32\CALC.EXE", vbMinimizedFocus)
    ' プロセスハンドルの取得
    hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, TaskId)
    ' プロセスハンドルが返されたかを判定
    If hProc <> 0 Then
        ' プロセスのシグナル待ち
        Cells(42, 4) = "起動"   
        Call WaitForSingleObject(hProc, INFINITE)
        ' プロセスクローズ
        CloseHandle hProc
        Cells(44, 4) = "終了" ← 電卓を終了させたらセルに書き込まれた
    End If
End Sub
-----------------------------------------------------------------------------------------
 
TaskId を explorer.exe に変更
    TaskId = Shell("C:\WINDOWS\explorer.exe ", vbMinimizedFocus)
      :
        Cells(44, 4) = "終了" ← explorer.exeを実行した直後にセルに書き込まれた
 

回答
投稿日時: 17/10/07 14:28:43
投稿者: simple

原因は(私には)よく分かりませんので、他の方からの回答を待って頂きたいのですが、
そもそもExplorerを開く目的は何ですか?
別の方法で対応できる可能性があるかもしれませんよ?

投稿日時: 17/10/10 13:46:20
投稿者: ふぁんふぁn

simple さんの引用:
原因は(私には)よく分かりませんので、他の方からの回答を待って頂きたいのですが、
そもそもExplorerを開く目的は何ですか?
別の方法で対応できる可能性があるかもしれませんよ?

 
Explorerを開く理由です。
 ・「○月○日_苗字.xls」 このようなブック(日報)が毎日30件程度(課員分)作成されます。
   保存先:日報フォルダ 
   フォルダ内には一日分のブックを保存します。
 ・翌日、日報処理マクロにて前日の日付「○月○日」と言う名前でフォルダを作成します。
 ・日報フォルダ内の同じ日付のブックを○月○日フォルダにコピーします。
 ※本来、日報処理マクロは一日1回実行ですが、日報の入力漏れ・忘れで、前日の日報をマクロ実行
  日に入力完了される事があります。
  日報処理マクロを再処理した場合、フォルダが作成済であるため、漏れ分のブックを手動でコピー
  したく、On Error Resume Nextでフォルダ作成エラー処理として、次のようにしたいと思っていま
  す。
   1)Msgboxにて「日報フォルダを開いてください。」⇒手動で日報フォルダを開く
      2)作成済の○月○日フォルダをマクロで開く
      3)日報フォルダから○月○日フォルダに手動でブックをコピーする
   4)○月○日フォルダを閉じる 
    ※閉じられるのを待って5)次処理を行いたいが、現在はMsgBox後に5)次処理を実行してしまう
   5)次処理
 
とりあえずですが、今は 4)と5)の間に MsgboxでWaitさせ、コピー完了後に Msgbox に応答して5)次処理
を行うようにしました。

回答
投稿日時: 17/10/10 20:37:16
投稿者: simple

回答コメントありがとうございました。
  
タイムラグがあって遅れて作成されたファイルをコピーするなら、
Explorerという重い処理を立ち上げなくても、
GetOpenFilenameを使って、複数の対象ファイルたちを指定して、
そのあとでコピー処理をするコードを作ればどうでしょうか。
GetOpenFilenameはファイル選択が終了するまできちんと待っていてくれます。
   
中身がよくわからない、動作がコントロールできない道具に頼るより
よほど健全ではないかと思います。
   
以下は、ご存じかと思いますが、念のためメモしておきます。
   
1. GetOpenFilenameについては以下を参考にして下さい。
[ファイルを開く]ダイアログボックスを表示する(GetOpenFilenameメソッド)
http://www.moug.net/tech/exvba/0060013.html
     
2.ファイルのコピーについては、 FileCopy ステートメントがよろしいでしょう。

投稿日時: 17/10/16 17:20:06
投稿者: ふぁんふぁn

simple さんの引用:
GetOpenFilenameを使って、複数の対象ファイルたちを指定して、
そのあとでコピー処理をするコードを作ればどうでしょうか。
GetOpenFilenameはファイル選択が終了するまできちんと待っていてくれます。
       :
       :
ファイルのコピーについては、 FileCopy ステートメントがよろしいでしょう。

 
simple 様、ご教授ありがとうございました。
2つのフォルダを開く事がナンセンスでしたね、アドバイスのようにGetOpenFilenameでコピー元を開き、ファイルを指定して複写先フォルダにFileCopyの方法でしたい事が簡単にできるようになりました。
ありがとうございました。
 
アドバイスをいただいて作成したマクロ(テスト用)です。
Sub sample1()
     
    Dim OpenFileName As Variant
    Dim 複写先フォルダ, i
    Dim FileName As String
     
    複写先フォルダ = "C:\Users\k12345\Desktop\VBA関係\複写先\"
     
    ChDir "C:\Users\k12345\Desktop\VBA関係\複写元"
    OpenFileName = Application.GetOpenFilename(FileFilter:="Excelファイル,*.xls*", MultiSelect:=True)
 
    If IsArray(OpenFileName) Then
        For i = LBound(OpenFileName) To UBound(OpenFileName)
         '確認用-Start
            MsgBox "指定されたファイルは、" & OpenFileName(i) & " です。", vbInformation
            FileName = Dir(OpenFileName(i))
            Range("M" & i + 25) = FileName
            Range("B" & i + 25) = OpenFileName(i)
         '確認用-End
            FileCopy OpenFileName(i), _
                 複写先フォルダ & FileName
        Next i
      '複写処理が完了したら電卓を起動する(確認用)
        TaskId = Shell("C:\WINDOWS\SYSTEM32\CALC.EXE", vbMinimizedFocus)
    Else
        MsgBox "キャンセルがクリックされました。", vbInformation
    End If