Is it possible to select a folder based on it's name rather then on it's path? VBA - Outlook - vba

Recently I am trying to create a function which selects specific folders.
I tested this at one user and it works. The problem however is that I also want to use this function at other users but not having to rewrite the function based on their folder structure.
The function works with a few folder names which all of them have (same names).
It consists of 1 main folder: #MemoScan and 4 sub-folders.
Based on these folder names I want to count how many mail items are in them.
I created the following function to do this:
Function HowManyEmails() As Integer
Dim objOutlook As Object, objnSpace As Object, MyCurrentFolder As MAPIFolder
Dim EmailCount As Integer
Set objOutlook = CreateObject("Outlook.Application")
Set objnSpace = objOutlook.GetNamespace("MAPI")
Set MyCurrentFolder = objnSpace.folders("William").folders("#MemoScan")
sFolder = MyCurrentFolder
For Each Folder In MyCurrentFolder.folders
sFolder = Folder
sSubmap = Right(sFolder, Len(sFolder) - 1)
For Each Item In Folder.Items
If TypeName(Item) = "MailItem" Then
EmailCount = EmailCount + 1
End If
Next Item
Next Folder
HowManyEmails = EmailCount
End Function
As you can see the folder that needs to be checked is hard-coded (needs to be since it runs on a close outlook event and nothing is selected).
The path now is: objnSpace.folders("William").folders("#MemoScan")
The thing is however that the main account/folder William wont be there at other users. My question is, how can I adjust it in such way that it will just look for the #MemoScan folder which is of the same at every user? Is this even possible?
If I leave the main William namespace out then it won't be able to find the #MemoScan folder.
The folder structure at this particular user is as follows:

The Namespace class provides the Stores property which returns a Stores collection object that represents all the Store objects in the current profile. The Store class provides the GetRootFolder method which returns a Folder object representing the root-level folder of the Store. You can use the GetRootFolder method to enumerate the subfolders of the root folder of the Store. Unlike NameSpace.Folders which contains all folders for all stores in the current profile, Store.GetRootFolder.Folders allows you to enumerate all folders for a given Store object in the current profile.
Sub EnumerateFoldersInStores()
Dim colStores As Outlook.Stores
Dim oStore As Outlook.Store
Dim oRoot As Outlook.Folder
On Error Resume Next
Set colStores = Application.Session.Stores
For Each oStore In colStores
Set oRoot = oStore.GetRootFolder
Debug.Print (oRoot.FolderPath)
EnumerateFolders oRoot
Next
End Sub
Private Sub EnumerateFolders(ByVal oFolder As Outlook.Folder)
Dim folders As Outlook.folders
Dim Folder As Outlook.Folder
Dim foldercount As Integer
On Error Resume Next
Set folders = oFolder.folders
foldercount = folders.Count
'Check if there are any folders below oFolder
If foldercount Then
For Each Folder In folders
Debug.Print (Folder.FolderPath)
EnumerateFolders Folder
Next
End If
End Sub
Also you can run the code against the currently selected folder in Outlook. The CurrentFolder property of the Explorer class returns a Folder object that represents the current folder displayed in the explorer.

Related

VBA selecting right mailbox?

