J'ai un problème dans un script VBScript que j'utilise avec une macro VBA/Excel et un HTA. Le problème ne concerne que le VBScript. J'ai les deux autres composants, c’est-à-dire que la macro VBA et le HTA Front-end fonctionnent parfaitement. Mais avant d’expliquer le problème, je pense que pour que vous puissiez m'aider, je dois vous aider à comprendre le contexte du VBScript.
En gros, tous les composants (VBScript, macro VBA et HTA) font partie d’un outil que je construis pour automatiser certaines tâches manuelles. C'est à peu près comme ça:
~~~~~~~~~~~~~
~~~~~~~~~~~~~
myScript.vbs utilise ensuite le 4ème argument, qui est un chemin PATH vers un dossier contenant plusieurs fichiers, et l'affecte à une variable à transmettre à un objet FileSystemObject lors de l'appel de GetFolder, c'est-à-dire.
... '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)
...
À partir de là, je crée une boucle pour pouvoir ouvrir séquentiellement les fichiers du dossier .__, puis exécuter ma macro, c.-à-d.
...
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
...
Veuillez noter que lorsque les 3 premiers fichiers Excel sont ouverts (contrôlés par le code avant la boucle, et non affichés ici car je n’ai aucun problème avec cette partie), je dois les garder ouverts.
Ce sont les fichiers du dossier (passé en tant que 4ème argument) qui doivent être ouverts et fermés de manière séquentielle. Mais entre l’ouverture et la fermeture, j’ai besoin de la macro/VBA (écrite dans l’un des 3 fichiers Excel précédemment ouverts) à exécuter à chaque fois la boucle itère et ouvre un nouveau fichier à partir du dossier (j'espère que vous suivrez - si pas s'il vous plaît laissez-moi savoir :)).
Le problème que je rencontre est que les fichiers du dossier s’ouvrent et se ferment, s’ouvrent et se ferment, n nombre de fois (n = n ° de fichiers dans le dossier, naturellement) sans attendre que la macro s’exécute. Ce n'est pas ce que je veux. J'ai essayé l'instruction WScript.sleep avec un délai de 10 secondes après l'instruction 'x1.Run strMyMacro', mais en vain.
Des idées?
Merci, QF.
REMARQUES:
1 - Pour plus de simplicité/clarté, voici comment:
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 Le HTA utilise un morceau de JavaScript qui supprime le 4ème fichier d'entrée de l'utilisateur (HTML: INPUT TYPE = "fichier") et le transmet au VBScript du HTA. Cela m'empêche de ne pas pouvoir sélectionner exclusivement un DOSSIER en HTML.
Vous devez indiquer à la course d'attendre que le processus soit terminé. Quelque chose comme:
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
Dans le script lui-même, démarrez Excel comme suit. Pendant que le débogage commence visible:
File = "c:\test\myfile.xls"
oShell.run """C:\Program Files\Microsoft Office\Office14\Excel.EXE"" " & File, 1, true
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."
Cela ne répond peut-être pas spécifiquement à votre longue question en 3 parties mais ce fil est ancien et je l’ai trouvé en cherchant aujourd’hui. Voici un moyen plus court de: "Attendre la fin d'un processus." Si vous connaissez le nom du processus tel que "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
Crédit à: http://crimsonshift.com/scripting-check-if-process-or-program-is-running-and-start-it/
Probablement quelque chose comme ça? (NON TEST&EACUTE;)
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