I am writing a simply script to delete all calendar objects within the Deleted Items folder. such calendar objects include meeting confirmations, declines...etc.
At present I have below, does not delete anything, even though checking the deleted items folder has many calendar confirmations, declines..etc:
Dim oDeletedItems As Outlook.Folder
Dim obj As Outlook.MailItem
Dim i As Integer
'Obtain a reference to deleted items folder
Set oDeletedItems = Application.Session.GetDefaultFolder(olFolderDeletedItems)
For i = oDeletedItems.Items.Count - 1 To 1 Step -1
' Delete all appointment items
If oDeletedItems.Items(i).Class = AppointmentItem Then
'Debug.Print obj.Subject
oDeletedItems.Items.Item(i).Delete
End If
Next
Firstly, do not use multiple dot notation (oDeletedItems.Items(i).Class) - cache the Items collection before entering the loop.
Secondly, confirmations, declines, etc. are meeting items, not appointments.
Thirdly, Class property returns one of the OlObjectClass enum values. AppointmentItem is an item type (interface).
You need to use 53 (olMeetingRequest) or 26 (olAppointment).
Fourthly, start the loop from Items.Count, not Items.Count-1.
set items = oDeletedItems.Items
For i = items.Count To 1 Step -1
' Delete all appointment items
set item = items.Item(I)
itemClass = item.Class
If (itemClass= olAppointment) or (itemClass= olMeetingRequest) Then
'Debug.Print obj.Subject
item.Delete
End If
Next
Related
This question already has answers here:
How can I compare all the titles of all RSS feeds and delete duplicates?
(2 answers)
Closed 5 years ago.
I'm wondering if there is a way to compare ALL TITLES in ALL RSS FEEDS and delete the duplicates.
I read through a lot of RSS Feeds, and it's obvious that a lot of people cross-post to several forums, and then I end up seeing the same RSS Feed multiple times.
I really just want to see each one one single time. Is there a way to list all feeds, and delete duplicates, if I actually have duplicates in my entire MS Outlook RSS Feed list?
Here's 0m3r's script, modified slightly.
Option Explicit
Public Sub Example()
Dim olNs As Outlook.NameSpace
Dim RSS_Folder As Outlook.MAPIFolder
Dim Item As Object
Dim Items As Items
Dim DupItem As Object
Dim i As Long
Dim j As Long
For j = 1 To 21
Set olNs = Application.GetNamespace("MAPI")
Set RSS_Folder = olNs.GetDefaultFolder(olFolderRssFeeds).Folders(j)
Set DupItem = CreateObject("Scripting.Dictionary")
Set Items = RSS_Folder.Items
For i = Items.Count To 1 Step -1
DoEvents
If TypeOf Items(i) Is PostItem Then
Set Item = Items(i)
If DupItem.Exists(Item.Subject) Then
Debug.Print Item.Subject ' Print on Immediate Window
Debug.Print TypeName(Item) ' Print on Immediate Window
Item.Delete
Else
'Debug.Print Item.Subject
DupItem.Add Item.Subject, 0
End If
End If
Next i
Debug.Print RSS_Folder
Next j
Set olNs = Nothing
Set RSS_Folder = Nothing
Set Item = Nothing
Set Items = Nothing
Set DupItem = Nothing
End Sub
Iterating over all items in the folder is not really a good idea.
For Each myItem In subFolder.Items
If InStr(myItem.Subject, "[on hold]") > 0 Then
You can use the Find/FindNext or Restrict methods of the Items class to find all items that correspond to your conditions. Read more about them in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Also you may find the AdvancedSearch method of the Application class helpful.
The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
Finally, you can stop the search process at any moment using the Stop method of the Search class.
Read more about that in the Advanced search in Outlook programmatically: C#, VB.NET article.
Work with Dictionary Object to compare Items.Subject in your olFolderRssFeeds
Dictionary in VBA is a collection-object:
you can store all kinds of things in it: numbers, texts, dates, arrays, ranges, variables and objects, Every item in a Dictionary gets its own unique key and
With that key you can get direct access to the item (reading/writing).
Here is quick Example code
Option Explicit
Public Sub Example()
Dim olNs As Outlook.NameSpace
Dim RSS_Folder As Outlook.MAPIFolder
Dim Item As Object
Dim Items As Items
Dim DupItem As Object
Dim i As Long
Set olNs = Application.GetNamespace("MAPI")
Set RSS_Folder = olNs.GetDefaultFolder(olFolderRssFeeds) _
.Folders("Microsoft At Home")
Set DupItem = CreateObject("Scripting.Dictionary")
Set Items = RSS_Folder.Items
For i = Items.Count To 1 Step -1
DoEvents
If TypeOf Items(i) Is PostItem Then
Set Item = Items(i)
If DupItem.Exists(Item.subject) Then
Debug.Print Item.subject ' Print on Immediate Window
Debug.Print TypeName(Item) ' Print on Immediate Window
' Item.Delete
Else
DupItem.Add Item.subject, 0
End If
End If
Next i
Set olNs = Nothing
Set RSS_Folder = Nothing
Set Item = Nothing
Set Items = Nothing
Set DupItem = Nothing
End Sub
This Example shows how to process all Folders under RSS Feed Folders
Option Explicit
Public Sub DupeRSS()
Dim olNs As Outlook.NameSpace
Dim RSS_Folder As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set RSS_Folder = olNs.GetDefaultFolder(olFolderRssFeeds)
' // Process Current Folder
Example RSS_Folder
End Sub
Public Sub Example(ByVal ParentFolder As Outlook.MAPIFolder)
Dim Folder As Outlook.MAPIFolder
Dim Item As Object
Dim DupItem As Object
Dim Items As Items
Dim i As Long
Set DupItem = CreateObject("Scripting.Dictionary")
Set Items = ParentFolder.Items
For i = Items.Count To 1 Step -1
DoEvents
If TypeOf Items(i) Is PostItem Then
Set Item = Items(i)
If DupItem.Exists(Item.subject) Then
Debug.Print Item.subject ' Print on Immediate Window
Debug.Print TypeName(Item) ' Print on Immediate Window
Item.Delete
Else
DupItem.Add Item.subject, 0
End If
End If
Next i
' // Recurse through subfolders
If ParentFolder.Folders.Count > 0 Then
For Each Folder In ParentFolder.Folders
Example Folder
Debug.Print Folder.Name
Next
End If
Set Folder = Nothing
Set Item = Nothing
Set Items = Nothing
Set DupItem = Nothing
End Sub
Remember the code will only compare duplicate in single folder
I wish to create a VBA program to remove items within the Deleted Items folder of my outlook. However, I only wish to remove such items from the certain users through matching a loose string.
For example, deleting all emails within the Deleted Items box from any user with address like "Plan_Group_", given I may receive emails from "Plan_Group_1", "Plan_Group_2","Plan_Group_3",...etc.
At present this is what I have for deletion, but it is for all items within the Deleted Items box:
Sub RemoveAutomaticItemsInDeletedItems()
Dim oDeletedItems As Outlook.Folder
Dim oItems As Outlook.Items
Dim i As Long
'Obtain a reference to deleted items folder
Set oDeletedItems = Application.Session.GetDefaultFolder(olFolderDeletedItems)
Set oItems = oDeletedItems.Items
For i = oItems.Count To 1 Step -1
oItems.Item(i).Delete
Next
End Sub
How can I extend this to only look for emails that loosely match a from address string?
Use an If statement to check the email address:
If TypeName(oItems.Item(i)) = "MailItem" And oItems(i).SenderEmailAddress Like "Plan_Group_*" Then
oItems.Item(i).Delete
End If
Or:
If TypeName(oItems.Item(i)) = "MailItem" And Left$(oItems(i).SenderEmailAddress, 11) = "Plan_Group_" Then
oItems.Item(i).Delete
End If
Just 2 ways of doing it
I wanted to develop VBA code that:
Loops through all email items in mailbox
If there are any type of other items say "Calendar Invitation" skips that item.
Finds out the emails with attachments
If attached file has ".xml" extension and a specific title in it, saves it to a directory, if not it keeps searching
Puts all email includes .xml attachments to "Deleted Items" folder after doing step 4 and deletes all emails in that folder by looping.
Code works perfect EXCEPT;
For example
There are 8 email received with ".xml" file attached to each one of them in your mailbox.
run the code
you will see only 4 of the 8 items are processed successfully, other 4 remain in their positions.
If you run the code again, now there would be 2 items processed successfully and other 2 remain in your mailbox.
Problem: After running the code, it is supposed to process all files and deletes them all not the half of them in each run. I want it to process all items at a single run.
BTW, this code runs every time I open the Outlook.
Private Sub Application_Startup()
'Initializing Application_Startup forces the macros to be accessible from other offic apps
'Process XML emails
Dim InboxMsg As Object
Dim DeletedItems As Outlook.Folder
Dim MsgAttachment As Outlook.Attachment
Dim ns As Outlook.NameSpace
Dim Inbox As Outlook.Folder
Dim fPathTemp As String
Dim fPathXML_SEM As String
Dim fPathEmail_SEM As String
Dim i As Long
Dim xmlDoc As New MSXML2.DOMDocument60
Dim xmlTitle As MSXML2.IXMLDOMNode
Dim xmlSupNum As MSXML2.IXMLDOMNode
'Specify the folder where the attachments will be saved
fPathTemp = "some directory, doesn't matter"
fPathXML_SEM = "some directory, doesn't matter"
fPathEmail_SEM = "some directory, doesn't matter"
'Setup Outlook
Set ns = GetNamespace("MAPI")
Set Inbox = ns.Folders.Item("mailbox-name").Folders("Inbox")
Set DeletedItems = ns.Folders.Item("mailbox-name").Folders("Deleted Items")
'Loop through all Items in Inbox, find the xml attachements and process if they are the matching reponses
'On Error Resume Next
For Each InboxMsg In Inbox.Items
If InboxMsg.Class = olMail Then 'if it is a mail item
'Check for xml attachement
For Each MsgAttachment In InboxMsg.Attachments
If Right(MsgAttachment.DisplayName, 3) = "xml" Then
'Load XML and test for the title of the file
MsgAttachment.SaveAsFile fPathTemp & MsgAttachment.FileName
xmlDoc.Load fPathTemp & MsgAttachment.FileName
Set xmlTitle = xmlDoc.SelectSingleNode("//title")
Select Case xmlTitle.Text
Case "specific title"
'Get supplier number
Set xmlSupNum = xmlDoc.SelectSingleNode("//supplierNum")
'Save the XML to the correct folder
MsgAttachment.SaveAsFile fPathXML_SEM & xmlSupNum.Text & "_" & Format(Date, "yyyy-mm-dd") & ".xml"
'Save the email to the correct folder
InboxMsg.SaveAs fPathEmail_SEM & xmlSupNum.Text & "_" & Format(Date, "yyyy-mm-dd") & ".msg"
'Delete the message
InboxMsg.Move DeletedItems
Case Else
End Select
'Delete the temp file
On Error Resume Next
Kill fPathTemp & MsgAttachment.FileName
On Error GoTo 0
'Unload xmldoc
Set xmlDoc = Nothing
Set xmlTitle = Nothing
Set xmlSupNum = Nothing
End If
Next
End If
Next
'Loop through deleted items and delete
For Each InboxMsg In DeletedItems.Items
InboxMsg.Delete
Next
'Clean-up
Set InboxMsg = Nothing
Set DeletedItems = Nothing
Set MsgAttachment = Nothing
Set ns = Nothing
Set Inbox = Nothing
i = 0
End Sub
Likely cause: When you do this InboxMsg.Move, all of the messages in your inbox after the one that was moved are bumped up by one position in the list. So you end up skipping some of them. This is a major annoyance with VBA's For Each construct (and it doesn't seem to be consistent either).
Likely solution: Replace
For Each InboxMsg In Inbox.Items
with
For i = Inbox.Items.Count To 1 Step -1 'Iterates from the end backwards
Set InboxMsg = Inbox.Items(i)
This way you iterate backward from the end of the list. When you move a message to deleted items, then it doesn't matter when the following items in the list are bumped up by one, because you've already processed them anyway.
It's often not a good idea to modify the contents of a (sub)set of items while looping over them. You could modify your code so that it first identifies all of the items that need to be processed, and adds them to a Collection. Then process all the items in that collection.
Basically you shouldn't be removing items from the Inbox while you're looping through its contents. First collect all the items you want to process (in your Inbox loop), then when you're done looping, process that collection of items.
Here's some pseudo-code which demonstrates this:
Private Sub Application_Startup()
Dim collItems As New Collection
'Start by identifying messages of interest and add them to a collection
For Each InboxMsg In Inbox.Items
If InboxMsg.Class = olMail Then 'if it is a mail item
For Each MsgAttachment In InboxMsg.Attachments
If Right(MsgAttachment.DisplayName, 3) = "xml" Then
collItems.Add InboxMsg
Exit For
End If
Next
End If
Next
'now deal with the identified messages
For Each InboxMsg In collItems
ProcessMessage InboxMsg
Next InboxMsg
'Loop through deleted items and delete
For Each InboxMsg In DeletedItems.Items
InboxMsg.Delete
Next
End Sub
Sub ProcessMessage(InboxMsg As Object)
'deal with attachment(s) and delete message
End Sub
I am trying to transform my Outlook2003 into the closest thing to gmail.
I started to use categories, which are pretty similar to labels in gmail. I can assign categories automatically with rules, and I can add categories manually.
I have also created "search folders", that show all mails with a given category, if they are not in the Deleted Items or Sent Items folders. This part is almost like the Label views in gmail.
Two things are missing basically, which should be done with macros (VBA to be precise) which I'm totally inexperienced with. So hence my questions:
-Can someone show me a macro to remove the category "Inbox"?
That would act exactly like the Archive button in gmail. In fact I want to assign this macro to a toolbar button and call it Archive.
I have a rule that adds the Inbox category to all incoming mail. As I said, I have a search folder displaying all mails categorized as Inbox, and I also have an All Mail search folder, that displays all messages regardless whether they have the Inbox category. Exactly like gmail, just the easy archiving is missing.
-Can someone show me a macro that would delete the selected mail/mails and also would remove the Inbox category before deletion? I would replace the default delete button with this macro. (Somewhat less important, as in my search folders I can filter messages that are physically placed in the Deleted Items folder, but it would be more elegant not to have mails categorized as Inbox in the trash.
Many thanks in advance,
szekelya
I have used Sue's remove code from http://www.outlookcode.com/codedetail.aspx?id=1211
But this should work you
Added save ! Doh!
Sub UnAssignInboxCat()
Dim SelectedItems As Selection
Dim Item As MailItem
Set SelectedItems = Application.ActiveExplorer.Selection
For Each Item In SelectedItems
RemoveCat Item, "Inbox"
Item.Save
Next
Set SelectedItems = Nothing
Set Item = Nothing
End Sub
Sub DeleteAndUnAssignInboxCat()
Dim SelectedItems As Selection
Dim Item As MailItem
Set SelectedItems = Application.ActiveExplorer.Selection
For i = SelectedItems.Count To 1 Step -1
Set Item = SelectedItems.Item(i)
RemoveCat Item, "Inbox"
Item.Save
Item.Delete
Next
Set SelectedItems = Nothing
Set Item = Nothing
End Sub
Sub RemoveCat(itm, catName)
arr = Split(itm.Categories, ",")
If UBound(arr) >= 0 Then
' item has categories
For i = 0 To UBound(arr)
If Trim(arr(i)) = catName Then
' category already exists on item
' remove it
arr(i) = ""
'rebuild category list from array
itm.Categories = Join(arr, ",")
Exit Sub
End If
Next
End If
End Sub
I have the following macro in outlook to clear my deleted folder. its strange as it doesn't seem to delete all entries. I have to run this a few times for it to clear to deleted items folder. (usually 2 or 3 times). Each time the number of deleted items in the folder does get reduced but I don't understand why everything doesn't get wiped out in the first go.
Here is my code; Anything wrong?
Public Sub EmptyDeletedEmailFolder()
Dim outApp As Outlook.Application
Dim deletedFolder As Outlook.MAPIFolder
Dim item As Object
Dim entryID As String
Set outApp = CreateObject("outlook.application")
Set deletedFolder = outApp.GetNamespace("MAPI").GetDefaultFolder(olFolderDeletedItems)
For Each item In deletedFolder.Items
item.Delete ' Delete from mail folder
Next
Set item = Nothing
Set deletedFolder = Nothing
Set outApp = Nothing
End Sub
Try:
For i = deletedFolder.Items.Count To 1 Step -1
deletedFolder.Items(i).Delete '' Delete from mail folder
Next
There can be problems with deleting items from a collection.
By deleting the objects in the collection "underneath" the iterator, it couldn't really go over each item in the collection because the collection was changing. Remou came up with a really good way that will be guaranteed to continuously delete items in the collection as long as there are items left. Just don't be deleting items yourself while the method runs or you could run into prolems.