In my Outlook, I have two accounts configured:
my main account / inbox: chip#mail.com
a shared mailbox: shared#mail.com
So there are two different mailboxes.
I could hide some default folders using VBA in both mailboxes.
But now I want to unhide a default folder in the shared mailbox shared#mail.com.
This is the suggested code:
Option Explicit
Public Sub UnHideFolders()
Dim oFolder As Outlook.Folder
Dim oPA As Outlook.propertyAccessor
Dim PropName, Value, FolderType As String
PropName = "http://schemas.microsoft.com/mapi/proptag/0x10F4000B"
Value = False
Set oFolder = Session.GetDefaultFolder(olFolderNotes)
Set oPA = oFolder.propertyAccessor
oPA.SetProperty PropName, Value
Set oFolder = Nothing
Set oPA = Nothing
End Sub
This works fine for the first mailbox account / inbox chip#mail.com, but I can't get it to work for the second account / shared mailbox shared#mail.com.
How do I have to change the above code to unhide folders in the second account / shared mailbox?
Thanks in advance for your support!
A somehow desperate Chipy
The following code can be used for getting the folder object that represents the default folder of the requested type for the current profile; for example, obtains the default Notes folder for the user who is currently logged on:
Set oFolder = Session.GetDefaultFolder(olFolderNotes)
To get folders from a shared account you need to use the NameSpace.GetSharedDefaultFolder method which returns a Folder object that represents the specified default folder for the specified user. This method is used in a delegation scenario, where one user has delegated access to another user for one or more of their default folders (for example, their shared Calendar folder). The following code illustrates a possible usage of the method to get a shared calendar folder:
Sub ResolveName()
Dim myNamespace As Outlook.NameSpace
Dim myRecipient As Outlook.Recipient
Dim CalendarFolder As Outlook.Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myRecipient = myNamespace.CreateRecipient("shared#mail.com")
myRecipient.Resolve
If myRecipient.Resolved Then
Call ShowCalendar(myNamespace, myRecipient)
End If
End Sub
Sub ShowCalendar(myNamespace, myRecipient)
Dim CalendarFolder As Outlook.Folder
Set CalendarFolder = myNamespace.GetSharedDefaultFolder(myRecipient, olFolderCalendar)
CalendarFolder.Display
End Sub
Note, the NameSpace.CreateRecipient method accepts the name of the recipient - it can be a string representing the display name, the alias, or the full SMTP email address of the recipient.
If that is not a standard folder or visible in Outlook you may consider using the Store.GetDefaultFolder method which returns a Folder object that represents the default folder in the store and that is of the type specified by the FolderType argument. This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.
To get the folder, try
Set oFolder = Session.Accounts("shared#mail.com").DeliveryStore.GetDefaultFolder(olFolderNotes)
... then re-use your existing code to manage the folder.

Move mails to folders with the sender's name

It is possible to create a rule which, for a sender, moves all the mails to the folder of your choice (for example, it creates a folder with the name of the sender).
If I want that for all the expeditors, I need to repeat the rule creation for each sender.
What I'd wish would be a macro "meta-rule" for each sender to have a folder with their name with the corresponding mails sorted.
I tried to start from the topic Outlook template rule to sort mails among directories.
I wrote this:
Sub RulesForFolders(m As MailItem)
Dim fldr As Outlook.Folder
For Each fldr In GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Folders
if fldr.Name Like m.SenderName Then m.MoveTo(SenderName)
else folders.add(m.SenderName)
Next
Set fldr = Nothing
End Sub
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
'
' If desperate declare as variant
Private Sub RulesForFolders(m As mailItem)
Dim targetFldr As folder
Dim myRoot As folder
Dim i As Long
Set myRoot = Session.GetDefaultFolder(olFolderInbox)
Debug.Print m.senderName
' This is often misused.
On Error Resume Next
' If folder exists the error is bypassed
' This is a rare beneficial use of On Error Resume Next
myRoot.folders.Add m.senderName
' Consider it mandatory to return to normal error handling
On Error GoTo 0
Set targetFldr = myRoot.folders(m.senderName)
m.Move targetFldr
End Sub
Private Sub RulesForFolders_test()
' Code requiring a parameter cannot run independently
Dim selItem As Object
' first select a mailitem
Set selItem = ActiveExplorer.Selection(1)
If selItem.Class = olMail Then
RulesForFolders ActiveExplorer.Selection(1)
End If
End Sub
First of all, I'd suggest starting from the NewMailEx event of the Application class which is fired when a new item is received in the Inbox. This event fires once for every received item that is processed by Microsoft Outlook. The item can be one of several different item types, for example, MailItem, MeetingItem, or SharingItem. The EntryIDsCollection string contains the Entry ID that corresponds to that item. The NewMailEx event fires when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item.
To find the folder with a sender name you can iterate over all subfolders recursively:
Private Sub processFolder(ByVal oParent As Outlook.MAPIFolder)
Dim oFolder As Outlook.MAPIFolder
Dim oMail As Outlook.MailItem
For Each oMail In oParent.Items
'Get your data here ...
Next
If (oParent.Folders.Count > 0) Then
For Each oFolder In oParent.Folders
processFolder oFolder
Next
End If
End Sub
Finally, I'd recommend delving deeper with VBA by starting from the Getting started with VBA in Office article.
You can also use the following code if you don't need to iterate over all folders:
Sub RulesForFolders(m As MailItem)
Dim fldr As Outlook.Folder
Dim new_fldr As Outlook.Folder
Dim ns as Outlook.Namespace
Dim inbox as Outlook.Folder
Set ns = Application.GetNamespace("MAPI")
Set inbox = ns.GetDefaultFolder(olFolderInbox)
For Each fldr In inbox.Folders
if InStr(fldr.Name,m.SenderName) > 0 Then
m.MoveTo(fldr)
Return
End If
Next
Set new_fldr = folders.add(m.SenderName)
m.MoveTo(new_fldr)
Set fldr = Nothing
Set new_fldr = Nothing
Set inbox = Nothing
Set ns = Nothing
End Sub

