domingo, 6 de octubre de 2024
¡Nunca más olvides un cumpleaños usando Excel y Power Automate!
domingo, 3 de marzo de 2024
¿Es verdad que ya no podremos usar macros en Outlook?
¿Es verdad que ya no podremos usar macros en Outlook?
¡Saludos!
Abraham Valencia
Lima, Perú
sábado, 15 de enero de 2022
Microsoft Outlook desde Excel (V): Imagen en el cuerpo del mensaje (Sin errores)
Durante muchos años en internet se han publicado un sinfín de artículos sobre el envío de correo electrónico a través del VBA de Excel. Yo mismo he publicado varias cosas al respecto haciendo uso de Microsoft Outlook o, mejor dicho, a través del objeto Outlook.
En el sentido de lo mencionado en el párrafo anterior, una de las preguntas recurrentes sobre el tema es sobre cómo dar formato a los textos enviados a través del VBA y el mensaje de correo electrónico, sobre todo incluyendo imágenes en el cuerpo del mensaje y/o como firma. Si bien la respuesta inmediata, y que se puede también encontrar en diversas páginas de internet, es usar la propiedad “HTMLBody” y aplicar algo de HTML (Enlace), aunque a muchas personas les ocurre de manera recurrente que la imagen puede hasta llegar como archivo adjunto, pero no se ve en el cuerpo del mensaje o se ve como un marco vacío (no he encontrado personas que les ocurra si se usa en el cuerpo del mensaje una imagen que ya está guardada en alguna url de internet), sobre todo cuando envían a Gmail o Hotmail y más con las nuevas versiones de Office, Windows y los nuevos niveles de seguridad de los servidores.
Buscando, leyendo, indagando, etc., hace un tiempo encontré una solución al dilema mencionado, usando algunas propiedades del objeto Outlook y accediendo a propiedades de la interfaz de programación de aplicaciones de mensajería del servidor a través de los conocidos Schema de Microsoft, lo que hoy compartiré con todos/as.
Comenzaremos declarando cinco variables que son las que vamos a usar; la primera estoy seguro que ya es conocida por ustedes.
Dim outlookApp As Outlook.Application
Luego las siguientes, que dejaré comentadas para que sepan a que nos ayuda cada una:
‘Objeto mensaje de correo
Dim mCorreo As MailItem
‘Colección de objetos Attachment
Dim colecAttach As Outlook.Attachments
‘Objeto Attachment, que representa lo que vamos a adjuntar
Dim objAttach As Outlook.Attachment
‘Permite crear, obtener, establecer y eliminar propiedades en el objeto Outlook
Dim proOutlook As Outlook.PropertyAccessor
Dim Ruta$, nImagen$
Ahora, vamos a declarar una constante que es equivalente a una de las propiedades canónicas PidTagAttachContentId. Esta contiene el encabezado de identificación de un archivo adjunto de mensaje de extensiones multipropósito de correo de Internet. Vamos a darle el valor de un Schema de Microsoft (Data and Story Library – DASL).
Const PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
Luego daremos valores a las variables:
'Creamos el objeto Outlook
Set outlookApp = CreateObject("Outlook.Application")
'Creamos el mensaje
Set mCorreo = outlookApp.CreateItem(olMailItem)
'Creamos el adjunto en el mensaje
Set colecAttach = mCorreo.Attachments
'Adjuntamos el archivo/Imagen
Set objAttach = colecAttach.Add("C:\Users\eavj6\Pictures\pez.jpg")
'Indicamos que haremos uso de una propiedad del adjunto
Set proOutlook = objAttach.PropertyAccessor
Ruta = "C:\Users\eavj6\Pictures\"
nImagen = "pez.jpg"
Lo que toca ahora es usar el método SetProperty para el nombre del Schema y el valor que nos interesa..
proOutlook.SetProperty PR_ATTACH_CONTENT_ID, "pez.jpg"
Lo que sigue debería entenderse si leyeron mis artículos anteriores jejeje.
With mCorreo
.Close olSave
.HTMLBody = "<BODY><IMG src=""cid:pez.jpg""> </BODY>" ‘aquí insertamos la imagen adjunta en el cuerpo del mensaje
.Save
.To = "uncorreo@gmail.com"
.Subject = "Prueba"
.Send
End With
Todo junto podría quedar del siguiente modo:
Option Explicit
'Todo Sobre Excel
'Abraham Valencia
'https://abrahamexcel.blogspot.com/
'https://www.facebook.com/TodosobreExcelAV/
'https://twitter.com/Todosobre_Excel
'https://www.youtube.com/channel/UCxEe3aA5uGrtYDdboBT_ptg
'Lima, Perú
'Enero del 2022
Sub ImagenenCuerpo()
Dim outlookApp As Outlook.Application
'Objeto mensaje de correo
Dim mCorreo As MailItem
'Colección de objetos Attachment
Dim colecAttach As Outlook.Attachments
'Objeto Attachment, que representa lo que vamos a adjuntar
Dim objAttach As Outlook.Attachment
'Permite crear, obtener, establecer y eliminar propiedades en el objeto Outlook
Dim proOutlook As Outlook.PropertyAccessor
Dim Ruta$, nImagen$
Const PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
'Creamos el objeto Outlook
Set outlookApp = CreateObject("Outlook.Application")
'Creamos el mensaje
Set mCorreo = outlookApp.CreateItem(olMailItem)
'Creamos el adjunto en el mensaje
Set colecAttach = mCorreo.Attachments
'Adjuntamos el archivo/Imagen
Set objAttach = colecAttach.Add("C:\Users\eavj6\Pictures\pez.jpg")
'Indicamos que haremos uso de una propiedad del adjunto
Set proOutlook = objAttach.PropertyAccessor
Ruta = "C:\Users\eavj6\Pictures\"
nImagen = "pez.jpg"
proOutlook.SetProperty PR_ATTACH_CONTENT_ID, "pez.jpg"
With mCorreo
.Close olSave
.HTMLBody = "<BODY><IMG src=""cid:pez.jpg""> </BODY>" 'aquí insertamos la imagen adjunta en el cuerpo del mensaje
.Save
.To = "uncorreo@gmail.com@gmail.com"
.Subject = "Prueba"
.Send
End With
MsgBox "Mensaje enviado", vbOKOnly, "Todo Sobre Excel"
End Subb
Y listo, eso es todo por hoy. Espero les sea útil. ¡Hasta la próxima!
Abraham Valencia
Lima, Perú
jueves, 30 de agosto de 2018
Microsoft Outlook desde Excel (IV): Enviar hojas y el libro activo por correo
En esta ocasión seguiremos trabajando con Microsoft Outllok pero ahora lo que veremos es como enviar hojas de un libro o incluso el propio libro como archivo adjunto del mensaje de correo. Voy a suponer que ya leyeron este artículo: Enlace, así que solo diré que para enviar el libro de Excel que es el activo en ese momento, bastará agregar una línea para adjuntarlo, además de lo habitual en estos casos. Con dicha línea lo que haremos es usar la propiedad “FullName”, que devuelve el nombre del libro incluyendo la ruta de su ubicación. De ese modo en el correo se adjuntará el archivo (siempre y cuando se haya guardado). Entonces, prueben esto:
Sub EnviarMensajeOutlook()
Dim OutlookApp As Outlook.Application
Dim objItem As MailItem
Set OutlookApp = CreateObject("Outlook.Application")
Set objItem = OutlookApp.CreateItem(olMailItem)
With objItem
.To = "abraham.valencia@gmail.com" 'Para
.Subject = "Adjuntando archivo" 'Asunto
.Body = "Estamos adjuntando un archivo" 'Cuerpo
.Attachments.Add ActiveWorkbook.FullName
Application.Wait (Now + TimeValue("00:00:03")) 'Tiempo para adjuntar
.Send 'Enviar
End With
Set OutlookApp = Nothing
Set objItem = Nothing
End Sub
Quizá no sea necesario enviar el libro completo sino solo la hoja activa. De ser así, guardaremos la hoja activa como archivo, lo adjuntaremos y lo eliminaremos de inmediato, en el supuesto de que no lo necesitamos posterior al envío:
Sub EnviarMensajeOutlook()
Dim OutlookApp As Outlook.Application
Dim objItem As MailItem
Set OutlookApp = CreateObject("Outlook.Application")
Set objItem = OutlookApp.CreateItem(olMailItem)
ActiveSheet.Copy
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "\Temporal.xlsx"
ActiveWorkbook.Close
With objItem
.To = "abraham.valencia@gmail.com" 'Para
.Subject = "Adjuntando archivo" 'Asunto
.Body = "Estamos adjuntando un archivo" 'Cuerpo
.Attachments.Add ThisWorkbook.Path & "\Temporal.xlsx"
Application.Wait (Now + TimeValue("00:00:03")) 'Tiempo para adjuntar
.Send 'Enviar
End With
Kill ThisWorkbook.Path & "\Temporal.xlsx"
Set OutlookApp = Nothing
Set objItem = Nothing
End Sub
De no desear que sea la hoja activa la que se envíe, basta indicar, en la línea respectiva, que hoja queremos copiar:
Sheets(“Hoja45”).Copy
O incluso puede ser un archivo con solo algunas de las hojas del libro:
Sheets(Array("Hoja1", "Hoja4")).Copy
En el Array pueden ir más hojas, no solo dos, por si acaso. Y eso es todo por hoy. Nos "vemos".
Abraham Valencia
sábado, 30 de junio de 2018
Microsoft Outlook desde Excel (III): Alertas a través del correo electrónico
Como ya he comentado en otros artículos, en los foros/comunidades de Excel entre las preguntas más frecuentes están las relacionadas a cómo enviar mensajes de correo electrónico a través de Macros de Excel. Muchas de dichas preguntas incluso tienen carácter más puntual y no es raro que las personas pregunten por “alertas” automáticas cuando, por ejemplo, se cumplen ciertas fechas que se consideran límites. En esta ocasión vamos a dar algunos consejos para esos casos y usando Microsoft Outlook.
Primero, por si acaso, recordemos como enviar mensajes a través de Outlook: Enlace_1, luego también recordemos como enviar mensajes masivos: Enlace_2, algo que nos será útil en esta ocasión. Ahora vamos a suponer que tenemos los siguientes datos:
Lo que vamos a hacer que la macro se active a través de evento “Open” del libro, por lo que pondremos lo siguiente en el módulo del libro (que lleva por defecto el nombre “ThisWorkBook”):
Private Sub Workbook_Open()
Call EnviarAlertas
End Sub
Entonces, dicho todo eso, nuestra macro debería quedar así:
Sub EnviarAlertas()
Dim OutlookApp As Outlook.Application
Dim objItem As MailItem
Dim UltimaFila As Long, x As Long
Dim FechaV As Date
Set OutlookApp = CreateObject("Outlook.Application")
Let UltimaFila = Cells(Rows.Count, 1).End(xlUp).Row
For x = 2 To UltimaFila
Let FechaV = Range("D" & x).Value
If FechaV < Date And Range("E" & x).Value = "" Then
Set objItem = OutlookApp.CreateItem(olMailItem)
With objItem
.To = Range("B" & x).Value
.cc = "tucorreo@correo.com"
.Subject = "Deuda vencida"
.Body = "Estimado/a señor/a " & Range("A" & x) & " su cuota de " & FormatCurrency(Range("C" & x).Value) & " venció el día " & Range("D" & x).Value
.Send
End With
Set objItem = Nothing
Range("E" & x).Value = "Sí"
End If
Next x
Set OutlookApp = Nothing
MsgBox "Cuentas revisadas"
End Sub
No olvides activar la referencia a "Microsoft Outlook 15.0 Object Library" en el editor de VBA (en donde el 15.0 puede variar dependiendo de tu versión de Excel).
Y listo, eso es todo en esta ocasión, solo adáptalo a tus necesidades. Hasta la próxima.
Abraham Valencia
jueves, 28 de junio de 2018
Microsoft Outlook desde Excel (II): Enviar mensajes masivos
Entre las preguntas más seguidas que se encuentra en los foros de Excel están aquellas relacionadas al envío de mensajes de correo electrónico a través de macros. Hay mucha información en internet al respecto, tanto usando Microsoft Outlook como usando la librería “Collaboration Data Objects” (CDO). En esta ocasión vamos a centrarnos en usar Microsoft Outlook.
Si bien, como ya mencioné, hay mucha información respecto al envío de mensajes, no necesariamente es tan fácil encontrar cosas específicas como el realizar envíos masivos y además adjuntando algún archivo y precisamente eso es lo que mostraremos como hacer.
Lo primero es que, por si acaso, den una leidita a esto: Enlace. Ahora, vamos a suponer que tenemos los datos, incluyendo el correo electrónico, de aquellas personas a las que queremos enviar el mensaje. Los datos para el ejemplo tendrán: Nombre, correo, fecha (de un supuesto reporte), ruta (del supuesto archivo/reporte pdf).
Sabemos entonces en que columna está cada tipo dato. Vamos a suponer también que las filas de datos pueden ir incrementándose, por lo que será necesario averiguar la última fila de manera automática para lo que usaremos la variable “UltimaFila”. Como son varios registros usaremos un bucle del tipo “For – Next” que comience a recorrer todo desde la fila 2 ya que la 1 es la de los encabezados.
Como ya expliqué en otro artículo, cuando se usa el objeto "Outlook", y justamente se nota más cuando se hacen envíos masivos, lo que ocurre es que se van colocando los mensajes en la "Bandeja de salida" así que es recomendable que se tenga el Microsoft Outlook configurado para el envío automático cuando se abre/cierra para que el proceso continúe cuando se use otra vez dicho programa ya que probablemente la macro no termine de enviar los mensajes. Igual vamos a usar “Application.Wait” para que haga una pausa de 10 segundos a la macro y esperar que sea tiempo suficiente para que adjunten los archivos por completo y se envíe el mensaje antes de que siga el bucle (que irá acumulando en la “fila” de la bandeja de salida del Outlook).
Sub EnviarMensajeOutlook()
Dim OutlookApp As Outlook.Application
Dim objItem As MailItem
Dim UltimaFila As Integer, x As Integer
Set OutlookApp = CreateObject("Outlook.Application")
Let UltimaFila = Cells(Rows.Count, 2).End(xlUp).Row
For x = 2 To UltimaFila
Set objItem = OutlookApp.CreateItem(olMailItem)
With objItem
.To = Range("B" & x).Value
.Subject = "Reporte de compras"
.Body = "Estimado/a señor/a " & Range("A" & x) & " le enviamos el repote del día " & Range("C" & x).Value
.Attachments.Add Range("D" & x).Value
Application.Wait (Now + TimeValue("00:00:10"))
.Send
End With
Set objItem = Nothing
Next x
Set OutlookApp = Nothing
MsgBox "Todo enviado"
End Sub
No olvides activar la referencia a "Microsoft Outlook 15.0 Object Library" en el editor de VBA (en donde el 15.0 puede variar dependiendo de tu versión de Excel).
domingo, 4 de febrero de 2018
Microsoft Outlook desde Excel (I)
Muchas veces deseamos que nuestros trabajos en Excel, o en otros programas de Office incluso, se puedan enviar a través de nuestro correo electrónico. Podríamos decir que si tenemos dicho correo configurado en nuestro Microsoft Outlook no será muy difícil lograrlo.
A través de VBA podemos manejar desde Excel nuestro Microsoft Outlook como un objeto y así enviar mensajes adjuntando incluso archivos o nuestra firma digital, si es que la tenemos.
Lo primero que recomiendo hacer es activar la referencia respectiva en el editor de VBA:
En mi caso dice 15.0 por la versión de Office que tengo en la respectiva PC pero se debe activar la que a cada uno le corresponda.
Para continuar, lo que vamos a hacer ahora es crear un objeto “Outlook” y también usaremos el método “CreateItem” con el parámetro del tipo “olMailItem” que creará un nuevo mensaje (objeto “MailItem”):
Dim OutlookApp As Outlook.Application
Dim objItem As MailItem
Set OutlookApp = CreateObject("Outlook.Application")
Set objItem = OutlookApp.CreateItem(olMailItem)
Tal y como cuando enviamos un mensaje desde nuestro correo o desde el propio Microsfot Outlook, el objeto creado tiene propiedades que representan los campos “Para”, “Asunto”, “Cuerpo”, etc:
With objItem
.To = "destinatario@ejemplo.com" 'Para
.CC = "segundodestinatario@ejemplo.com" 'Con copia
.Subject = "Prueba" 'Asunto
.Body = "Este es un mensaje de prueba" 'Cuerpo
End With
Lo único que faltaría es que usemos el método “Send” para enviar el mensaje:
.Send
Toda nuestra macro junta podría quedar así:
Sub EnviarMensajeOutlook() Dim OutlookApp As Outlook.Application Dim objItem As MailItem
Set OutlookApp = CreateObject("Outlook.Application") Set objItem = OutlookApp.CreateItem(olMailItem)
With objItem .To = "destinatario@ejemplo.com" 'Para .CC = "segundodestinatario@ejemplo.com" 'Con copia .Subject = "Prueba" 'Asunto .Body = "Este es un mensaje de prueba" 'Cuerpo .Send End With Set OutlookApp = Nothing Set objItem = Nothing End Sub
Si deseamos poder ir cambiando el correo de destino o el texto del cuerpo del mensaje o etc., sin tener que modificar la macro, podemos colocar los datos en celdas o variables:
With objItem
.To = Range("A1").Value
.CC = Range("A2").Value
.Subject = Range("A3").Value
.Body = Range("A4").Value
.Send
End With
En este momento ya se deben de haber dado cuenta (o ya sabían) que el cuerpo del mensaje se envía sin formato y quizá lo que queremos es más bien que dicho mensaje tenga formato como ya estamos, casi todos, acostumbrados hoy en día cuando usamos el correo electronico. Para lograr eso ya no debemos usar la propiedad “Body” sino que ahora usaremos la propiedad “HTMLBody” pero tendremos que aplicar algo de “HTML” en nuestro VBA:
.HTMLBody = "<html>" & _
"<body><font color=""#FF0000"" size=""6"" face=""Comic Sans MS, cursive""><strong>Hola mi querido y estimado amigo</strong></font>" & _
"</body></html>"
Si lo que queremos, además, es adjuntar algún archivo a nuestro mensaje, debemos usar la propiedad “Attachments” y su método “Add”. Podemos agregar más de un archivo del siguiente modo:
.Attachments.Add "D:\Miarchivouno.xlsm"
.Attachments.Add "D:\MiArchivoNuevo.xlsx"
Es bueno recordar que también podemos usar un bucle y/o variables para agregar más archivos.
Siguiendo con los adjuntos, probablemente tengamos nuestra firma en formato “JPG” y queremos incluirla en el cuerpo del mensaje; de ser así, lo primero que debemos hacer es adjuntar el archivo:
.Attachments.Add “D:\MiFirma.jpg"
Después incluiremos dicha imagen en el cuerpo del mensaje del siguiente modo y/o similar:
.HTMLBody = "<html>" & _
"<body>" & _
"<p>Aqui tu mensaje</p>" & _
"<br>" & _
"<br>" & _
"<img src='cid:'" & .Attachments.Item(1).Filename & "'' height=100 width=75>" & _
"</body>" & _
"</html>"
Los archivos adjuntos tienen un índice, si se tiene más archivos adjuntos, considerar el índice adecuado. En este caso he usado el uno (1).
Hasta la próxima.
Abraham Valencia
PD: En realidad cuando se usa el objeto "Outlook", y sobre todo se nota cuando se hacen envíos masivos, lo que ocurre es que se van colocando los mensajes en la "Bandeja de salida" así que es recomendable que se tenga el Microsoft Outlook configurado para el envío automático al abrir/cerrar para que el proceso continúe el envío así se cierre el Excel. Igual si se desea que se haga casi al instante el envío desde la macro, se puede añadir un Application.Wait después del "Send" o tener el Outlook abierto.
Extras:
En ocasiones deseamos enviar un rango de nuestra hoja como parte del cuerpo del mensaje, hay algunas alternativas como convertir el rango en imagen y colocarla en el cuerpo del mensaje, similar a lo que se hace con las firmas pero la mejor alternativa que he visto es usar una “Función Definida por el Usuario” (UDF) que convierte el rango en lenguaje “HTML” y permite incluirlo en el cuerpo del mensaje a través de la propiedad “HTMLBody”. EL autor es Ron de Bruin y la UDF podemos encontrarla aquí:
http://www.rondebruin.nl/win/s1/outlook/bmail2.htm
Cuando tenemos más de un correo configurado en el Outlook, recomiendo usar una UDF (Autor: Antoni - Galicia, España) para poder elegir el correo que queremos usar:
https://ayudaexcel.com/foro/topic/32737-elegir-cuenta-de-correo-de-outlook/
De no elegir alguno de los correos con la UDF, se usará el correo configurado como predeterminado.