• Shopee đêm nay có mã cho ngày 5/5

kiến thức [Mẹo VBA] Cách hiển thị tiếng Việt trong hộp thoại MsgBox

NguyenDang95

Senior Member
Chào mọi người, như đã biết VBA không hỗ trợ gõ tiếng Việt trong cửa sổ lập trình VBE nên việc hiển thị hộp thoại tiếng Việt trong hộp thoại MsgBox là điều bất khả thi. Ngoài việc dùng hàm chuyển đổi Unicode của một số diễn đàn chuyên về VBA, bằng kiến thức ít ỏi của bản thân tôi cũng xin đóng góp một cách đơn giản như sau:
  • Tạo một tệp .txt với cấu trúc “label: nội dung”, lưu với encoding UTF-16
Untitled.png

  • Viết hàm PairTextLinePair (sẽ trình bày ở ví dụ bên dưới) tìm label (bên trái dấu “:”, nếu tìm được thì trả về chuỗi nằm bên phải dấu “:”)
  • Tùy biến hàm MsgBox để hỗ trợ hiển thị ký tự Unicode nhờ API MessageBoxW, GetFocus
  • Dùng đối tượng Scripting.FileSystemObject, đọc toàn bộ tệp .txt, trả kết quả cho hàm PairTextLinePair
Ví dụ: Hiển thị hộp thoại nhắc người dùng đính kèm tệp vào mail trước khi gửi trong Outlook.
Code:
Option Explicit
#If VBA7 Then
    Private Declare PtrSafe Function MessageBoxW Lib "user32" (ByVal hWnd As LongPtr, ByVal lpText As LongPtr, ByVal lpCaption As LongPtr, ByVal uType As Long) As Long
    Private Declare PtrSafe Function GetFocus Lib "user32" () As LongPtr
    Private Declare PtrSafe Function MessageBeep Lib "user32" (ByVal wType As Long) As Long
#Else
    Private Declare Function MessageBoxW Lib "user32" (ByVal hWnd As Long, ByVal lpText As Long, ByVal lpCaption As Long, ByVal uType As Long) As Long
    Private Declare Function GetFocus Lib "user32" () As Long
    Private Declare Function MessageBeep Lib "user32" (ByVal wType As Long) As Long
#End If

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim objItem As Outlook.MailItem
    If TypeOf Item Is Outlook.MailItem Then
        Set objItem = Item
        If CancelNoAttachments(objItem) Then Cancel = True
    End If
    Set objItem = Nothing
End Sub

Private Function CancelNoAttachments(ByVal objItem As Outlook.MailItem) As Boolean
    Dim strMsg As String
    Dim strMsgSet As String
    Dim strKeyword1 As String
    Dim strKeyword2 As String
    Dim strPath As String
    Dim intPos1 As Integer
    Dim intPos2 As Integer
    Dim fso As Object
    Dim fsoFile As Object
    strPath = "C:\Outlook-msgbox.txt"
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fsoFile = fso.OpenTextFile(strPath, 1, False, -1)
    strMsgSet = fsoFile.ReadAll
    fsoFile.Close
    If objItem.Attachments.Count = 0 Then
        strKeyword1 = ParseTextLinePair(strMsgSet, "attached:")
        strKeyword2 = ParseTextLinePair(strMsgSet, "Attached:")
        intPos1 = InStr(1, objItem.Body, strKeyword1)
        intPos2 = InStr(1, objItem.Body, strKeyword2)
        If intPos1 > 0 Or intPos2 > 0 Then
            strMsg = ParseTextLinePair(strMsgSet, "Check for attachments:")
            If MsgBoxW(strMsg, vbQuestion + vbYesNo, "Add attachments?") = vbYes Then CancelNoAttachments = True
        End If
    End If
    Set fso = Nothing
    Set fsoFile = Nothing
End Function

‘Tùy biến hàm MsgBox để hỗ trợ hiển thị ký tự Unicode
Function MsgBoxW(Prompt As String, Optional Buttons As VbMsgBoxStyle = vbOKOnly, Optional Title As String = "Microsoft Outlook") As VbMsgBoxResult
Select Case Buttons
    Case vbInformation
        MessageBeep (&H10)
    Case vbQuestion
        MessageBeep (&H20)
    Case vbExclamation
        MessageBeep (&H30)
    Case vbCritical
        MessageBeep (&H40)
    Case Else
        MessageBeep (&H0)
