martes, 1 de septiembre de 2015

VBA: Adjuntar hoja activa como pdf al enviar un email desde Excel.

En varias ocasiones me han llegado consultas respecto a la manera de enviar Hojas de nuestros libros de trabajo en Excel como fichero adjunto al enviar nuestros correos...
En principio no es posible tal cosa, ya que Microsoft Outlook sólo permite adjuntar Libros completos... la solución más normal es generar un nuevo Libro y dentro de éste, copiar y pegar la Hoja a enviar.
Hoy haremos una operación algo distinta con una macro.
Generaremos un fichero .pdf temporalmente (luego borraremos como parte del procedimiento) con la hoja activa de nuestro libro, y será este .pdf el que adjuntaremos y enviaremos desde Outlook.


Para ello insertamos el código en un módulo estándar de nuestro proyecto de VBA desde el editor de VB.

Sub EnvioEmail_HojaActiva_comoPDF()
Dim olApp As Object
Dim olMail As Object
Dim RutaTemporal As String, NombreFicheroTemporal  As String, RutaCompleta As String

'deshabilitamos el refresco de pantalla
'y muy importante los eventos!
With Application
    .ScreenUpdating = False
    .EnableEvents = False
End With

'Definimos una variable que será la Ruta donde guardaremos,
'antes de enviar como adjunto, el pdf que generaremos...
RutaTemporal = Environ$("temp") & "\"

'Generamos el nombre del fichero temporal .Pdf
NombreFicheroTemporal = ActiveSheet.Name & ".pdf"

'Combinando las dos variables anteriores, tendremos la Ruta Completa de nuestro .pdf
RutaCompleta = RutaTemporal & NombreFicheroTemporal

'Depuramos posibles errores a la hora de Exportar
' a la ruta anterior, la hoja activa como PDF
On Error GoTo err
ActiveSheet.ExportAsFixedFormat _
        Type:=xlTypePDF, _
        Filename:=RutaCompleta, _
        Quality:=xlQualityStandard, _
        IncludeDocProperties:=True, _
        IgnorePrintAreas:=False, _
        OpenAfterPublish:=False

'LLega el momento de abrir la aplicación Outlook
Set olApp = CreateObject("Outlook.Application")
'y generar un nuevo email a enviar...
Set olMail = olApp.CreateItem(0)

Dim destinatario As String, Asunto As String, Cuerpo As String
'FALTA ASIGNAR VALORES A ESTAS VARIABLES!!!
On Error Resume Next
With olMail
    .to = destinatario          'añadimos el destinatario, el Para...
    '.CC = destinatario         'para adjuntar destinatario en Con Copia a...
    '.BCC = destinatario        'para adjuntar destinatario en Con Copia Oculta a...
    .Subject = Asunto        'indicaríamos el Asunto
    .Body = Cuerpo           'indicaríamos el Cuerpo del email
    'adjuntamos el fichero pdf desde la ruta donde la guardamos
    .Attachments.Add RutaCompleta
    .Display    'o bien usaremos .Send para enviar directamente...
    '.Send
End With
On Error GoTo 0

'Ya que el email ha sido enviado (o mostrado) con el pdf adjuntado
'podemos borrar el pdf que habíamos guardado (en la carpeta temporal)...
Kill RutaCompleta

'limpiamos las variables creadas.
Set olMail = Nothing
Set olApp = Nothing

'Reestablecemos las condiciones prevías
'refresco de pantalla y activamos loe eventos
With Application
    .ScreenUpdating = True
    .EnableEvents = True
End With

Exit Sub

'para el control de errores en caso de exportación como Pdf...
err:
    MsgBox err.Description

End Sub



Si ejecutamos nuestro procedimiento 'EnvioEmail_HojaActiva_comoPDF', veríamos:

VBA: Adjuntar hoja activa como pdf al enviar un email desde Excel.



Observa que al no haber asignado valor a las variables 'Destinatario, 'Asunto' y 'Cuerpo', en el email no han aparecido completados...

