Gestión de Procesos (Imprimir PDFs)

Hace algún tiempo, me pidieron que hiciera un código para imprimir los pdfs de una lista en Excel, dicha lista eran unos hiperviculos que apuntaban a pdfs en el disco duro y se tenia que recorrer todas las celdas que tuvieran hipervinculos e imprimir el pdf apuntado.
Desde VBA es fácil abrir Adobe Reader e imprimir el pdf, pero después de imprimir, VBA ya no puede cerrar Adobe Reader y al final quedan múltiples instancias del Adobe Reader abiertas y es muy molesto y poco practico.
Utilizando solamente VBA no es posible controlar los procesos que se inician pero desde VBA podemos hacer uso de APIs de Windows para controlar los procesos así que eso fue lo que hice.
La idea entonces era

  1. Ver si la celda tiene hiperviculo
  2. Obtener la ruta del pdf
  3. Abrir Adobe Reader con la instrucción de Imprimir el PDF
  4. Capturar el ID del proceso(Adobe Reader) que se inicia
  5. Esperar que se Imprima el PDF
  6. Obtener el handle(manejador) del proceso(Adobe Reader)
  7. Cerrar el proceso(Adobe Reader)
  8. Ir a la siguiente celda y regresar al paso 1

De estos pasos lo que no se puede hacer VBA es el paso 6 y el paso 7 para ello necesitamos las siguientes APIs:
OpenProcess: su función es obtener el handle de un proceso mediante su ID (que se obtiene en el paso 4)
TerminateProcess: su función como su nombre lo indica es terminar un proceso mediante su handle(que se obtiene en el paso 4 con la API anterior)

Finalmente el código queda de esta forma

 

Public Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Const PROCESS_TERMINATE As Long = (&H1) 'Para poder utilizar el handle para cerrar el proceso

Sub ImprimirPDFs()
    Dim CeldaInicial As String
    Dim rutaPDF As String
    Dim i As Integer
    Dim pid As Long
    Dim hnd As Long
    CeldaInicial = "B3"'Celda inicial
    Do While Sheets("Hoja1").Range(CeldaInicial).Offset(i).Hyperlinks.Count > 0'Paso 1
        rutaPDF = Empty
        rutaPDF = Sheets("Hoja1").Range(CeldaInicial).Offset(i).Hyperlinks(1).Address'Paso 2
        If rutaPDF <> Empty Then
            pid = Shell("C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe /p /h """ & rutaPDF & """", vbMinimizedNoFocus)'Paso 3 y 4
            DoEvents'Paso 5
            hnd = OpenProcess(PROCESS_TERMINATE, True, pid)'Paso 6
            TerminateProcess hnd, 0'Paso 7
        End If
        i = i + 1'Paso 8
    Loop
End Sub

 

De esta manera el código imprime todos los pdf a los que apuntan las celdas que tienen hipervinculos, es decir, abre Adobe Reader, imprime, cierra el Adobe Reader y repite el proceso, y al final no quedan instancias de Adobe Reader Abiertas.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s