Dùng sự kiện Private Sub Worksheet_Change để thông báo

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

LanAnh19

Thành viên chính thức
Tham gia
1/5/22
Bài viết
76
Được thích
8
Giới tính
Nữ
Các anh/chị giúp em trường hợp sau
Em muốn dùng sự kiện Private Sub Worksheet_Change tại sheet DT để thông báo như sau
Ví dụ ở sheet DT mà em nhập Tên khách hàng ( cột C) sau khi nhập tên xong và Enter
Nếu bên sheet Ma_KH có tên khách hàng và có ghi tình trạng thì có thông báo tình trạng theo dòng tương ứng
Ví dụ : tên khách hàng Cty AAA thì thông báo là "No lau, kho doi"
tên khách hàng Cty BBB thì không thông báo ( vì không có ghi tình trạng)
tên khách hàng Cty CCC thì thông báo là "Lay tien lien"
Em xin cảm ơn!
 

File đính kèm

  • ThongBao.xlsm
    10.1 KB · Đọc: 8
Các anh/chị giúp em trường hợp sau
Em muốn dùng sự kiện Private Sub Worksheet_Change tại sheet DT để thông báo như sau
Ví dụ ở sheet DT mà em nhập Tên khách hàng ( cột C) sau khi nhập tên xong và Enter
Nếu bên sheet Ma_KH có tên khách hàng và có ghi tình trạng thì có thông báo tình trạng theo dòng tương ứng
Ví dụ : tên khách hàng Cty AAA thì thông báo là "No lau, kho doi"
tên khách hàng Cty BBB thì không thông báo ( vì không có ghi tình trạng)
tên khách hàng Cty CCC thì thông báo là "Lay tien lien"
Em xin cảm ơn!
Bạn mình thử xem!
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("C9:C10000")) Is Nothing Then
        Dim Dic As Object, Key, Lr&, Arr(), i&
        Set Dic = CreateObject("Scripting.Dictionary")
        With Sheets("Ma_KH")
            Lr = .Range("F" & Rows.Count).End(xlUp).Row
            Arr = .Range("F13:G" & Lr).Value
            For i = 1 To UBound(Arr)
                If Arr(i, 1) <> "" Then
                    Key = Arr(i, 1)
                    If Not Dic.exists(Key) Then Dic.Add (Key), Arr(i, 2)
                End If
            Next i
        End With
        If Dic.exists(Target.Value) Then MsgBox Dic.Item(Target.Value)
    End If
    Set Dic = Nothing
End Sub
 
Upvote 0
Thêm chút mắm nêm:

If Dic.exists(Target.Value) And not IsEmpty(Dic.Item(Target.Value) ) Then MsgBox Dic.Item(Target.Value)
 
Upvote 0
Em xin cảm ơn các anh nhiều ạ!
 
Upvote 0
Xử lý dữ liệu ở sheet Ma_KH một lần duy nhất trong vòng đời sử dụng đó thôi. Khi thay đổi bảng dữ liệu đó mới cần xử lý lại.
Ai đời mỗi lần chên một phát lại dựng óp dếch, đọc bảng dữ liệu rồi chép vào óp dếch. Mệt lắm luôn ấy.
 
Upvote 0
Xử lý dữ liệu ở sheet Ma_KH một lần duy nhất trong vòng đời sử dụng đó thôi. Khi thay đổi bảng dữ liệu đó mới cần xử lý lại.
Ai đời mỗi lần chên một phát lại dựng óp dếch, đọc bảng dữ liệu rồi chép vào óp dếch. Mệt lắm luôn ấy.
Cám ơn bác, không biết ý bác có phải thế này?
Em chạy debug thì thấy code vẫn vận hành hết các lệnh, chưa thấy điểm khác nhau.
Nhờ bác khai sáng thêm giúp!
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim Dic As Object, Key, Lr&, Arr(), i&
    Set Dic = CreateObject("Scripting.Dictionary")
    With Sheets("Ma_KH")
        Lr = .Range("F" & Rows.Count).End(xlUp).Row
        Arr = .Range("F13:G" & Lr).Value
        For i = 1 To UBound(Arr)
            If Arr(i, 1) <> "" Then
                Key = Arr(i, 1)
                If Not Dic.exists(Key) Then Dic.Add (Key), Arr(i, 2)
            End If
        Next i
    End With
    If Not Intersect(Target, Range("C9:C10000")) Is Nothing Then
        If Dic.exists(Target.Value) And Not _
        IsEmpty(Dic.Item(Target.Value)) Then MsgBox Dic.Item(Target.Value)
    End If
    Set Dic = Nothing
End Sub
 
Upvote 0
Đặt cái đít sần làm biến Static hoặc biến toàn cục.
Nếu xét thấy nó Nothing thì bắt đầu dựng. Không phải thì do lần chạy trước đã dựng nó rồi, cứ thoải mái xài tiếp.
 
