2012-04-23 42 views
5

Tôi gặp sự cố trong VBScript mà tôi đang sử dụng với macro VBA/Excel và HTA. Vấn đề là chỉ VBScript, tôi có hai thành phần khác, tức là VBA vĩ mô và HTA front-end làm việc hoàn hảo. Nhưng trước khi tôi giải thích vấn đề, tôi nghĩ rằng để bạn giúp tôi tôi phải giúp bạn hiểu bối cảnh của VBScript. Vì vậy, về cơ bản tất cả các thành phần (VBScript, VBA vĩ mô và HTA) là một phần của một công cụ mà tôi đang xây dựng để tự động hóa một số công việc thủ công. Nó khá nhiều đi như thế này:VBScript - Làm thế nào để làm cho chương trình đợi cho đến khi quá trình kết thúc?

A - HTA

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

  1. tài lựa chọn một số tập tin từ HTA/GUI.
  2. Trong HTML của HTA, có một số VBScript trong thẻ "SCRIPT" chuyển các tệp đầu vào của người dùng 4 làm đối số cho VBScript (được thực thi bởi WScript.exe - bạn có thể tham khảo ghi chú số 1 để rõ ràng)
  3. Kịch bản, cho phép gọi số myScript.vbs từ bây giờ xử lý 4 đối số, 3 trong số đó là tệp cụ thể và 4 là vị trí đường dẫn/thư mục có nhiều tệp trong đó - (xem chú thích # 2) cho rõ ràng)

B - myScript.vbs

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

  1. myScript.vbs mở ra 3 đối số đầu tiên là các tệp Excel. Một trong số đó là tệp * .xlsm có macro VBA của tôi.
  2. myScript.vbs sau đó sử dụng đối số thứ 4 mà là một đường dẫn đến một thư mục chứa nhiều file và gán cho một biến để thông qua một đối tượng FileSystemObject khi gọi GetFolder, tức là

    ... '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. Từ đây tôi tạo ra một vòng lặp để tôi liên tục có thể mở các tập tin trong thư mục và sau đó chạy vĩ mô của tôi, tức là

    ... 
    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 
    ... 
    

Hãy n ote rằng khi 3 tệp Excel đầu tiên đã mở (được kiểm soát bởi mã trước vòng lặp và không được hiển thị ở đây vì tôi không gặp vấn đề gì với phần đó), tôi phải giữ chúng mở.

Đó là các tệp trong thư mục (đã được chuyển làm đối số thứ tư) phải tuần tự mở và đóng. Nhưng inbetween mở và đóng, tôi yêu cầu VBA/macro (viết trong một trong 3 tệp Excel đã mở trước đó) để chạy mỗi lần vòng lặp lặp lại và mở tệp mới từ thư mục (Tôi hy vọng bạn làm theo - nếu không vui lòng cho tôi biết :)).

Sự cố tôi gặp phải là các tệp trong thư mục mở và đóng, mở và đóng, n số lần (n = # tệp trong thư mục, một cách tự nhiên) mà không chờ macro chạy. Đây không phải là điều tôi muốn. Tôi đã cố gắng tuyên bố WScript.sleep với một sự chậm trễ 10 giây sau khi tuyên bố 'x1.Run strMyMacro', nhưng vô ích.

Bất kỳ ý tưởng nào?

Cảm ơn, QF.

GHI CHÚ:

1 - Để đơn giản/rõ ràng đây là cách:

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 Các HTA sử dụng một mảnh của JavaScript mà dải những người sử dụng 4 tập tin đầu vào (HTML: INPUT TYPE = "file ") và chuyển cho VBScript trong HTA. Điều này giúp tôi giải quyết vấn đề không thể chọn độc quyền một FOLDER trong HTML.

+0

bạn có thể thêm 'x4WB.close' đến hết VBA của bạn vĩ mô thay vì trong VBScript ? –

+0

@oraclecertifiedprofessional: Tôi sẽ cung cấp cho nó một whirl cùng với các tài liệu tham khảo khác sau này. Cảm ơn. –

Trả lời

15

Bạn cần phải cho thời gian chờ đợi cho đến khi quá trình này kết thúc. Một cái gì đó như:

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 

Trong chính kịch bản, hãy khởi động Excel như vậy. Trong khi gỡ lỗi bắt đầu nhìn thấy:

File = "c:\test\myfile.xls" 
oShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"" " & File, 1, true 
+0

Có lẽ tôi đã hiểu sai câu hỏi nhưng File Loop nằm trong vbs và do đó phương thức trên không thể được sử dụng để thực hiện kịch bản chờ sau 'x4WB.Close' :) Nhưng như tôi đã nói, tôi có thể hiểu nhầm nó .. –

+0

@peter: Xin chào Peter, tôi nghĩ bạn có thể đã hiểu lầm. Nơi bạn có biến "lệnh" của bạn và sau đó bạn chuyển nó cho đối tượng WScript của bạn, tôi đã làm điều đó trong HTA của tôi. ** MyScript.vbs ** của tôi sau đó tiếp quản và nó nằm trong kịch bản lệnh này mà tôi đang thực hiện tất cả việc xử lý Excel. Tuy nhiên, tôi đã thử ý tưởng của bạn trong ** myScript.vbs ** bằng cách thực hiện: 'Dim WshShell Đặt WshShell = CreateObject (" WScript.Shell ") WshShell.run" C: \ Program Files \ Microsoft Office \ Office14 \ EXCEL.exe "&" "& Fil, 0, true' nhưng điều này trả về lỗi VBScript cho biết tệp không thể tìm thấy ...? –

+0

Ngoài nhận xét của tôi khi tôi hết dung lượng, tôi đã thử nghiệm chuỗi mà tôi đang chuyển đến Excel để kiểm tra xem đó có phải là chuỗi không hợp lệ bằng cách in nó trong MsgBox không. Tuy nhiên, MsgBox cho thấy rằng tôi đang chuyển chuỗi các tập tin vào Excel một cách chính xác. Tôi không hiểu điều gì khác có thể là vấn đề. –

0

Có lẽ một cái gì đó như thế này? (chưa được kiểm tra)

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 
2
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." 
1

này có thể không trả lời đặc biệt dài câu hỏi 3 phần của bạn, nhưng chủ đề này là cũ và tôi thấy điều này trong khi tìm kiếm ngày hôm nay. Dưới đây là một cách ngắn hơn để: "Đợi cho đến khi quá trình hoàn tất". Nếu bạn biết tên của quá trình như "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 

tín dụng đối với: http://crimsonshift.com/scripting-check-if-process-or-program-is-running-and-start-it/

Các vấn đề liên quan