save PDF attachment with filename &domain name

I would like to run a macro to do follow steps:
- save PDF only attachment to hard drive
- save it with a revise name filename & domain name.
Here is the code I search from open source and mix it together. any help is appreciated. thanks
Public Sub Download_Attachments()
Dim ns As NameSpace
Dim olFolder_Inbox As Folder
Dim olMail As MailItem
Dim olAttachment As Attachment
Dim strFolderPath As String
Dim strFileName As String
Dim strSenderAddress As String
Dim strSenderDomain As String
Dim fso As Object
strFolderPath = "C:\"
Set ns = GetNamespace("MAPI")
Set fso = CreateObject("Scripting.FileSystemObject")
Set olFolder_Inbox = Application.ActiveExplorer.CurrentFolder
Set olMail = Application.ActiveWindow.CurrentItem
'Get sender domain
strSenderAddress = olMail.SenderEmailAddress
strSenderDomain = Right(strSenderAddress, Len(strSenderAddress) - InStr(strSenderAddress, "#"))
For Each olMail In olFolder_Inbox.Items
If TypeName(olMail) = "MailItem" And olMail.Attachments.Count > 0 Then
For Each olAttachment In olMail.Attachments
Select Case UCase(fso.GetExtensionName(olAttachment.FileName))
Case "PDF", "pdf"
olAttachment.SaveAsFile strFolderPath & strFileName
Case Else
'skip
End Select
Next olAttachment
End If
Next olMail
Set olFolder_Inbox = Nothing
Set fso = Nothing
Set ns = Nothing
End Sub
The following line of code retrieves the active folder in the Explorer window, not the Inbox one. Outlook can be started with any active folder, you can specify the folder name to the Outlook.exe file. To get the default folders (Inbox) you need to use the NameSpace.GetDefaultFolder method which returns a Folder object that represents the default folder of the requested type for the current profile; for example, obtains the default Calendar folder for the user who is currently logged on. For example, the following sample code uses the CurrentFolder property to change the displayed folder to the user's default Inbox folder.
Sub ChangeCurrentFolder()
Dim myNamespace As Outlook.NameSpace
Set myNamespace = Application.GetNamespace("MAPI")
Set Application.ActiveExplorer.CurrentFolder = myNamespace.GetDefaultFolder(olFolderInbox)
End Sub
Then it is not really recommended to iterate over all items in the folder.
For Each olMail In olFolder_Inbox.Items
Instead, you need to use the Find/FindNext or Restrict methods of the Items class to get only items that correspond to your conditions. Read more about these methods 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
Finally, the part you are interested in is the SaveAsFile method of the Attachment class which saves the attachment to the specified path:
olAttachment.SaveAsFile strFolderPath & domainName & strFileName
Make sure a qualified file path is passed as a parameter. I'd recommend running the code under the debugger and see what values are passed.

How to Create Task in Shared Task List?