End Select
MsgBoxW = MessageBoxW(GetFocus(), StrPtr(Prompt), StrPtr(Title), Buttons)
End Function

Function ParseTextLinePair(strSource As String, strLabel As String)
    Dim intLocLabel As Integer
    Dim intLocCRLF As Integer
    Dim intLenLabel As Integer
    Dim strText As String
    'Lay vi tri cua chuoi ky tu label trong van ban nguon
    intLocLabel = InStr(1, strSource, strLabel)
    'Tinh do dai chuoi ky tu label
    intLenLabel = Len(strLabel)
    'Neu ton tai chuoi ky tu label thi thuc hien buoc tiep theo
    If intLocLabel > 0 Then
        'Tim vi tri ky tu xuong dong, bat dau tu vi tri chuoi ky tu label
        intLocCRLF = InStr(intLocLabel, strSource, vbCrLf)
        'Tien hanh tach chuoi label
        If intLocCRLF > 0 Then
            intLocLabel = intLocLabel + intLenLabel
            strText = Mid(strSource, intLocLabel, intLocCRLF - intLocLabel)
        Else: strText = Mid(strSource, intLocLabel + intLenLabel)
        End If
    End If
    ParseTextLinePair = Trim(strText)
End Function

Kết quả:
1639451709515.png
 
Last edited:
Ý bác là trước khi gửi mail thì hiển thị thông báo kiểm tra lại danh sách người gửi, cc, bcc xem có sai sót gì, nếu người dùng bấm Yes là gửi đi đúng không bác?
Chuẩn rồi thím :sexy_girl:

Lâu rồi không động vào VBA thấy cái thread của thím cũng ham mà mấy cái cú pháp của VBA lười quá :shame:
 
Chuẩn rồi thím :sexy_girl:

Lâu rồi không động vào VBA thấy cái thread của thím cũng ham mà mấy cái cú pháp của VBA lười quá :shame:
Code đơn giản thôi thím:
Đưa thủ tục dưới đây đặt vào ThisOutlookSession, khởi động lại Outlook là xong.

Code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    If TypeOf Item Is Outlook.MailItem Then
        If MsgBox("Hay kiem tra lai danh sach nguoi gui, cc, bcc truoc khi xac nhan gui mail di." & vbCrLf & "Ban chac chan muon gui mail den (nhung) nguoi nhan nay?", vbQuestion + vbYesNo, "Check Recipients Before Sending") = vbYes Then
            Cancel = False
        Else: Cancel = True
        End If
    End If
End Sub

Kết quả:
1639472551925.png
 
Code đơn giản thôi thím:
Đưa thủ tục dưới đây đặt vào ThisOutlookSession, khởi động lại Outlook là xong.

Code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    If TypeOf Item Is Outlook.MailItem Then
        If MsgBox("Hay kiem tra lai danh sach nguoi gui, cc, bcc truoc khi xac nhan gui mail di." & vbCrLf & "Ban chac chan muon gui mail den (nhung) nguoi nhan nay?", vbQuestion + vbYesNo, "Check Recipients Before Sending") = vbYes Then
            Cancel = False
        Else: Cancel = True
        End If
    End If
End Sub

Kết quả:
View attachment 922199
Có làm cách nào mà list ra hết được không thím?

Ví dụ

Check sending address
To: Mr A [email protected], Mr B [email protected]
Cc: Ms C [email protected]
Bcc: Mrs D [email protected]
 
Có làm cách nào mà list ra hết được không thím?

Ví dụ

Check sending address
To: Mr A [email protected], Mr B [email protected]
Cc: Ms C [email protected]
Bcc: Mrs D [email protected]
Bác phải lưu email người nhận vào Contacts thì mới hiện tên người nhận nhé, không thì Outlook chỉ hiển thị mỗi địa chỉ email.