13 comentarios:

  1. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  2. BUENAS NOCHES TENGO EL SIGUIENTE CÓDIGO PERO ME INDICA QUE HAY UN ERROR DADO QUE NO ENCUENTRA LA RUTA, ME PUEDEN AYUDAR Y ES QUE YO TENGO QUE ENVIAR UNA LISTA DE PDF'S CON DIFERENTES NOMBRES A DIFERENTES DESTINATARIOS

    Sub EnviarEmail()
    '
    ' Declaramos variables
    '
    Dim OutlookApp As Outlook.Application
    Dim MItem As Outlook.MailItem
    Dim cell As Range
    Dim Asunto As String
    Dim Correo As String
    Dim Destinatario As String
    Dim Recibo As String
    Dim Msg As String
    Dim ADJUNTO, ADJ As Variant

    '
    Set OutlookApp = New Outlook.Application
    '
    'Recorremos la columna EMAIL
    '
    For Each cell In Range("B3:B23")
    '
    'Asignamos valor a las variables
    '
    Destinatario = cell.Offset(0, -1).Value
    Correo = cell.Value
    Recibo = cell.Offset(0, 1).Value
    Asunto = "RECIBO DE NOMINA DE " & Destinatario

    ADJ = "C:\Users\HP2\Desktop\MACRO PARA ENVIAR RECIBOS\" & Range("c3").Value & ".pdf"

    'Cuerpo del mensaje
    '
    Msg = "Buenas Tardes " & Destinatario & vbNewLine & vbNewLine
    Msg = Msg & "Envio recibo correspondiente de la Cta 17 " & vbNewLine
    Msg = Msg & "Atentamente: Teresa Hernandez" & vbNewLine
    Msg = Msg & "Nóminas." & vbNewLine
    '
    Set MItem = OutlookApp.CreateItem(olMailItem)
    With MItem
    .Attachments.Add ADJ
    .To = Correo
    .Subject = Asunto
    .Body = Msg
    .Send

    '
    End With
    '
    Next
    '
    End Sub

    ResponderEliminar
  3. EL ERROR LO ARROJA EN .Attachments.Add ADJ

    ResponderEliminar
    Respuestas
    1. Hola,
      estás seguro existe el pdf en esa ruta con el nombre que toma de la celda C3 ??
      es lo primero a revisar
      Slds

      Eliminar
  4. Buenas tardes, me sale un mensaje
    "error definido por la aplicación o el objeto"

    ResponderEliminar
    Respuestas
    1. Hola Daniel,
      Entiendo has copiado y pegado el código del post tal cual.
      El problema de ese mensaje es que siempre es muy ambiguo... en qué linea se paró el depurador?
      Saludos

      Eliminar
    2. Se para en la ultima línea.

      Eliminar
    3. Hola Daniel,
      ???

      tendría que ver el fichero.. no tiene sentido que se pare en la línea:
      MsgBox err.Description
      si ha llegado ahí es por que existe algún error anterior...
      Puedes enviarme el fichero a:
      excelforo@gmail.com
      ?
      Slds

      Eliminar
  5. Hola!

    Muchas gracias me sirvió muchísimo, Como podría adjuntar todo el archivo (2 pestañas) en pdf?

    Gracias!

    ResponderEliminar
    Respuestas
    1. Hola Karen,
      podrías hacer un bucle
      for each sh in worksheets
      sh.ExportAsFixedFormat ......
      next sh

      es decir, ir exportando hoja a hoja..

      Espero haber entendido bien tu cuestión

      Saludos

      Eliminar
  6. Genial! Muy bueno. Me sirvió de mucho!

    Pero necesito que me des una ayuda.
    Quiero esto mismo, pero poder ponerle un nombre al adjunto que envía y que para eso tome el valor de una celda que tiene el nombre que deberia tener ese adjunto PDF.

    Y Por ultimo, necesito que condicionalmente envie el mail a los destinatarios. Osea... yo tengo que hacer una planilla de rendición de gastos para una empresa, tengo que hacer que el mail lo envie al aprobador que corresponde a ese empleado, y ponga en copia a los correspondientes controladores, y que si es otro empleado pueda elegir a otros destinatarios como aprobadores y controladores.

    Espero que me puedas dar una mano!

    Muchas gracias por tu aporte desde ya!

    ResponderEliminar
    Respuestas
    1. Hola Juanjo,
      en la linea 18
      NombreFicheroTemporal = ActiveSheet.Name & ".pdf"
      cámbialo por
      NombreFicheroTemporal = range("A1").value & ".pdf"
      en A1 estaría el nombre que quieres dar al pdf

      La segunda parte, si la he entendido bien, es más elaborada...pero para condicionar el destinatario podrías emplear un SELECT CASE o un IF.. THEN...

      En todo caso, mejor lee las normas de uso del blog, en particular la parte de peticiones a medida.

      Saludos

      Eliminar