vba - Ejecute el script por lotes una vez para múltiples correos electrónicos
loops email (1)
Tengo varios correos electrónicos entrando (cada día recibo 3 correos electrónicos para pedidos de 3 categorías). Los correos electrónicos están en el formato:
" EXTRACTO DE ÓRDENES - [Categoría] - [Fecha] ".
Donde [Categoría] puede ser Category 1
, Category 2
o Category 3
. [Fecha] es la fecha en que se envió el correo electrónico en el formato DD / MM / YYYY.
Tengo una configuración de reglas para buscar '' Pedidos '' y luego llamo al código siguiente.
Quiero ejecutar Complete.bat
después de que todos los archivos adjuntos de correo electrónico se hayan guardado y solo deseo llamarlo una vez.
Intenté hacer esto creando otro sub llamado saveAttachtoDisk_CATEGORY1(itm)
que solo se llama cuando encuentra " Categoría 1 " en el asunto. Luego guarda el archivo adjunto pero también busca una categoría 1 en el asunto Y también busca la fecha de ayer.
Quiero una mejor solución que no dependa de la fecha. Una variable global podría funcionar donde establezco que la variable sea 1, luego ejecuto Complete.bat
y luego, en el futuro si variable = 1, no ejecuto Complete.bat
. No estoy seguro de dónde colocar esta variable (¿variable global?) Ya que ambos submódulos parecen ser el lugar equivocado para poner esto y referenciarlo.
Ambos estos dos módulos se guardan en la sección ''Módulos'' de Microsoft Outlook VBA.
Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim SaveFolder As String
SaveFolder = "D:/Orders/"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile SaveFolder & "/" & objAtt.DisplayName
objAtt.Delete
Next
itm.Save
End Sub
Otro módulo:
Public Sub saveAttachtoDisk_CATEGORY1(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim SaveFolder As String
SaveFolder = "D:/Orders/"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile SaveFolder & "/" & objAtt.DisplayName
objAtt.Delete
Next
itm.Save
If InStr(1, itm.Subject, "ORDERS EXTRACT - Category 1 -" & Format(Date, "dd/mm/yyyy")) Then
Shell "D:/Orders/Complete.bat"
End If
End Sub
Suposiciones
- OP recibirá exactamente tres correos electrónicos por día (aunque eso se puede personalizar en el código)
- Los sujetos siempre comenzarán con "EXTRACTO DE PEDIDOS -" y ningún otro correo electrónico comenzará con ese código.
- A OP le gustaría ejecutar Complete.bat una vez por día al recibir el tercer correo electrónico de ORDERS EXTRACT.
- OP aready tiene una regla configurada para ejecutar SaveAttachtoDisk al recibir un correo electrónico ORDERS EXTRACT. Esta regla se puede cambiar para ejecutar CategorySaveAndComplete
- OP está utilizando Outlook 2013 o posterior
Solución propuesta
El siguiente código guardará los archivos adjuntos para cada correo electrónico de extracción de pedidos y luego verificará si se han recibido los tres. Decidí no usar .Find y .FindNext, ya que esos métodos no pueden usar comodines y, por lo tanto, requieren una codificación física de los nombres de las categorías. También elegí no usar .Restrict ya que solo hay tres elementos para los que estamos buscando.
Dicho esto, las soluciones con .Find y .Restrict también serían válidas y funcionarían mejor que las siguientes bajo ciertas condiciones, como un usuario con muchos elementos en su bandeja de entrada.
Tenga en cuenta que el recuento esperado de pedidos, extractos de correos electrónicos, cadenas de materias para hacer coincidir y fechas anteriores para verificar, se puede establecer a través de constantes. Implementé la verificación de fecha previa en caso de que OP quisiera verificar cada día anterior también.
Option Explicit
Public Const C_ExpectedOrderCount As Integer = 3 ''Set number of expected emails for categories
Public Const C_SubjectFormat As String = "ORDERS EXTRACT - *"
Public Const C_PrevDatesToCheck As Integer = 0 ''If the Outlook app may not be open every day, set this to the number of prior days the script should also check.
Public Sub CategorySaveAndComplete(itm As Outlook.MailItem)
''Do not take any action if this is not an ORDERS EXTRACT email.
If itm.Subject Like C_SubjectFormat Then
Dim objAtt As Outlook.Attachment
Dim SaveFolder As String
SaveFolder = "D:/Orders/"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile SaveFolder & "/" & objAtt.DisplayName
objAtt.Delete
Next
itm.Save
''Check all emails in Inbox for ORDERS EXTRACT - * - DATE
Dim Item As Object
Dim objNS As Outlook.NameSpace
Set objNS = GetNamespace("MAPI")
Dim olFolder As Outlook.MAPIFolder
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Dim iLoop As Integer
Dim iCount As Integer
Dim DateCheck As Date
For iLoop = 0 To C_PrevDatesToCheck
''Reset DateCheck and iCount if we are looping through days
DateCheck = DateSerial(Year(Date), Month(Date), Day(Date)) - iLoop
iCount = 0
''Loop through mail items
For Each Item In olFolder.Items
If Item.Class = 43 Then
''This is an email. Check if it matches our criteria.
If Item.Subject Like C_SubjectFormat And CDate(CLng(Item.ReceivedTime)) = DateCheck Then iCount = iCount + 1
End If
Next
''If we have met the expected targets, then run the batch file.
If iCount = C_ExpectedOrderCount Then
''We have exactly the expected number of items. Run the batch file.
Shell "D:/Orders/Complete.bat"
ElseIf iCount > C_ExpectedOrderCount Then
''More items than expected. Check if user is OK with running batch file; if so, run it now.
If MsgBox("More order extracts than expected were received. Expected " & _
C_ExpectedOrderCount & "; received " & iCount & " for " & Format(DateCheck, "mmm d, yy") & _
". Would you like to run the Complete.bat file now?", vbYesNo) = vbYes Then Shell "D:/Orders/Complete.bat"
End If
Next iLoop
End If
End Sub