[Outlook VBA] 做出 Outlook 郵件資料夾的樹狀目錄 - 返回 最初的純真性情 - udn部落格
返回 最初的純真性情
作家:ThisIsTheWay
文章分類
    Top
    [Outlook VBA] 做出 Outlook 郵件資料夾的樹狀目錄
    2009/06/18 02:37:44
    瀏覽:9845
    迴響:3
    推薦:17
    引用0

     

    *這裡所說的 "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語言參考手冊
    回應
    迴響(3) :
    3樓. Morris Chu
    2017/04/17 15:32
    真想給您跪了...(Maligbee@yahoo.com.tw)
    蒙您看得起! 哈哈哈 ThisIsTheWay2017/05/13 15:38回覆
    2樓. 古 月
    2011/07/21 12:44
    男女大不同

    我看了頭大

    但老公會喜歡

    好欽佩您


    1樓. the dreamer girl
    2009/06/19 15:40
    謝謝

    謝謝您的電腦程式教學

    雖然還未進入狀況

    但我會努力學習


    the dreamer girl~~ 最新作品:


    馬來西亞-吉隆坡市區觀光

    我貼出來的都是有一點點難度的程式,對於完全不會的人,是比較困難看懂的。

    ThisIsTheWay2009/06/21 13:49回覆
    發表迴響

    會員登入