Tìm những thư nhận được trong ngày của thư mục Inbox trong Outlook và xuất kết quả thành tập tin Excel

Liên hệ QC

nguyendang95

Thành viên chính thức
Tham gia
25/5/22
Bài viết
71
Được thích
74
Nhân tiện gần đây có bạn hỏi "Làm thế nào để tìm những thư nhận được trong ngày từ Outlook và xuất kết quả tìm kiếm thành một báo cáo Excel hoàn chỉnh, vì yêu cầu công việc rất cần thao tác này" nên tôi xin viết về chủ đề này.

Trường hợp này ta có thể viết macro VBA trong Outlook giúp thống kê một cách tự động và nhanh chóng mà không cần dò tìm và viết thông tin của từng cái email sang Excel một cách thủ công.

Trong một thư mục email không chỉ chứa mỗi email mà còn có những item khác như tập tin đính kèm theo email. Nếu viết vòng lặp For Each hay For Next theo kiểu "nông dân" thì cũng được nhưng sẽ là thảm họa khi trong thư mục có hàng trăm, thậm chí lên đến hàng nghìn email khác nhau và ngày giờ nhận email cũng khác nhau, như thế code sẽ chạy cực kỳ chậm. May thay, Outlook cung cấp cho chúng ta nhiều đối tượng để tìm kiếm item trong Outlook như AdvancedSearch, Items.Restrict, Table, ... bằng truy vấn DASL hay DAV,... giúp cho ra kết quả rất nhanh và chính xác.

Macro dưới đây sử dụng đối tượng Table trong Outlook để tìm kiếm những thư nhận được trong ngày và trả kết quả sang tập tin Excel mới.

Mã:
Option Explicit