Code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim objMail As Outlook.MailItem
    Dim objRecip As Outlook.Recipient
    Dim colRecips As Outlook.Recipients
    Dim strRecipAddr As String
    Dim strCCAddr As String
    Dim strBCCAddr As String
    Dim strRecipName As String
    Dim strCCName As String
    Dim strBCCName As String
  
    If TypeOf Item Is Outlook.MailItem Then
        Set objMail = Item
        Set colRecips = objMail.Recipients
        For Each objRecip In colRecips
            With objRecip
                .Resolve
                If .Resolved Then
                    Select Case .Type
                        Case olTo
                            strRecipAddr = .Address
                            strRecipName = .Name
                        Case olCC
                            strCCAddr = .Address
                            strCCName = .Name
                        Case olBCC
                            strBCCAddr = .Address
                            strBCCName = .Name
                    End Select
                End If
            End With
        Next
        If MsgBox("Hay kiem tra lai danh sach nguoi gui, cc, bcc truoc khi xac nhan gui mail di." & vbCrLf & _
                    "Ban chac chan muon gui mail den (nhung) nguoi nhan nay?" & vbCrLf & vbCrLf & _
                    "Nguoi nhan :" & strRecipName & " " & strRecipAddr & vbCrLf & _
                    "CC: " & strCCName & " " & strCCAddr & vbCrLf & _
                    "BCC: " & strBCCName & " " & strBCCAddr, vbQuestion + vbYesNo, "Check Recipients Before Sending") = vbYes Then
            Cancel = False
        Else: Cancel = True
        End If
    End If
    Set objMail = Nothing
    Set objRecip = Nothing
    Set colRecips = Nothing
End Sub

Kết quả:
1639474803596.png
 
Last edited:
Bác phải lưu email người nhận vào Contacts thì mới hiện tên người nhận nhé, không thì Outlook chỉ hiển thị mỗi địa chỉ email.

Code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim objMail As Outlook.MailItem
    Dim objRecip As Outlook.Recipient
    Dim colRecips As Outlook.Recipients
    Dim strRecipAddr As String
    Dim strCCAddr As String
    Dim strBCCAddr As String
    Dim strRecipName As String
    Dim strCCName As String
    Dim strBCCName As String
 
    If TypeOf Item Is Outlook.MailItem Then
        Set objMail = Item
        Set colRecips = objMail.Recipients
        For Each objRecip In colRecips
            With objRecip
                .Resolve
                If .Resolved Then
                    Select Case .Type
                        Case olTo
                            strRecipAddr = .Address
                            strRecipName = .Name
                        Case olCC
                            strCCAddr = .Address
                            strCCName = .Name
                        Case olBCC
                            strBCCAddr = .Address
                            strBCCName = .Name
                    End Select
                End If
            End With
        Next
        If MsgBox("Hay kiem tra lai danh sach nguoi gui, cc, bcc truoc khi xac nhan gui mail di." & vbCrLf & _
                    "Ban chac chan muon gui mail den (nhung) nguoi nhan nay?" & vbCrLf & vbCrLf & _
                    "Nguoi nhan :" & strRecipName & " " & strRecipAddr & vbCrLf & _
                    "CC: " & strCCName & " " & strCCAddr & vbCrLf & _
                    "BCC: " & strBCCName & " " & strBCCAddr, vbQuestion + vbYesNo, "Check Recipients Before Sending") = vbYes Then
            Cancel = False
        Else: Cancel = True
        End If
    End If
    Set objMail = Nothing
End Sub

Kết quả:
View attachment 922279
Cám ơn thím.

Cơ mà sao mình add thử cái code bên kia vào không được nhỉ. Hay Office 365 Business không được nhỉ.
 
@NguyenDang95 có bug thím ơi. Nếu mà danh sách người gửi nhiều thì nó chỉ hiện cái cuối cùng thôi :D
Sorry thím nha :big_smile: Nãy em không để ý là sẽ có trường hợp người gửi nhiều hơn một :beat_shot:

