網路城邦
RSS Feed Link 部落格聯播
Office (Word、Excel、Powerpoint、Outlook) VBA (Visiual Basic for Application) 巨集 macro 增益集 add-in 程式設計

與大家分享這些知識,這裡的文章以及文章裡的程式實例都是我寫的 (除非有標示引用出處的例外)。只是我現在的工作和我的心已經離這些愈來愈遠了,就擺在這裡供大家參考吧!

朋友們可透過email或在 facebook 找我:

way_kkiimmoo@yahoo.com.tw

http://www.facebook.com/way.cheng

文章數:49
[Outlook VBA] 做出 Outlook 郵件資料夾的樹狀目錄
興趣嗜好電腦3C 2009/06/18 02:37:44

 
*這裡所說的 "Outlook" 是指 "Microsoft Office (我用的是2003版)" 裡的 Outlook,不是 Outlook Express。Outlook Express 不支援 VBA。
*2018/7/2補充說明:經查
2007版的物件庫已變更。在2007版中,此程式裡的 Outlook.MAPIFolder 都必須改成 Outlook.Folder
 
有位朋友讀了「 把 email 附件檔全部存入一個資料夾」這篇文章,留言問道:『如果我不是使用預設的"收件匣",而是我自己建的郵件目錄,還能使用GetDefaultFolder()嗎?如果不行,那要如何取得這個資料匣內的郵件呢?』這是一個很好的問題。GetDefaultFolder() 只能用於 Outlook 預設的資料夾,傳回的一定是如:"收件匣"、"寄件匣"、"連絡人"......等等這些資料夾物件。對於一般資料夾 (包括 Outlook 預設的資料夾),可以用底下這樣來取得:

Set myNameSpace = Application.GetNamespace("MAPI")
For Each subFolder In myNameSpace.Folders
    If subFolder.Name = "個人資料夾" Then
          .........(對這個資料夾要做的處理)
    End If
Next subFolder

或者像這樣:

Set myNameSpace = Application.GetNamespace("MAPI")
For i = 1 to myNameSpace.Folders.Count
    If myNameSpace.Folders(i).Name = "個人資料夾" Then
          .........(對這個資料夾要做的處理)
    End If
Next i 

在 Outlook 裡的資料夾其實是樹狀的結構,而且允許使用者自建資料夾。myNameSpace.Folders是 Outlook "第一層資料夾" 組成的集合 (collection) 物件。myNameSpace.Folders.Count 是這個集合裡的資料夾總數。而像 myNameSpace.Folders(1)、myNameSpace.Folders(2)......就是這個集合裡的個別資料夾。

myNameSpace.Folders(i).Name 就是某個資料夾的名稱。在底下的程式裡,還會用到資料夾的.DefaultMessageClass這個屬性來判斷資料夾的類別。(.Name 和.DefaultMessageClass屬性值都是字串型態)
要存取使用者自建的資料夾,就必須面對多層資料夾的問題,因為使用者自建的資料夾,不確定在第幾層 (不可能是第一層資料夾)。在前述「 把 email 附件檔全部存入一個資料夾」那篇文章裡,我為了降低程式的複雜度,刻意迴避了資料夾樹狀結構問題。在另一篇「 快速的把讀取窗格全部關掉」裡,您就會看到我用遞迴呼叫的方法來解決樹狀結構 (多層資料夾) 的問題。

底下我用實例來示範以 Msgbox 列出 Outlook 多層資料夾整個樹狀結構目錄,這個 ShowMailNoteFolderTree() 副程式執行的時候,會把樹狀結構裡的一層一層的資料夾名稱組成在strFolderTre 這個字串變數裡,最後再把它 show 出來。

為了示範如何利用.DefaultMessageClass這個屬性,我刻意把程式寫成只列出"郵件與通知" 類別的資料夾,也就是篩選.DefaultMessageClass屬性為"IPM.Note"的資料夾。(另一個原因是若把所有類別的資料夾都列出來可能太多,Msgbox的樹狀目錄超過螢幕高度就......)

怎麼知道 "IPM.Note" 是 "郵件與通知" 類別呢?也不難,我先寫了一個不篩選類別的版本,把每個資料夾的 .DefaultMessageClass 屬性值都列在資料夾名稱右邊,就知道啦!

Sub ShowMailNoteFolderTree()
Dim myNameSpace As Outlook.NameSpace
Dim subFolder As Outlook.MAPIFolder
Dim strFolderTree As String
Dim i, TotalSubs, tmpSubs As Integer
Dim LastOne As Boolean
Set myNameSpace = Application.GetNamespace("MAPI") TotalSubs = 0 計算 ("郵件與通知" 類別的) 子資料夾個數
For Each subFolder In myNameSpace.Folders
    If subFolder.DefaultMessageClass = "IPM.Note" Then "IPM.Note" 字串由實測而得
        TotalSubs = TotalSubs + 1
    End If
Next subFolder
LastOne = False
 i = 0
tmpSubs = 0
strFolderTree = "MAPI Root" & vbCrLf
For Each subFolder In myNameSpace.Folders 對於 Outlook MAPI 所有資料夾
If subFolder.DefaultMessageClass = "IPM.Note" Then 篩選符合 ("郵件與通知" 類別) 條件者
    i = i + 1
    If i = TotalSubs Then
        LastOne = True 判斷是否為最後一個 ("郵件與通知" 類別) 子資料夾
        tmpSubs = tmpSubs + AddSubTree(strFolderTree, subFolder, "", LastOne) 列出此資料夾的子樹
    End If