Public Sub CreateSimpleCustomReport()
    Dim objolNS As Outlook.NameSpace
    Dim objolStore As Outlook.Store
    Dim objolFldr As Outlook.Folder
    Dim objolTbAllMails As Outlook.Table
    Dim objolTbUnreadMails As Outlook.Table
    Dim objolRow As Outlook.Row
    Dim objolAcc As Outlook.Account
    Dim objolcolAccs As Outlook.Accounts
    Dim lngRow As Long
    Dim Data() As Variant
    Dim objXlApp As Object
    Dim objXlWb As Object
    Dim objxlSh As Object
    Dim strFilter As String
    Const xlContinuous As Byte = 1
    Const xlOpenXMLWorkbook As Byte = 51
    strFilter = "@SQL=%today(" & Quote("urn:schemas:httpmail:datereceived") & ")%"
    Set objolNS = Application.Session
    Set objXlApp = CreateObject("Excel.Application")
    With objXlApp
        .Visible = True
        .DisplayAlerts = False
        Set objXlWb = .Workbooks.Add 'Tao t?p tin Excel d? làm báo
    End With
    Set objolcolAccs = objolNS.Accounts
    For Each objolAcc In objolcolAccs 'Duy?t qua t?ng tài kho?n email
        Set objolStore = objolAcc.DeliveryStore
        Set objolFldr = objolStore.GetDefaultFolder(olFolderInbox) 'Xác d?nh h?p thu Inbox
        Set objolTbAllMails = objolFldr.GetTable(strFilter) 'Tìm nh?ng thu dã nh?n trong ngày hôm nay
        Set objolTbUnreadMails = objolTbAllMails.Restrict("@SQL=" & Quote("urn:schemas:httpmail:read") & "= 0") 'L?c ra k?t qu? nh?ng thu chua d?c t? k?t qu? tìm ki?m ? trên
        With objolTbAllMails.Columns 'Xác d?nh nh?ng thu?c tính c?a thu c?n l?y thông tin
            .Add "http://schemas.microsoft.com/mapi/proptag/0x0C1A001E" 'PR_SENDER_NAME
            .Add "UnRead" 'Read/Unread, tr? v? ki?u Boolean
            .Add "http://schemas.microsoft.com/mapi/proptag/0x10820040" 'PR_LAST_VERB_EXECUTION_TIME
            .Add "http://schemas.microsoft.com/mapi/proptag/0x10810003" 'PR_LAST_VERB_EXECUTED
            .Add "ReceivedTime" 'Th?i gian nh?n thu
        End With
        Set objxlSh = objXlWb.Sheets.Add 'Thêm Sheet m?i
        With objxlSh
            '.Name = objolAcc.SMTPAddress 'Ð?a ch? email
            .Range("B2").Value = "Account name: " & objolAcc.SMTPAddress 'Tên ngu?i dùng tài kho?n email
            .Range("B3").Value = "Folder: " & objolFldr.Name 'Tên thu m?c Inbox
            .Range("B4").Value = "Date: " & Format$(Date, "dd/mm/yyyy")
            .Range("B5").Value = "Number of incoming mails: " & objolTbAllMails.GetRowCount
            .Range("B6").Value = "Number of unread mails: " & objolTbUnreadMails.GetRowCount
            .Range("B8").Value = "Subject"
            .Range("C8").Value = "From"
            .Range("D8").Value = "Received Time"
            .Range("E8").Value = "Read/Unread"
            .Range("F8").Value = "Reply/Forward"
            .Range("G8").Value = "Reply Time"
        End With
        lngRow = 9 'Dòng cu?i cùng trong Sheet tru?c khi vi?t d? li?u
        With objxlSh 'Ti?n hành d?nh d?ng c?t
            .Range("B:G").EntireColumn.AutoFit 'T? d?ng giãn c?t
            .Range("B8:G8").Font.Bold = True
            .Range("B9").CurrentRegion.Borders.LineStyle = xlContinuous 'Thêm vi?n cho toàn b? b?ng
        End With
        If objolTbAllMails.GetRowCount > 0 Then 'N?u trong ngày hôm nay nh?n du?c 1 thu tr? lên
            Do Until objolTbAllMails.EndOfTable 'Duy?t qua b?ng k?t qu? d? l?y d? li?u
                Set objolRow = objolTbAllMails.GetNextRow
                Data() = objolRow.GetValues 'Ghi k?t qu? tìm ki?m vào m?ng
                With objxlSh 'Ghi d? li?u tìm ki?m t? b?ng ra t?p tin Excel
                    .Cells(lngRow, 2).Value = Data(1) 'Subject
                    .Cells(lngRow, 3).Value = Data(5) 'From
                    .Cells(lngRow, 4).Value = Format$(Data(9), "dd/mm/yyyy hh:mm") 'Received Time
                    Select Case Data(6) 'Read/Unread
                        Case True: .Cells(lngRow, 5).Value = "Unread"
                        Case False: .Cells(lngRow, 5).Value = "Read"
                    End Select
                    .Cells(lngRow, 6).Value = LastVerbText(CByte(Data(8))) 'Reply?
                    .Cells(lngRow, 7).Value = Data(7) 'Reply Time
                End With
                lngRow = lngRow + 1 'Xuong hang khi da ghi xong mot dong
            Loop
            With objxlSh
                .Range("B:G").EntireColumn.AutoFit
                .Range("B9").CurrentRegion.Borders.LineStyle = xlContinuous
                .Cells(lngRow + 1, 2).Value = "Date and Time of Report: " & Format$(Date, "dd/mm/yyyy") & " " & Format$(Time, "hh:mm:ss")
            End With
        Else: objxlSh.Cells(lngRow + 2, 2).Value = "Date and Time of Report: " & Now
        End If
    Next
    With objXlApp
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With
    Set objolNS = Nothing
    Set objolStore = Nothing
    Set objolFldr = Nothing
    Set objolTbAllMails = Nothing
    Set objolTbUnreadMails = Nothing
    Set objolRow = Nothing
    Set objXlApp = Nothing
    Set objXlWb = Nothing
    Set objxlSh = Nothing
    Set objolAcc = Nothing
    Set objolcolAccs = Nothing
End Sub

Private Function LastVerbText(Value As Byte) As String
    Select Case Value
        Case 102: LastVerbText = "Reply"
        Case 103: LastVerbText = "Reply to all"
        Case 104: LastVerbText = "Forward"
        Case Else: LastVerbText = "None"
    End Select
End Function

Private Function Quote(Text As String) As String
    Quote = Chr(34) & Text & Chr(34)
End Function

Kết quả minh họa sau khi chạy macro:

1653918197206.png
 
Chuỗi lọc của bạn chỉ dùng được với Outlook phiên bản tiếng Anh. Gặp tiếng Việt, Hàn, Nhật, Pháp... là chẳng làm ăn được gì.

Đừng vội đánh giá dùng vòng lặp thế này thế kia. Quan trọng là tư duy kỹ thuật code.
Người ta chỉ đơn giản sort items theo ngày một phát, chẳng hạn mới nhất lên đầu, thì chớp mắt xong rồi.
 