Code:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim objMail As Outlook.MailItem
    Dim objRecip As Outlook.Recipient
    Dim colRecips As Outlook.Recipients
    Dim arrTo()
    Dim arrCC()
    Dim arrBCC()
    Dim strRecipAddr As String
    Dim strCCAddr As String
    Dim strBCCAddr As String
    Dim strRecipName As String
    Dim strCCName As String
    Dim strBCCName As String
    Dim i, j, k As Integer
   
    If TypeOf Item Is Outlook.MailItem Then
        Set objMail = Item
        Set colRecips = objMail.Recipients
        For Each objRecip In colRecips
            With objRecip
                .Resolve
                If .Resolved Then
                    Select Case .Type
                        Case olTo
                            i = i + 1
                            strRecipAddr = .Address
                            strRecipName = .Name
                            ReDim Preserve arrTo(1 To i)
                            arrTo(i) = strRecipName & " " & strRecipAddr
                        Case olCC
                            j = j + 1
                            strCCAddr = .Address
                            strCCName = .Name
                            ReDim Preserve arrCC(1 To j)
                            arrCC(j) = strCCName & " " & strCCAddr
                        Case olBCC
                            k = k + 1
                            strBCCAddr = .Address
                            strBCCName = .Name
                            ReDim Preserve arrBCC(1 To k)
                            arrBCC(k) = strBCCName & " " & strBCCAddr
                    End Select
                End If
            End With
        Next
        If MsgBox("Hay kiem tra lai danh sach nguoi gui, cc, bcc truoc khi xac nhan gui mail di." & vbCrLf & _
                    "Ban chac chan muon gui mail den (nhung) nguoi nhan nay?" & vbCrLf & vbCrLf & _
                    "Nguoi nhan: " & Join(arrTo, " ") & vbCrLf & _
                    "CC: " & Join(arrCC, " ") & vbCrLf & _
                    "BCC: " & Join(arrBCC, " "), vbQuestion + vbYesNo, "Check Recipients Before Sending") = vbYes Then
            Cancel = False
        Else: Cancel = True
        End If
    End If
    Set objMail = Nothing
    Set objRecip = Nothing
    Set colRecips = Nothing
End Sub


Kết quả:

1639482251715.png
 
Last edited:
Bác phải để code trong ThisOutlookSession là được mà, bản nào chạy đều được hết.
View attachment 922345
Thớt rành về outlook quá sẵn cho mình hỏi ké luôn vấn đề không liên quan lắm. Mình dùng office 365 mà outlook nó không cho thêm gmail. Cứ chọn thêm gmail là nó hiện cái giao diện đăng nhập rất cũ của google, nhập xong mật khẩu thì google báo là không thể đăng nhập. Mình google search thì thấy bảo là phải đăng nhập bằng mật khẩu ứng dụng gì đấy.
 
Thớt rành về outlook quá sẵn cho mình hỏi ké luôn vấn đề không liên quan lắm. Mình dùng office 365 mà outlook nó không cho thêm gmail. Cứ chọn thêm gmail là nó hiện cái giao diện đăng nhập rất cũ của google, nhập xong mật khẩu thì google báo là không thể đăng nhập. Mình google search thì thấy bảo là phải đăng nhập bằng mật khẩu ứng dụng gì đấy.
Thím làm theo hướng dẫn này là được á, căn bản do thằng Google bắt phải mở xác thực hai bước thì mới cho phép đăng nhập trên Outlook.
https://support.microsoft.com/en-us...-outlook-70191667-9c52-4581-990e-e30318c2c081
 
có cách nào hẹn giờ gửi mail trên outlook, tự động bcc bản thân mỗi khi gửi mail không fen, mình dùng office 365 :big_smile:
 
Ông thớt làm gì dài dòng thế :amazed:

Tạo 1 sheet mới coi như là sheet hệ thống. Tạo 01 bảng trong sheet đó bao gồm các cột : stt, tiêu đề, nội dung. Rồi viết code này

Sub MyMsgBox(stt As Integer)
Application.Assistant.DoAlert Application.WorksheetFunction.VLookup(stt, [TênBảng], 2, 0) _
, Application.WorksheetFunction.VLookup(stt, [TênBảng], 3, 0), _
msoAlertButtonOK, msoAlertIconInfo, 0, 0, 0
End Sub

Rồi sau đó cần dùng thì cứ thêm vào bảng hệ thống đó, rồi gọi ra thôi. Ví dụ :

stt tiêu đề nội dung
1 thông báo 1 nội dung 1
2 thông báo 2 nội dung 2
3 thông báo 3 nội dung 3
4 thông báo 4 nội dung 4
5 thông báo 5 nội dung 5

Lấy cái nào thì gõ

Call MyMsgbox(1) là xong

:big_smile:
 
Back
Top