I'm trying to convert an email to task and place that task inside a shared task folder. My co-worker shared the folder and has given me owner access to the folder as well.
We have utilized the script on slipstick to accomplish this. This code does work for my co-worker, but does not work for me.
When I dig into the list of folders I see my personal task list as a folder and not the shared folder. (Via the code below)
Is there any way that I can add a task to a shared task folder?
Public strFolders As String
Public Sub GetFolderNames()
Dim olApp As Outlook.Application
Dim olSession As Outlook.NameSpace
Dim olStartFolder As Outlook.MAPIFolder
Dim lCountOfFound As Long
lCountOfFound = 0
Set olApp = New Outlook.Application
Set olSession = olApp.GetNamespace("MAPI")
' Allow the user to pick the folder in which to start the search.
Set olStartFolder = olSession.PickFolder
' Check to make sure user didn't cancel PickFolder dialog.
If Not (olStartFolder Is Nothing) Then
' Start the search process.
ProcessFolder olStartFolder
End If
' Create a new mail message with the folder list inserted
Set ListFolders = Application.CreateItem(olMailItem)
ListFolders.Body = strFolders
ListFolders.Display
' clear the string so you can run it on another folder
strFolders = ""
End Sub
Sub ProcessFolder(CurrentFolder As Outlook.MAPIFolder)
Dim i As Long
Dim olNewFolder As Outlook.MAPIFolder
Dim olTempFolder As Outlook.MAPIFolder
Dim olTempFolderPath As String
' Loop through the items in the current folder.
For i = CurrentFolder.Folders.Count To 1 Step -1
Set olTempFolder = CurrentFolder.Folders(i)
olTempFolderPath = olTempFolder.FolderPath
' Get the count of items in the folder
olCount = olTempFolder.Items.Count
'prints the folder path and name in the VB Editor's Immediate window
Debug.Print olTempFolderPath & " " & olCount
' prints the folder name only
' Debug.Print olTempFolder
' create a string with the folder names.
' use olTempFolder if you want foldernames only
strFolders = strFolders & vbCrLf & olTempFolderPath & " " & olCount
lCountOfFound = lCountOfFound + 1
Next
' Loop through and search each subfolder of the current folder.
For Each olNewFolder In CurrentFolder.Folders
'Don't need to process the Deleted Items folder
If olNewFolder.Name <> "Deleted Items" Then
ProcessFolder olNewFolder
End If
Next
End Sub
In addition the Task folder, you will need permission to your co-worker's Mailbox. (Not Inbox nor other folders.)
If you add the mailbox to your profile, see the accepted answer here.
If you do not add the mailbox to your profile, see the answer describing GetSharedDefaultFolder. Redemption is not required.

Use Folder Path String to select folder in VBA in Outlook

How can I enter a string as a folder location
ex. \MySpecificEmailAddress\Inbox
To select that folder in VBA using outlook?
I obtained the path using:
... = ActiveExplorer.CurrentFolder.FolderPath
I have searched far and wide to automatically tell the script which specific folder to run a macro on without having to select the folder then run the script.
You should be able to enumerate Session.Stores and then Store.GetRootFolder.Folders to access all folders for a given mailbox. Depending on how many levels deep you need to go, this may take a bit more effort (i.e. recursion).
Here is a code snippet from MSDN which enumerates all folders under the mailbox/store root folders:
Sub EnumerateFoldersInStores()
Dim colStores As Outlook.Stores
Dim oStore As Outlook.Store
Dim oRoot As Outlook.Folder
On Error Resume Next
Set colStores = Application.Session.Stores
For Each oStore In colStores
Set oRoot = oStore.GetRootFolder
Debug.Print (oRoot.FolderPath)
EnumerateFolders oRoot
Next
End Sub
Private Sub EnumerateFolders(ByVal oFolder As Outlook.Folder)
Dim folders As Outlook.folders
Dim Folder As Outlook.Folder
Dim foldercount As Integer
On Error Resume Next
Set folders = oFolder.folders
foldercount = folders.Count
'Check if there are any folders below oFolder
If foldercount Then
For Each Folder In folders
Debug.Print (Folder.FolderPath)
EnumerateFolders Folder
Next
End If
End Sub
I have just now built and tested the following function to get an outlook folder by it's path string... of course it is in Javascript, but you can easily convert it to VBA or VBScript.
function getFolderByPath(oParent, sFoldPath) {
sFoldPath = sFoldPath.toLowerCase();
var oFolds = new Enumerator(oParent.Folders);
for(oFolds.moveFirst(); !oFolds.atEnd(); oFolds.moveNext()) {
var sPath = oFolds.item().FolderPath.toLowerCase();
if(sPath == sFoldPath) return oFolds.item();
if(sFoldPath.indexOf(sPath + "\\") == 0) return getFolderByPath(oFolds.item(), sFoldPath);
}
return null;
}
Usage:
var oRequiredFolder = getFolderByPath(oNameSpaceObject, "\\\\My\\required\\folder\\path");
Hope this helps someone.