End If
Next subFolder
MsgBox strFolderTree & vbCrLf & "總計列出 " & TotalSubs + tmpSubs & " 個資料夾"
End Sub

在 ShowMailNoteFolderTree() 裡將多次叫用 AddSubTree() 來為 Outlook 第一層各資料夾建立它的子樹狀結構目錄。AddSubTree() 是一個用 "遞迴呼叫 (Recursion Call)" 的做法寫的函數,簡單的說,當它把指定的資料夾之名稱 (.Name) 加到目錄樹字串裡之後,如果這個指定的資料夾有子樹的話,它就會叫用 "它自己" 來處理子樹。

我把AddSubTree()的參數和傳回值意義寫在底下的程式碼註解裡,AddSubTree()的傳回值則是累加的,每一個被叫用的AddSubTree()都會傳回它的子樹大小(含有的資料夾數),所以,最後可以算出整個樹狀結構目錄的資料夾總數。

此外,閱讀的時候請特別注意 trTree是 "ByRef"(傳址的)!藉由傳址的方法,從 ShowMailNoteFolderTree()裡的strFolderTree 這個字串變數"本身"(不是它的"變數值" 喔!) 會被傳給被叫用的AddSubTree(),一路傳遞下去,所以字串會愈接愈長,直到 ShowMailNoteFolderTree()裡最後執行到Msgbox把它show出來為止。

Function AddSubTree(ByRef strTree As String, thisFolder As Outlook.MAPIFolder, _
                                 strPrefix As String, isLast As Boolean) As Integer
參數:strTree = 資料夾樹字串,thisFolder = 這個資料夾要被列出名稱和其子資料夾樹
strPrefix = 在此資料夾名稱前面要加的樹枝字串
isLast = 此資料夾本身是否為其父資料夾裡的最後一個 ("郵件與通知" 類別) 子資料夾
傳回值:此資料夾之子資料夾樹內的資料夾總數
Dim myNameSpace As Outlook.NameSpace
Dim subFolder As Outlook.MAPIFolder
Dim i, TotalSubs, tmpSubs As Integer
Dim LastOne As Boolean
If isLast Then 若是最後一個子資料夾,則名稱前面加 "└" 分支,否則就加 "├" 分支
    strTree = strTree & strPrefix & "└" & thisFolder.Name & vbCrLf
Else
    strTree = strTree & strPrefix & "├" & thisFolder.Name & vbCrLf
End If
此資料夾全部應有這麼多個子資料夾
TotalSubs = thisFolder.Folders.Count
但此題我只想列出 "郵件與通知" 類別的子資料夾
TotalSubs = 0 計算 ("郵件與通知" 類別的) 子資料夾個數
For Each subFolder In thisFolder.Folders
    If subFolder.DefaultMessageClass = "IPM.Note" Then "IPM.Note" 字串由實測而得
         TotalSubs = TotalSubs + 1
    End If
Next subFolder
If TotalSubs <> 0 Then 此資料夾若有 ("郵件與通知" 類別的) 子資料夾
     LastOne = False
     tmpSubs = 0
     i = 0
    For Each subFolder In thisFolder.Folders , 就把它所有的子資料夾樹列出來
        If subFolder.DefaultMessageClass = "IPM.Note" Then 篩選符合條件者
            i = i + 1
            If i = TotalSubs Then LastOne = True 判斷是否為最後一個子資料夾
            If isLast Then 若此資料夾本身是其父資料夾的最後一個 ("郵件與通知" 類別的) 
                                 子資料夾,就在其子資料夾名稱前面加一個全型的空白字元
                tmpSubs = tmpSubs + AddSubTree(strTree, subFolder, strPrefix & " ", LastOne)
            Else 否則,就在其子資料夾名稱前面加一個 "│" 樹枝
                tmpSubs = tmpSubs + AddSubTree(strTree, subFolder, strPrefix & "│", LastOne)
            End If
        End If
    Next subFolder
End If
AddSubTree = TotalSubs + tmpSubs
    傳回子資料夾樹內的 ("郵件與通知" 類別的) 資料夾總數
End Function

※ 以上程式碼裡因有使用 "│"、 " " 、"└"、"├" 等 BIG5 碼特殊字元,所以需在 BIG5 中文內碼的環境執行才能正常顯示。
※ 關於如何在 Outlook 裡執行巨集,請看這篇文章: 在 Outlook 裡使用巨集
※ 如需本文提及之各物件、集合、型別、屬性等等的詳細資料,請查 Outlook VBA 的 Help,或 Office 2003 VBA語言參考手冊

最新創作
[Excel VBA] 盤後彙整 N 分鐘 K 線 (利用抄錄到的成交價量資料)即將改版!
2022/02/11 13:19:40 |瀏覽 4497 回應 2 推薦 3 引用 0
從阿里山上的神木到開莆來學的牌樓
2022/01/24 10:51:16 |瀏覽 493 回應 1 推薦 5 引用 0
[Excel VBA] 使用者自訂函數:SumX(range) 不加隱藏儲存格的加總
2019/11/25 23:01:07 |瀏覽 5660 回應 2 推薦 3 引用 0
[Excel VBA] 固定間隔時間記錄DDE傳入資料之「預約開關版」(改版中)
2019/06/18 23:31:11 |瀏覽 5516 回應 2 推薦 3 引用 0
[Excel VBA] 抄錄 DDE OnCalculate 之預約開關版 (即將改版)
2019/06/11 20:47:12 |瀏覽 3291 回應 1 推薦 5 引用 0