I count the number of emails in Outlook by Category.
I am getting the output in a MsgBox.
I want the output in Excel.
Example-
Category No of Emails
Material(blue) 42
Vendor(green) 5
Macro used as below
Sub CategoriesEmails()
Dim oFolder As MAPIFolder
Dim oDict As Object
Dim sStartDate As String
Dim sEndDate As String
Dim oItems As Outlook.Items
Dim sStr As String
Dim sMsg As String
On Error Resume Next
Set oFolder = Application.ActiveExplorer.CurrentFolder
Set oDict = CreateObject("Scripting.Dictionary")
sStartDate = Date - 365
sEndDate = Date
Set oItems = oFolder.Items.Restrict("[Received] >= '" & sStartDate & "' And [Received] <= '" & sEndDate & "'")
oItems.SetColumns ("Categories")
For Each aitem In oItems
sStr = aitem.Categories
If Not oDict.Exists(sStr) Then
oDict(sStr) = 0
End If
oDict(sStr) = CLng(oDict(sStr)) + 1
Next aitem
sMsg = ""
For Each aKey In oDict.Keys
sMsg = sMsg & aKey & ": " & oDict(aKey) & vbCrLf
Next
MsgBox sMsg
Set oFolder = Nothing
End Sub
Based on your code, I've updated my code, you can paste all and run it:
Sub CategoriesEmails()
Dim oFolder As MAPIFolder
Dim oDict As Object
Dim sStartDate As String
Dim sEndDate As String
Dim oItems As Outlook.Items
Dim sStr As String
Dim sMsg As String
Dim strFldr As String
Dim OutMail As Object
Dim xlApp As Object
On Error Resume Next
Set oFolder = Application.ActiveExplorer.CurrentFolder
Set oDict = CreateObject("Scripting.Dictionary")
sStartDate = Date - 365
sEndDate = Date
Set oItems = oFolder.Items.Restrict("[Received] >= '" & sStartDate & "' And [Received] <= '" & sEndDate & "'")
oItems.SetColumns ("Categories")
For Each aItem In oItems
sStr = aItem.Categories
If Not oDict.Exists(sStr) Then
oDict(sStr) = 0
End If
oDict(sStr) = CLng(oDict(sStr)) + 1
Next aItem
sMsg = ""
i = 0
strFldr = "D:\"
Set xlApp = CreateObject("Excel.Application")
xlApp.Application.Visible = True
xlApp.Workbooks.Open strFldr & "test.xlsx"
xlApp.Sheets("Sheet1").Select
For Each aKey In oDict.Keys
xlApp.Range("a1").Offset(i, 0).Value = sMsg & aKey
xlApp.Range("B1").Offset(i, 0).Value = oDict(aKey) & vbCrLf
i = i + 1
Next
xlApp.Save
Set oFolder = Nothing
End Sub
You could change the fileUrl, fileName, Excel field as your actual situation.
Related
I search the inbox folder for given subject, sender from column 1 and date.
Based on the result it should populate rows in column 2 with Yes or No. But it populates all rows as No. I'm sure I should see at least one Yes.
The value of variable i is always nothing. Looks like it is a problem with filterstring variable.
Sub searchemailsreceived()
Application.ScreenUpdating = False
ThisWorkbook.Activate
Dim ol As outlook.Application
Dim ns As outlook.Namespace
Dim fol As outlook.Folder
Dim i As Object
Dim mi As outlook.MailItem
Dim filterstring As String
Dim dmi As outlook.MailItem
Dim lstRow As Long
Dim rng As Range
ThisWorkbook.Sheets("Sheet1").Activate
lstRow = Cells(Rows.Count, 2).End(xlUp).Row
Set rng = Range("A2:A" & lstRow)
Set ol = New outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
Set dmi = ol.CreateItem(olMailItem)
For Each cell In rng
filterstring = "#SQL=(""urn:schemas:httpmail:fromemail"" LIKE '%" & Range(cell.Address).Offset(0, 0).Value2 & "%' AND ""urn:schemas:httpmail:subject"" LIKE '%This is my subject%' AND ""urn:schemas:httpmail:datereceived"" >= '4/1/2021 12:00 AM')"
For Each i In fol.Items.Restrict(filterstring)
If i.Class = olMail Then
Range(cell.Address).Offset(0, 1).Value2 = "Yes"
GoTo landhere
End If
Next i
Range(cell.Address).Offset(0, 1).Value2 = "No"
landhere:
Next cell
Set mi = Nothing
Set dmi = Nothing
Set ol = Nothing
Application.ScreenUpdating = False
End Sub
Try the following cleaned function (untested):
Sub SearchEmailsReceived()
Application.ScreenUpdating = False
Dim ol As Outlook.Application: Set ol = New Outlook.Application
Dim fol As Outlook.MAPIFolder: Set fol = ol.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim lstRow As Long: lstRow = ws.Cells(Rows.Count, 2).End(xlUp).Row
Dim rng As Range: Set rng = ws.Range("A2:A" & lstRow)
Dim i As Object, filterstring As String, Cell As Range
Dim dmi As Outlook.MailItem: Set dmi = ol.CreateItem(olMailItem)
For Each Cell In rng
filterstring = "#SQL=urn:schemas:httpmail:fromemail LIKE '%" & Cell.Value2 & "%' AND urn:schemas:httpmail:subject LIKE '%This is my subject%' AND urn:schemas:httpmail:datereceived >= '4/1/2021 12:00 AM'"
Cell.Offset(0, 1) = "No"
For Each i In fol.Items.Restrict(filterstring)
If i.Class = olMail Then Cell.Offset(0, 1) = "Yes"
Next i
Next Cell
Set dmi = Nothing
Set ol = Nothing
Application.ScreenUpdating = False
End Sub
The answer linked by #niton shows the SQL=urn... doesn't contain quote marks so they have been removed. You may want to cut down the filterstring and test whether each additional AND statement causes issues though. Maybe comment out subject and date to test whether it finds any e-mails from the recipients first then work them back in the further requirements once you know the base works ok
the fromemail schema didn't work for me. what worked for me is ""http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & Cell.Value2 & "%'
Thank you for helping.
Demonstration with "urn:schemas:httpmail:fromemail" and "proptag/0x0065001f".
Option Explicit
Sub searchemailsreceived_Demo()
'Application.ScreenUpdating = False
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim folItems As Outlook.Items
Dim folItemsSQL As Outlook.Items
Dim folItems1SQL As Outlook.Items
Dim folItems2SQL As Outlook.Items
Dim folItems3SQL As Outlook.Items
Dim i As Long
Dim filterString1 As String
Dim filterString2 As String
Dim filterString3 As String
Dim filterStringSQL As String
Dim filterString1SQL As String
Dim filterString2SQL As String
Dim filterString3SQL As String
Dim lastRowColA As Long
Dim rng As Range
Dim cell As Object
Dim foundFlag As Boolean
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
lastRowColA = Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("A2:A" & lastRowColA)
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.GetDefaultFolder(olFolderInbox)
Set folItems = fol.Items
Debug.Print "folItems.Count..: " & folItems.Count
For Each cell In rng
'filterString1 = """http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & cell.Value2 & "%'"
' or
' Based on sample data, a filter without wildcards may be preferable.
' Col A = email addresses starting in row 2
Debug.Print
filterString1 = """urn:schemas:httpmail:fromemail"" LIKE '" & cell.Value2 & "'"
Debug.Print "filterString1 ..: " & filterString1
filterString1SQL = "#SQL=(" & filterString1 & ")"
Debug.Print "filterString1SQL: " & filterString1SQL
Set folItems1SQL = folItems.Restrict(filterString1SQL)
Debug.Print "folItems1SQL.Count.: " & folItems1SQL.Count
' Condition 1
foundFlag = False
For i = 1 To folItems1SQL.Count
If folItems1SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems1SQL(i).SenderEmailAddress: " & folItems1SQL(i).SenderEmailAddress
cell.Offset(0, 2).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 2).Value2 = "No"
End If
' Condition 2
Dim strSubject As String
strSubject = "test"
Debug.Print
filterString2 = """urn:schemas:httpmail:subject"" LIKE '%" & strSubject & "%'"
Debug.Print "filterString2 ..: " & filterString2
filterString2SQL = "#SQL=(" & filterString2 & ")"
Debug.Print "filterString2SQL: " & filterString2SQL
Set folItems2SQL = folItems.Restrict(filterString2SQL)
Debug.Print "folItems2SQL.Count.: " & folItems2SQL.Count
foundFlag = False
For i = 1 To folItems2SQL.Count
If folItems2SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems2SQL(i).Subject: " & folItems2SQL(i).Subject
cell.Offset(0, 3).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 3).Value2 = "No"
End If
' Condition 3
Dim strDate As String
strDate = "2021/04/01 12:00 AM"
Debug.Print
filterString3 = """urn:schemas:httpmail:datereceived"" >= '" & strDate & "'"
Debug.Print "filterString3: " & filterString3
filterString3SQL = "#SQL=(" & filterString3 & ")"
Debug.Print "filterString3SQL: " & filterString3SQL
Set folItems3SQL = folItems.Restrict(filterString3SQL)
Debug.Print "folItems3SQL.Count : " & folItems3SQL.Count
foundFlag = False
For i = 1 To folItems3SQL.Count
If folItems3SQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItems3SQL(i).ReceivedTime: " & folItems3SQL(i).ReceivedTime
cell.Offset(0, 4).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 4).Value2 = "No"
End If
' Condition 1 AND Condition 2 AND Condition 3
Debug.Print
Debug.Print filterString1
Debug.Print filterString2
Debug.Print filterString3
filterStringSQL = "#SQL=(" & filterString1 & " AND " & filterString2 & " AND " & filterString3 & ")"
Debug.Print "filterStringSQL: " & filterStringSQL
Set folItemsSQL = folItems.Restrict(filterStringSQL)
Debug.Print "folItemsSQL.Count : " & folItemsSQL.Count
foundFlag = False
For i = 1 To folItemsSQL.Count
If folItemsSQL(i).Class = olMail Then
Debug.Print "i = " & i
Debug.Print " - folItemsSQL(i).SenderEmailAddress: " & folItemsSQL(i).SenderEmailAddress
Debug.Print " - folItemsSQL(i).Subject...........: " & folItemsSQL(i).Subject
Debug.Print " - folItemsSQL(i).ReceivedTime......: " & folItemsSQL(i).ReceivedTime
Debug.Print
cell.Offset(0, 1).Value2 = "Yes"
foundFlag = True
Exit For
End If
Next
If foundFlag = False Then
cell.Offset(0, 1).Value2 = "No"
End If
Next cell
Application.ScreenUpdating = True
End Sub
Actually I tried a smaller and it worked but thank you.
Sub searchemailsreceived()
Application.ScreenUpdating = False
ThisWorkbook.Activate
Dim ol As Outlook.Application: Set ol = New Outlook.Application
Dim ns As Outlook.Namespace: Set ns = ol.GetNamespace("MAPI")
Dim fol As Outlook.Folder: Set fol = ns.GetDefaultFolder(olFolderInbox)
Dim filterstring As String
Dim lstRow As Long: lstRow = Cells(Rows.Count, 2).End(xlUp).Row
Dim rng As Range: Set rng = Range("A2:A" & lstRow)
ThisWorkbook.Sheets("Sheet1").Activate
For Each Cell In rng
filterstring = "#SQL=(""http://schemas.microsoft.com/mapi/proptag/0x0065001f"" CI_STARTSWITH '%" & Cell.Value2 & "%' AND ""urn:schemas:httpmail:subject"" LIKE '%This is a subject%' AND ""urn:schemas:httpmail:datereceived"" >= '1/1/2000 12:00 AM')"
Range(Cell.Address).Offset(0, 2).Value2 = fol.Items.Restrict(filterstring).Count
filterstring = ""
Next Cell
Set ol = Nothing
Application.ScreenUpdating = False
End Sub
I'm attempting to use a fairly standard method for pulling emails from Outlook and then extracting Zip files. The File names and the folder locations are correct. I wonder if PKZip files (our corporate standard for Zip files) requires a special technique? Here's my code so far... It works perfectly up to the point where files are extracted from the Zip files where it fails. (oApp.Namespace(fDest).CopyHere oApp.Namespace(fDest & Fname).Items)
Sub SaveAttachments()
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim i As Object
Dim mi As Outlook.MailItem
Dim at As Outlook.Attachment
Dim Inbox As MAPIFolder
Dim strDate As String
Dim oApp As Object
Dim fDest As String
Dim fZip As String
strDate = InputBox("Enter Date in format dd-Mmm-yyyy", "User Date", Format(Now(), "dd-Mmm-yyyy"))
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.Folders("GCMNamLogs").Folders("Inbox")
fDest = "C:\Users\jb76991\Desktop\0_SWPA 50011 CORP Violations\"
For Each i In fol.Items.Restrict("#SQL=urn:schemas:httpmail:subject LIKE '%" & strDate & "%'")
If i.Class = olMail Then
Set mi = i
For Each at In mi.Attachments
If InStr(at.Filename, ".zip") > 0 Then
If InStr(mi.Subject, "Daily SWPA swpaViolRPT REPORT for DOMAIN:CORP") > 0 Then
'Set oApp = CreateObject("Shell.Application")
FileNameFolder = fDest
Fname = at.Filename
at.SaveAsFile fDest & Fname
Set oApp = CreateObject("Shell.Application")
Debug.Print fDest & Fname
oApp.Namespace(fDest).CopyHere oApp.Namespace(fDest & Fname).Items
Application.Wait (Now + TimeValue("0:00:02"))
End If
If InStr(mi.Subject, "Daily SWPA swpaViolRPT REPORT for DOMAIN:INFRA") > 0 Then
Set oApp = CreateObject("Shell.Application")
FileNameFolder = fDest
Fname = at.Filename
at.SaveAsFile fDest & Fname
Debug.Print fDest & Fname
oApp.Namespace(fDest).CopyHere oApp.Namespace(fDest & Fname).Items
Application.Wait (Now + TimeValue("0:00:01"))
End If
If InStr(mi.Subject, "Daily SWPA swpaSumRPT REPORT for DOMAIN:CORP") > 0 Then
Set oApp = CreateObject("Shell.Application")
FileNameFolder = fDest
Fname = at.Filename
at.SaveAsFile fDest & Fname
Debug.Print fDest & Fname
oApp.Namespace(fDest).CopyHere oApp.Namespace(fDest & Fname).Items
Application.Wait (Now + TimeValue("0:00:01"))
End If
If InStr(mi.Subject, "Daily SWPA swpaSumRPT REPORT for DOMAIN:INFRA") > 0 Then
Set oApp = CreateObject("Shell.Application")
FileNameFolder = fDest
Fname = at.Filename
at.SaveAsFile fDest & Fname
Debug.Print fDest & Fname
oApp.Namespace(fDest).CopyHere oApp.Namespace(fDest & Fname).Items
Application.Wait (Now + TimeValue("0:00:01"))
End If
End If
Next at
End If
Next i
MsgBox ("Done")
End Sub
The string/variant is the fix, but you'd also benefit from reducing the repetition in the code
(untested)
Sub SaveAttachments()
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim i As Object
Dim mi As Outlook.MailItem
Dim at As Outlook.Attachment
Dim Inbox As MAPIFolder
Dim strDate As String
Dim fDest As Variant, FName As Variant, e, arrZips
strDate = InputBox("Enter Date in format dd-Mmm-yyyy", "User Date", Format(Now(), "dd-Mmm-yyyy"))
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.Folders("GCMNamLogs").Folders("Inbox")
arrZips = Array("Daily SWPA swpaViolRPT REPORT for DOMAIN:CORP", _
"Daily SWPA swpaViolRPT REPORT for DOMAIN:INFRA", _
"Daily SWPA swpaSumRPT REPORT for DOMAIN:CORP", _
"Daily SWPA swpaSumRPT REPORT for DOMAIN:INFRA")
fDest = "C:\Users\jb76991\Desktop\0_SWPA 50011 CORP Violations\"
For Each i In fol.items.Restrict("#SQL=urn:schemas:httpmail:subject LIKE '%" & strDate & "%'")
If i.Class = olMail Then
Set mi = i
For Each at In mi.Attachments
FName = at.Filename
If InStr(FName, ".zip") > 0 Then
For Each e In arrZips
If InStr(mi.Subject, e) > 0 Then
at.SaveAsFile fDest & FName
ExtractZip fDest & FName, fDest, 2
Exit For
End If
Next e
End If
Next at
End If
Next i
MsgBox ("Done")
End Sub
Sub ExtractZip(ZipPath, DestFolder, Optional waitsecs As Long = 0)
Debug.Print "Extracting '" & ZipPath & "' to '" & DestFolder & "'"
With CreateObject("Shell.Application")
.Namespace(DestFolder).copyhere .Namespace(ZipPath).items
End With
If waitsecs > 0 Then Application.Wait Now + waitsecs / (24 * 60 * 60)
End Sub
I wrote the below code and it works perfect when I want to extract the outlook email items in my excel sheet, but it does not work when I want to get the emails that were received on a certain date:
Sub getMail()
Dim i As Long
Dim arrHeader As Variant
Dim olNS As Namespace
Dim olInboxFolder As MAPIFolder
Dim olItems As Items
Dim olItem As Variant
Set olNS = GetNamespace("MAPI")
Set olInboxFolder = olNS.PickFolder 'Pick folder
Set olItems = olInboxFolder.Items
arrHeader = Array("Date Created", "SenderEmailAddress", "Subject", "Body")
ThisWorkbook.Worksheets("Output").Range("A1").Resize(1, UBound(arrHeader) + 1).Value = arrHeader
ActiveSheet.Range("E2", Range("E2").End(xlDown)).NumberFormat = "mm/dd/yyyy h:mm AM/PM"
i = 1
sFilter = InputBox("Enter Date")
FilterString = "[ReceivedTime] > sFilter "
For Each olItem In olItems.Restrict(FilterString)
' MailItem
If olItem.Class = olMail Then
Set mi = olItem
Debug.Print mi.ReceivedTime
ThisWorkbook.Worksheets("Output").Cells(i + 1, "A").Value = olItems(i).ReceivedTime
If olItems(i).SenderEmailType = "SMTP" Then
ThisWorkbook.Worksheets("Output").Cells(i + 1, "B").Value = olItems(i).SenderEmailAddress
ElseIf olItems(i).SenderEmailType = "EX" Then
ThisWorkbook.Worksheets("Output").Cells(i + 1, "B").Value = olItems(i).Sender.GetExchangeUser.PrimarySmtpAddress
End If
ThisWorkbook.Worksheets("Output").Cells(i + 1, "C").Value = olItems(i).Subject
ThisWorkbook.Worksheets("Output").Cells(i + 1, "D").Value = olItems(i).Body
i = i + 1
On Error Resume Next
' ReportItem
ElseIf olItem.Class = olReport Then
ThisWorkbook.Worksheets("Output").Cells(i + 1, "A").Value = olItems(i).CreationTime
ThisWorkbook.Worksheets("Output").Cells(i + 1, "B").Value = _
olItems(i).PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x0E04001E") 'PR_DISPLAY_TO
ThisWorkbook.Worksheets("Output").Cells(i + 1, "C").Value = olItems(i).Subject
i = i + 1
End If
Next olItem
ThisWorkbook.Worksheets("Output").Cells.EntireColumn.AutoFit
MsgBox "Export complete.", vbInformation
Set olItems = Nothing
Set olInboxFolder = Nothing
Set olNS = Nothing
End Sub
For example I want to get all the emails that were sent starting with 08/16/2020 date, Or get all the emails on a certain date range.
Private Sub getMail_InputBoxDate()
Dim olNS As namespace
Dim olFilterFolder As Folder
Dim olItems As Items
Dim olItem As Object
Dim mi As mailItem
Dim filterString As String
Dim sDate1 As String
Dim filterString1 As String
Dim sDate2 As String
Dim filterString2 As String
Dim olItemsRes As Items
Set olNS = GetNamespace("MAPI")
Set olFilterFolder = olNS.PickFolder 'Pick folder
Set olItems = olFilterFolder.Items
olItems.Sort "[ReceivedTime]", True
Debug.Print vbCr & "olItems.Count: " & olItems.Count
sDate1 = InputBox("Enter Start Date", , "2020-09-14")
'Debug.Print sDate1
sDate1 = Format(sDate1 & " 00:00 AM", "DDDDD HH:NN")
Debug.Print vbCr & "sDate1: " & sDate1
' Single quotes around variable.
filterString1 = "[ReceivedTime] >= '" & sDate1 & "'"
Debug.Print " filterString1: " & filterString1
Set olItemsRes = olItems.Restrict(filterString1)
Debug.Print " olItemsRes.Count: " & olItemsRes.Count
sDate2 = InputBox("Enter date, one day after desired range.", , "2020-09-15")
'Debug.Print sDate2
sDate2 = Format(sDate2 & " 00:00 AM", "DDDDD HH:NN")
Debug.Print vbCr & "sDate2: " & sDate2
' With single quotes around variable.
filterString2 = "[ReceivedTime] < '" & sDate2 & "'"
Debug.Print " filterString2: " & filterString2
' Option 1 - Restrict the previously restricted items
Set olItemsRes = olItemsRes.Restrict(filterString2)
Debug.Print " olItemsRes.Count: " & olItemsRes.Count
Debug.Print
For Each olItem In olItemsRes
' MailItem
If olItem.Class = olMail Then
Set mi = olItem
Debug.Print mi.ReceivedTime & " " & mi.Subject
End If
Next olItem
' Option 2 - Combine two working filters into one
filterString = filterString1 & " AND " & filterString2
Debug.Print vbCr & "filterString combined: " & filterString
' Restrict the original items once
Set olItemsRes = olItems.Restrict(filterString)
Debug.Print "olItemsRes.Count: " & olItemsRes.Count
Debug.Print
For Each olItem In olItemsRes
' MailItem
If olItem.Class = olMail Then
Set mi = olItem
Debug.Print mi.ReceivedTime & " " & mi.Subject
End If
Next olItem
Debug.Print vbCr & "Done."
End Sub
This is Restrict Outlook Items by Date but adds time to the user-input date.
I am working on a "mail bot", where I will receive a filled template, and populate and save an Excel file with that information.
I can fill the first file and quit the Excel file.
When a second mail arrives, I get
'1004 - application-defined or object-defined error'
Why am I getting the error on the second and beyond ones?
I am running the code when a new mail arrives
Option Explicit
Private WithEvents inboxItems As Outlook.Items
Private Sub Application_Startup()
Dim outlookApp As Outlook.Application
Dim objectNS As Outlook.NameSpace
Set outlookApp = Outlook.Application
Set objectNS = outlookApp.GetNamespace("MAPI")
Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items
End Sub
The main sub
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim MessageInfo
Dim Result
Dim splitter() As String
Dim splitter2() As String
Dim str As Variant
Dim LoopCali As Integer
Dim xlApp As Object
Dim sourceWB As Workbook
Dim sourceWS As Worksheet
Dim strFile As String
If TypeName(Item) = "MailItem" Then
If InStr(Item.Subject, "BOT") > 0 Then
splitter = Split(Item.Body, vbCrLf)
splitter2 = Split(splitter(40), "-")
Set xlApp = CreateObject("Excel.Application")
strFile = "C:\Users\e1257539\Desktop\SMOBOT\SMO_TOOL_BOT.xlsm"
With xlApp
.Visible = TRUE
.EnableEvents = FALSE
End With
Set sourceWB = Workbooks.Open(strFile, , False, , , , , , , True)
sourceWB.Activate
With xlApp
.Worksheets("HEADER").Range("D6").Value2 = splitter(22)
.Worksheets("HEADER").Range("D8").Value2 = splitter(12)
.Worksheets("HEADER").Range("F4").Value2 = "AINT"
.Worksheets("HEADER").Range("F3").Value2 = "EXW"
.Worksheets("HEADER").Range("C2").Value2 = Worksheets("QuoteSTG").Range("A" + CStr(Worksheets("QuoteSTG").Range("B1").Value2)).Value2
.Worksheets("QuoteSTG").Range("A" + CStr(Worksheets("QuoteSTG").Range("B1").Value2)).Value2 = ""
End With
If splitter(2) = "Calibração" Then
Result = MsgBox(splitter(2), vbOKOnly, i)
LoopCali = splitter(26)
End If
If splitter(2) = "Trainamento" Then
End If
End If
MessageInfo = "" & _
"Sender : " & Item.SenderEmailAddress & vbCrLf & _
"Sent : " & Item.SentOn & vbCrLf & _
"Received : " & Item.ReceivedTime & vbCrLf & _
"Subject : " & Item.Subject & vbCrLf & _
"Size : " & Item.Size & vbCrLf & _
"Message Body : " & vbCrLf & Item.Body
End If
xlApp.Quit
Set xlApp = Nothing
Set sourceWB = Nothing
Set sourceWS = Nothing
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
xlApp.Quit
Set xlApp = Nothing
Set sourceWB = Nothing
Set sourceWS = Nothing
'Resume ExitNewItem
End Sub
As checked on the link sent by the user: Niton
Excel application not closing from Outlook VBA function
The main issue was that the excel file wasn't closing.
After some changes this was the final result:
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim MessageInfo
Dim Result
Dim splitter() As String
Dim splitter2() As String
Dim str As Variant
Dim LoopCali As Integer
Dim i As Integer
Dim xlApp As Object
Dim sourceWB As Object
Dim Header, QuoteSTG, AINT As Object
Dim strFile As String
Dim file_name As String
'
i = 0
'
If TypeName(Item) = "MailItem" Then
If InStr(Item.Subject, "BOT") > 0 Then
splitter = Split(Item.Body, vbCrLf)
splitter2 = Split(splitter(40), "-")
Result = MsgBox(splitter2(0), vbOKOnly, i)
Result = MsgBox(splitter2(1), vbOKOnly, i)
'
Set xlApp = CreateObject("Excel.Application")
strFile = "C:\Users\e1257539\Desktop\SMOBOT\SMO_TOOL_BOT.xlsm"
With xlApp
.Visible = True
.EnableEvents = False
End With
Set sourceWB = Workbooks.Open(strFile)
sourceWB.Activate
Set Header = sourceWB.Sheets(4) 'header
Set QuoteSTG = sourceWB.Sheets(13) 'quotestg
Set AINT = sourceWB.Sheets(7) 'aint
If splitter(2) = "Calibração" Then
LoopCali = splitter(26)
file_name = QuoteSTG.Range("A" + CStr(QuoteSTG.Range("B1").Value2)).Value2
QuoteSTG.Range("A" + CStr(QuoteSTG.Range("B1").Value2)).Value2 = ""
sourceWB.Save
Header.Range("D6").Value2 = splitter(22)
Header.Range("D8").Value2 = splitter(12)
Header.Range("F4").Value2 = "AINT"
Header.Range("F3").Value2 = "EXW"
Header.Range("C2").Value2 = file_name
End If
If splitter(2) = "Treinamento" Then
End If
End If
End If
MkDir "C:\Users\e1257539\Desktop\SMOBOT\" + file_name
sourceWB.SaveAs FileName:="C:\Users\e1257539\Desktop\SMOBOT\" + file_name + "\" + file_name
sourceWB.Close
xlApp.Quit
Set xlApp = Nothing
Set sourceWB = Nothing
Set AINT = Nothing
Set QuoteSTG = Nothing
Set Header = Nothing
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
End Sub
I'm using a script that opens an email and downloads its attachment. Right now I can either choose to download the most recent attachment on the most recent email:
Sub CTEmailAttDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim oOlResults As Object
Dim x As Long
Dim NewFileName As String
NewFileName = "Daily Tracker " & Format(Now, "dd-MM-yyyy")
'You can only have a single instance of Outlook, so if it's already open
'this will be the same as GetObject, otherwise it will open Outlook.
Set oOlAp = CreateObject("Outlook.Application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'No point searching the whole Inbox - just since yesterday.
Set oOlResults = oOlInb.Items.Restrict("[ReceivedTime]>'" & Format(Date - 1, "DDDDD HH:NN") & "'")
'If you have more than a single attachment they'll all overwrite each other.
'x will update the filename.
x = 1
For Each oOlItm In oOlResults
If oOlItm.Attachments.Count > 0 Then
For Each oOlAtch In oOlItm.Attachments
If GetExt(oOlAtch.FileName) = "xlsx" Then
oOlAtch.SaveAsFile AttachmentPath & "\" & NewFileName & ".xlsx"
End If
x = x + 1
Next oOlAtch
End If
Next oOlItm
End Sub
'----------------------------------------------------------------------
' GetExt
'
' Returns the extension of a file.
'----------------------------------------------------------------------
Public Function GetExt(FileName As String) As String
Dim mFSO As Object
Set mFSO = CreateObject("Scripting.FileSystemObject")
GetExt = mFSO.GetExtensionName(FileName)
End Function
By using '[Subject] =' I can download it by subject.
My question is, how can I put those two filters together so I can filter by Subject and ReceivedTime?
I tried binding them together with ,, &, + and so far I haven't been successful.
#SQL=(Subject LIKE '%blah%') AND (ReceivedTime > '01/02/2015')
It is a struggle to get the syntax for even one restrict. As indicated in the comment by Scott Holtzman, if you know each filter separately, you can filter twice.
Option Explicit
Sub CTEmailAttDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim oOlResults As Object
Dim oOlSubjectResults As Object
Dim strFilter As String
Dim i As Long
Dim x As Long
Dim NewFileName As String
NewFileName = "Daily Tracker " & format(Now, "dd-MM-yyyy")
'You can only have a single instance of Outlook, so if it's already open
'this will be the same as GetObject, otherwise it will open Outlook.
Set oOlAp = CreateObject("Outlook.Application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'No point searching the whole Inbox - just since yesterday.
Set oOlResults = oOlInb.Items.Restrict("[ReceivedTime]>'" & format(Date - 1, "DDDDD HH:NN") & "'")
strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34) & " like '%test%'"
Set oOlSubjectResults = oOlResults.Restrict(strFilter)
If oOlSubjectResults.count = 0 Then
Debug.Print "No emails found with applicable subject"
Else
'If you have more than a single attachment they'll all overwrite each other.
'x will update the filename.
x = 1
For i = 1 To oOlSubjectResults.count
Set oOlItm = oOlSubjectResults(i)
If oOlItm.Attachments.count > 0 Then
Debug.Print oOlItm.Subject
For Each oOlAtch In oOlItm.Attachments
Debug.Print oOlAtch.DisplayName
If GetExt(oOlAtch.FileName) = "xlsx" Then
oOlAtch.SaveAsFile AttachmentPath & "\" & NewFileName & ".xlsx"
End If
x = x + 1
Next oOlAtch
End If
Next i
End If
ExitRoutine:
Set oOlAp = Nothing
Set oOlns = Nothing
Set oOlInb = Nothing
Set oOlResults = Nothing
Set oOlSubjectResults = Nothing
End Sub