10

VBA/Excel マクロと HTA で使用している VBScript に問題があります。問題は VBScript だけです。他の 2 つのコンポーネント、つまり VBA マクロと HTA フロントエンドは完全に機能しています。しかし、問題を説明する前に、VBScript のコンテキストを理解していただく必要があります。

したがって、基本的にすべてのコンポーネント (VBScript、VBA マクロ、および HTA) は、手作業を自動化するために作成しているツールの一部です。それはほとんど次のようになります:

A - HTA

~~~~~~~~~~~~

  1. ユーザーが HTA/GUI からいくつかのファイルを選択します。
  2. HTA の HTML 内には、「SCRIPT」タグ内にいくつかの VBScript があり、ユーザーの 4 つの入力ファイルを引数として VBScript に渡します (WScript.exe によって実行されます - ここで明確にするために、注 #1 を参照してください)。
  3. スクリプトは、これからはmyScript.vbsと呼び、4 つの引数を処理します。そのうちの 3 つは特定のファイルで、4 番目は複数のファイルが含まれるパス/フォルダーの場所です (わかりやすくするために、注 #2 も参照してください)。

B - myScript.vbs

~~~~~~~~~~~~

  1. myScript.vbs は、Excel ファイルである最初の 3 つの引数を開きます。そのうちの 1 つは、私の VBA マクロを含む *.xlsm ファイルです。
  2. 次に、myScript.vbs は、複数のファイルを含むフォルダーへの PATH である 4 番目の引数を使用し、それを変数に割り当てて、GetFolder を呼び出すときに FileSystemObject オブジェクトに渡します。

    ... 'Other code here, irrelevant for this post
    Dim FSO, FLD, strFolder
    ... 'Other code here, irrelevant for this post
    arg4 = args.Item(3)
    strFolder = arg4
    Set FSO = CreateObject("Scripting.FileSystemObject"
    'Get a reference to the folder you want to search
    Set FLD = FSO.GetFolder(strFolder)
    ...
    
  3. ここからループを作成して、フォルダー内のファイルを順番に開き、マクロを実行できるようにします。

    ...
    Dim strWB4, strMyMacro
    strMyMacro = "Sheet1.my_macro_name"
    
    'loop through the folder and get the file names
    For Each Fil In FLD.Files
    
        Set x4WB = x1.Workbooks.Open(Fil)
    x4WB.Application.Visible = True
    
    x1.Run strMyMacro
    
    x4WB.close
    Next 
    ...
    

最初の 3 つの Excel ファイルを開いたら (ループ前のコードによって制御され、その部分に問題がないためここには表示されません)、それらを開いたままにしておく必要があることに注意してください。

順番に開いたり閉じたりする必要があるのは、(4 番目の引数として渡された) フォルダー内のファイルです。ただし、開いてから閉じるまでの間に、ループが繰り返されてフォルダーから新しいファイルが開かれるたびに、VBA/マクロ (以前に開いた 3 つの Excel ファイルの 1 つに書き込まれたもの) を実行する必要があります (フォローしていただければ幸いです - そうでない場合は、私にさせてください知る :) )。

私が抱えている問題は、マクロが実行されるのを待たずに、フォルダー内のファイルが n 回 (n = フォルダー内のファイルの数、当然) 開いたり閉じたり、開いたり閉じたりすることです。これは私が望むものではありません。「x1.Run strMyMacro」ステートメントの後に 10 秒遅れて WScript.sleep ステートメントを試しましたが、役に立ちませんでした。

何か案は?

ありがとう、QF。

ノート:

1 - 簡単/明確にするために、次のようにします。

    strCMD = cmd /c C:\windows\system32\wscript.exe myScript.vbs <arg1> <arg2> <arg3> <arg4>
    'FYI - This is run by creating a WShell object, wsObj, and using the .run method, i.e. WShell.run(strCMD)

2 HTA は、ユーザーの 4 番目の入力ファイル (HTML: INPUT TYPE="file") を取り除き、それを HTA 内の VBScript に渡す JavaScript の一部を使用します。これにより、HTML で FOLDER を排他的に選択できないという問題を回避できます。

4

4 に答える 4

20

プロセスが完了するまで待機するように実行に指示する必要があります。何かのようなもの:

const DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true
set oShell = WScript.CreateObject("WScript.Shell")
command = "cmd /c C:\windows\system32\wscript.exe <path>\myScript.vbs " & args
oShell.Run command, DontShowWindow, WaitUntilFinished

スクリプト自体では、Excel を次のように起動します。デバッグ開始が表示されている間:

File = "c:\test\myfile.xls"
oShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"" " & File, 1, true
于 2012-04-23T11:39:46.690 に答える
5
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")
objWMIService.Create "notepad.exe", null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
    Set objLatestProcess = colMonitoredProcesses.NextEvent
    If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
        i = 1
    End If
Loop
Wscript.Echo "Notepad has been terminated."
于 2014-10-27T13:23:53.040 に答える
1

たぶん、こういうこと?(未テスト)

Sub Sample()
    Dim strWB4, strMyMacro
    strMyMacro = "Sheet1.my_macro_name"

    '
    '~~> Rest of Code
    '

    'loop through the folder and get the file names
    For Each Fil In FLD.Files
        Set x4WB = x1.Workbooks.Open(Fil)
        x4WB.Application.Visible = True

        x1.Run strMyMacro

        x4WB.Close

        Do Until IsWorkBookOpen(Fil) = False
            DoEvents
        Loop
    Next

    '
    '~~> Rest of Code
    '
End Sub

'~~> Function to check if the file is open
Function IsWorkBookOpen(FileName As String)
    Dim ff As Long, ErrNo As Long

    On Error Resume Next
    ff = FreeFile()
    Open FileName For Input Lock Read As #ff
    Close ff
    ErrNo = Err
    On Error GoTo 0

    Select Case ErrNo
    Case 0:    IsWorkBookOpen = False
    Case 70:   IsWorkBookOpen = True
    Case Else: Error ErrNo
    End Select
End Function
于 2012-04-23T11:29:29.813 に答える
0

これはあなたの長い 3 部構成の質問に具体的に答えるものではないかもしれませんが、このスレッドは古く、今日検索中にこれを見つけました。「プロセスが終了するまで待つ」という短い方法を次に示します。「EXCEL.EXE」などのプロセス名がわかる場合

strProcess = "EXCEL.EXE"    
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
Do While colProcesses.Count > 0
    Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
    Wscript.Sleep(1000) 'Sleep 1 second
   'msgbox colProcesses.count 'optional to show the loop works
Loop

クレジット: http://crimsonshift.com/scripting-check-if-process-or-program-is-running-and-start-it/

于 2018-01-17T19:22:01.330 に答える