Upvote 0
Chuỗi lọc của bạn chỉ dùng được với Outlook phiên bản tiếng Anh. Gặp tiếng Việt, Hàn, Nhật, Pháp... là chẳng làm ăn được gì.

Đừng vội đánh giá dùng vòng lặp thế này thế kia. Quan trọng là tư duy kỹ thuật code.
Người ta chỉ đơn giản sort items theo ngày một phát, chẳng hạn mới nhất lên đầu, thì chớp mắt xong rồi.
Thường thì nhiều người sẽ viết thủ tục có tham số là giá trị cần lọc, sau đó thiết kế một biểu mẫu có text box để nhập tham số cho thủ tục đó. Lúc đó nhập giá trị unicode đềy được nhé.
Nếu dùng vòng lặp trong trường hợp này thì chương trình sẽ rất rối rắm do phải dùng nhiều câu lệnh if để kiểm tra điều kiện. Tại sao lại không dùng những đối tượng có sẵn như AdvancedSearch, Item.Find, Items.Restrict,... để tìm cho nhanh mà vẫn đạt hiệu quả?
Mục đích của macro này là giúp người dùng liệt kê được danh sách những email nhận được trong ngày vào một tệp Excel. Nếu có vài email thì không sao, chứ số lượng email lên đến cả trăm thì thống kê bằng tay sẽ rất lâu.
 
Upvote 0
Thường thì nhiều người sẽ viết thủ tục có tham số là giá trị cần lọc

Thường nào nữa đâu bạn. Cụ thể là cái chủ đề này của bạn đó.

1653968471558.png


Unicode nào chỗ này hả bạn?

strFilter = "@SQL=%today(" & Quote("urn:schemas:httpmail:datereceived") & ")%"

Nếu dùng vòng lặp trong trường hợp này thì chương trình sẽ rất rối rắm

Rối rắm chỗ nào? Bạn úp cái code rối rắm đó lên đây tôi chỉnh lại cho.

Tại sao lại không dùng những đối tượng có sẵn

Không có ai nói không dùng cái nào cả. Chỉ có bạn đi đánh giá này nọ thôi.

1653968674485.png
Mục đích của macro này là giúp người dùng liệt kê được danh sách những email nhận được trong ngày vào một tệp Excel. Nếu có vài email thì không sao, chứ số lượng email lên đến cả trăm thì thống kê bằng tay sẽ rất lâu.

Không ai nói gì tay hay chân gì ở đây cả. Vẫn bàn về code.
 
Upvote 0
Thường nào nữa đâu bạn. Cụ thể là cái chủ đề này của bạn đó.

View attachment 276670



Unicode nào chỗ này hả bạn?

strFilter = "@SQL=%today(" & Quote("urn:schemas:httpmail:datereceived") & ")%"



Rối rắm chỗ nào? Bạn úp cái code rối rắm đó lên đây tôi chỉnh lại cho.



Không có ai nói không dùng cái nào cả. Chỉ có bạn đi đánh giá này nọ thôi.

View attachment 276671


Không ai nói gì tay hay chân gì ở đây cả. Vẫn bàn về code.
Bạn ơi, nếu bạn nói như vậy thì bạn chẳng biết gì về lập trình Outlook nên tôi xin phép không tiếp chuyện bạn nữa nhé. Bạn cứ tỏ ra tinh tướng mình biết tất rồi tự dưng nhảy xổ vào bài người ta phán này phán nọ trong khi chẳng biết gì về lập trình Outlook.
 
Upvote 0
Bạn ơi, nếu bạn nói như vậy thì bạn chẳng biết gì về lập trình Outlook nên tôi xin phép không tiếp chuyện bạn nữa nhé. Bạn cứ tỏ ra tinh tướng mình biết tất rồi tự dưng nhảy xổ vào bài người ta phán này phán nọ trong khi chẳng biết gì về lập trình Outlook.

Trong này có nhiều người như bạn, khi tranh luận đuối lý, thấy người ta phát hiện ra cái sai... không làm gì được thì quay ra công kích cá nhân.

Tôi không bao giờ chấp những câu chữ như thế.

Bạn cứ trao đổi chuyên môn, tôi có khả năng tới đâu sẵn sàng trao đổi với bạn tới đó.

Bạn cứ làm chỗ này đi sẽ biết ai biết, ai chẳng biết.

1653970533715.png
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom