Espere a que finalice Shell, luego formatee las celdas: ejecute un comando sincrónicamente
Tengo un ejecutable al que llamo usando el comando de shell:
Shell (ThisWorkbook.Path & "\ProcessData.exe")
El ejecutable realiza algunos cálculos y luego exporta los resultados a Excel. Quiero poder cambiar el formato de los resultados DESPUÉS de exportarlos.
En otras palabras, primero necesito el comando Shell para ESPERAR hasta que el ejecutable finalice su tarea, exporte los datos y LUEGO realice los siguientes comandos para formatear.
Probé el Shellandwait()
, pero sin mucha suerte.
Tuve:
Sub Test()
ShellandWait (ThisWorkbook.Path & "\ProcessData.exe")
'Additional lines to format cells as needed
End Sub
Desafortunadamente, aún así, el formateo se realiza antes de que finalice el ejecutable.
Sólo como referencia, aquí estaba mi código completo usando ShellandWait
' Start the indicated program and wait for it
' to finish, hiding while we wait.
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Const INFINITE = &HFFFF
Private Sub ShellAndWait(ByVal program_name As String)
Dim process_id As Long
Dim process_handle As Long
' Start the program.
On Error GoTo ShellError
process_id = Shell(program_name)
On Error GoTo 0
' Wait for the program to finish.
' Get the process handle.
process_handle = OpenProcess(SYNCHRONIZE, 0, process_id)
If process_handle <> 0 Then
WaitForSingleObject process_handle, INFINITE
CloseHandle process_handle
End If
Exit Sub
ShellError:
MsgBox "Error starting task " & _
txtProgram.Text & vbCrLf & _
Err.Description, vbOKOnly Or vbExclamation, _
"Error"
End Sub
Sub ProcessData()
ShellAndWait (ThisWorkbook.Path & "\Datacleanup.exe")
Range("A2").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlTop
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
End Sub
Pruebe el objeto WshShell en lugar de la función nativa Shell
.
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim errorCode As Long
errorCode = wsh.Run("notepad.exe", windowStyle, waitOnReturn)
If errorCode = 0 Then
MsgBox "Done! No error to report."
Else
MsgBox "Program exited with error code " & errorCode & "."
End If
Aunque tenga en cuenta que:
Si
bWaitOnReturn
se establece en falso (el valor predeterminado), el método Ejecutar regresa inmediatamente después de iniciar el programa, devolviendo automáticamente 0 (no debe interpretarse como un código de error).
Entonces, para detectar si el programa se ejecutó exitosamente, debe waitOnReturn
configurarlo en Verdadero como en mi ejemplo anterior. De lo contrario, simplemente devolverá cero pase lo que pase.
Para el enlace anticipado (da acceso a Autocompletado), establezca una referencia a "Modelo de objetos de Windows Script Host" (Herramientas > Referencia > establecer marca de verificación) y declare así:
Dim wsh As WshShell
Set wsh = New WshShell
Ahora, para ejecutar su proceso en lugar del Bloc de notas... Espero que su sistema se oponga a las rutas que contienen caracteres de espacio ( ...\My Documents\...
,, ...\Program Files\...
etc.), por lo que debe encerrar la ruta entre "
comillas "
:
Dim pth as String
pth = """" & ThisWorkbook.Path & "\ProcessData.exe" & """"
errorCode = wsh.Run(pth , windowStyle, waitOnReturn)
Lo que tienes funcionará una vez que agregues
Private Const SYNCHRONIZE = &H100000
que te falta. (El significado 0
se transmite como cuyo derecho de acceso OpenProcess
no es válido)
Hacer Option Explicit
la línea superior de todos sus módulos habría generado un error en este caso