Upvote 0
Đặt cái đít sần làm biến Static hoặc biến toàn cục.
Nếu xét thấy nó Nothing thì bắt đầu dựng. Không phải thì do lần chạy trước đã dựng nó rồi, cứ thoải mái xài tiếp.
Cảm ơn bác, có lẽ vầy thì bớt lãng phí nhất chăng?
1. Private Sub Workbook_Open() -->khởi tạo và nạp dữ liệu vào dictionary (với khai báo public dictionary)
2. Private Sub Worksheet_Change(ByVal Target As Range)-->trả kết quả nếu có thay đổi ở target
3. Private Sub Workbook_BeforeClose(Cancel As Boolean) -->giải phóng dictionary
 
Upvote 0
Cảm ơn bác, có lẽ vầy thì bớt lãng phí nhất chăng?
1. Private Sub Workbook_Open() -->khởi tạo và nạp dữ liệu vào dictionary (với khai báo public dictionary)
2. Private Sub Worksheet_Change(ByVal Target As Range)-->trả kết quả nếu có thay đổi ở target
3. Private Sub Workbook_BeforeClose(Cancel As Boolean) -->giải phóng dictionary
Bài này dùng vlookup để làm thì có khác biệt gì không bạn?
 
Upvote 0
Cảm ơn bác, có lẽ vầy thì bớt lãng phí nhất chăng?
1. Private Sub Workbook_Open() -->khởi tạo và nạp dữ liệu vào dictionary (với khai báo public dictionary)
2. Private Sub Worksheet_Change(ByVal Target As Range)-->trả kết quả nếu có thay đổi ở target
3. Private Sub Workbook_BeforeClose(Cancel As Boolean) -->giải phóng dictionary
Vầy mới phí dữ tợn. Tôi mở workbook ra xem, chả làm gì cả. Rốt cuộc cả một mớ code chạy?
Ở bài trên, tôi nói là code WorkSheet_Change cứ tự nhiên mà check, nếu Nothing thì dựng, có rồi khỏi dựng.

Và ở bài trên, tôi ghỉ giải thích cho bạn kỹ thuật để dựng Object chỉ một lần. Lúc ấy tôi chưa xem code bài #7.
Code bài ấy bị cái lỗi lớn là "tự dưng dọn đường cho hoành tráng rồi đến cuối cùng mới xét xem vua có đi qua hay không". Đáng lé phải xét Target trước. Không đúng thì Exit Sub luôn, khỏi làm gì cả.
 
Upvote 0
Bài này dùng vlookup để làm thì có khác biệt gì không bạn?
Ý bạn hỏi không biết có phải là muốn biết khác về phương pháp, hay kết quả?
Nếu dùng hàm vlookup() thì bắt buộc phải có bẫy lỗi (trường hợp target không có trong bảng dò sẽ lỗi code).
Còn phương pháp thì chắc chắn rồi, chúng sẽ khác nhau.
 
Upvote 0
Cốt kiếc gì cũng chẳng qua được thực tế
(tôi chả hiểu tại sao bà con hay chê tôi ký thuyết mà chẳng thực tế. Ngược lại tôi thì thấy bà con chú vào những cái không thực tế - chạy 1/2 giây muốn tối ưu thành 1/4 giây)

Quyết định VLookup (đúng ra trong bài này là Index/Match tốt hơn - dễ kiểm soát hơn) hay Đít sần tùy thuộc vào cách sử dụng.
Nếu một lần mở file ra, chỉ phải làm một vài chục con nợ thì Index/Macth thực tế hơn. Nếu phải làm một lần cả trăm con nợ thì Đít sần hữu hiệu hơn vì nó tra cứu nhanh hơn. Trừ phi dữ liệu có sắp xếp - Match dữ liệu có sắp xếp rất nhanh. (*1)

Tuy nhiên, nếu một lần phân tích cả trăm con nợ thì tôi dùng cách khác chứ cách gõ mã rồi thông báo "No lâu, khó đói" là cách quá thô sơ, và quá cứng nhắc, không xứng đáng làm.
 
Upvote 0
Tuy nhiên, nếu một lần phân tích cả trăm con nợ thì tôi dùng cách khác chứ cách gõ mã rồi thông báo "No lâu, khó đói" là cách quá thô sơ, và quá cứng nhắc, không xứng đáng làm.
Khách hàng thuộc diện "No lâu, khó đói" là khách hàng mà mình nên giữ mối quan hệ lâu dài --=0 :)
 
Upvote 0
Khách hàng thuộc diện "No lâu, khó đói" là khách hàng mà mình nên giữ mối quan hệ lâu dài --=0 :)
Lâu dài chi vậy? Dân đang no mua hàng kén chọn lắm. Có đói mới bạ đâu vớ đấy.
Điển hình ở đây, dân đói bài nhiều lúc thấy câu hỏi mập mờ nhưng vẫn giải, hy vọng người hỏi sẽ thêm chi tiết sau rồi có dịp sửa chữa.
 
Upvote 0
Web KT

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

Back
Top Bottom