Hỏi cách tối ưu cho sự kiện buttonclick với nhiều buttons giống nhau chức năng!!!

Liên hệ QC

Pham Dinh Ca

Thành viên mới
Tham gia
22/10/17
Bài viết
46
Được thích
1
Giới tính
Nam
Nghề nghiệp
Thất Nghiệp
Gửi các bạn trong diễn đàn!

Mình xin sự trợ giúp từ phía các bạn

Mình lập 1 form trong VBA mà có rất nhiều các command buttons ( ~ 30 cái). mà chức năng gần như giống nhau

Khi click vào các button thì sẽ chạy 1 đoạn sub giống nhau.

Vấn đề là, nếu viết lặp đi lặp lại các sự kiện cho từng buttons thì oải quá.

Vậy xin mọi người chia sẽ cách tối ưu cho vấn đề này

Mong muốn viết 1 đoạn ngắn có thể áp dụng được cho nhiều buttons khác nhau.

Xin cảm ơn mọi người!!!

1661882014182.png
 
Mình lập 1 form trong VBA mà có rất nhiều các command buttons ( ~ 30 cái). mà chức năng gần như giống nhau

Khi click vào các button thì sẽ chạy 1 đoạn sub giống nhau.

Vấn đề là, nếu viết lặp đi lặp lại các sự kiện cho từng buttons thì oải quá.
Lần sau phải đính kèm tập tin.

Lần này tự ráp vào tập tin của mình.

Giả thiết: Những CommandButton nào có cùng một macro thì phải có tên với tiền tố "btn_" như mô tả. Các CommandButton khác không cần và không được có tiền tố "btn_". Nếu giả thiết khác thì lần sau rút kinh nghiệm mô tả. Vì lần này tôi chỉ viết 1 lần.

1. Trong VBE: menu Insert -> Class -> đổi tên trong cửa sổ Properties thàng clsButton. Dán code sau vào module clsButton
Mã:
Option Explicit

Private WithEvents ctrl As MSForms.CommandButton
Private strMacro As String

Private Sub Class_Terminate()
    Set ctrl = Nothing
End Sub

' Cai nay hien tai khong can nen chi la ghi chu. Neu tuong lai can thi bo ghi chu
'Property Get Button() As MSForms.CommandButton
'    Set Button = ctrl
'End Property

Property Set Button(ctl As MSForms.CommandButton)
    Set ctrl = ctl
End Property

Property Let Macro(ByVal cmd As String)
    strMacro = cmd
End Property

Private Sub ctrl_Click()
    On Error Resume Next
    If strMacro <> vbNullString Then Application.Run strMacro, ctrl
End Sub

2. Trong module Form dán code
Mã:
Option Explicit

Private ctrl() As clsButton

Private Sub UserForm_Initialize()
Dim index As Integer, count As Long
    ReDim ctrl(1 To Me.Controls.count)
    For index = 1 To Me.Controls.count
        If InStr(1, Me.Controls("btn_" & index).Name, "btn_") = 1 Then
            count = count + 1
            Set ctrl(count) = New clsButton
            Set ctrl(count).Button = Me.Controls("btn_" & index)
            ctrl(count).Macro = "chonso"
        End If
    Next index
    If count Then ReDim Preserve ctrl(1 To count)
End Sub

Private Sub UserForm_Terminate()
Dim index As Long
    For index = LBound(ctrl) To UBound(ctrl)
        Set ctrl(index) = Nothing
    Next index
End Sub

3. Menu Insert -> Module. Dán code sau vào module
Mã:
Option Explicit

Sub chonso(ByVal cmd As MSForms.CommandButton)
'    biet nguoi dung nhan CommandButton nao thi xu ly thich hop. O day chi la hien thi ten CommandButton duoc nhan
    MsgBox "Nguoi dung nhan " & cmd.Name
End Sub
 
Upvote 0
Nếu 30 button(s) chạy cùng 1 sub thì tạo 1 button thôi.
 
Upvote 0
Lần sau phải đính kèm tập tin.

Lần này tự ráp vào tập tin của mình.

Giả thiết: Những CommandButton nào có cùng một macro thì phải có tên với tiền tố "btn_" như mô tả. Các CommandButton khác không cần và không được có tiền tố "btn_". Nếu giả thiết khác thì lần sau rút kinh nghiệm mô tả. Vì lần này tôi chỉ viết 1 lần.

1. Trong VBE: menu Insert -> Class -> đổi tên trong cửa sổ Properties thàng clsButton. Dán code sau vào module clsButton
Mã:
Option Explicit

Private WithEvents ctrl As MSForms.CommandButton
Private strMacro As String

Private Sub Class_Terminate()
    Set ctrl = Nothing
End Sub

' Cai nay hien tai khong can nen chi la ghi chu. Neu tuong lai can thi bo ghi chu
'Property Get Button() As MSForms.CommandButton
'    Set Button = ctrl
'End Property

Property Set Button(ctl As MSForms.CommandButton)
    Set ctrl = ctl
End Property

Property Let Macro(ByVal cmd As String)
    strMacro = cmd
End Property

Private Sub ctrl_Click()
    On Error Resume Next
    If strMacro <> vbNullString Then Application.Run strMacro, ctrl
End Sub

2. Trong module Form dán code
Mã:
Option Explicit

Private ctrl() As clsButton

Private Sub UserForm_Initialize()
Dim index As Integer, count As Long
    ReDim ctrl(1 To Me.Controls.count)
    For index = 1 To Me.Controls.count
        If InStr(1, Me.Controls("btn_" & index).Name, "btn_") = 1 Then
            count = count + 1
            Set ctrl(count) = New clsButton
            Set ctrl(count).Button = Me.Controls("btn_" & index)
            ctrl(count).Macro = "chonso"
        End If
    Next index
    If count Then ReDim Preserve ctrl(1 To count)
End Sub

Private Sub UserForm_Terminate()
Dim index As Long
    For index = LBound(ctrl) To UBound(ctrl)
        Set ctrl(index) = Nothing
    Next index
End Sub

3. Menu Insert -> Module. Dán code sau vào module
Mã:
Option Explicit

Sub chonso(ByVal cmd As MSForms.CommandButton)
'    biet nguoi dung nhan CommandButton nao thi xu ly thich hop. O day chi la hien thi ten CommandButton duoc nhan
    MsgBox "Nguoi dung nhan " & cmd.Name
End Sub
Em thấy nó đơn giản mà, đâu dùng gì quá trời code chi cho phí ạ?

1) Tại Class Module có tên clsFormEvent:

PHP:
Public WithEvents cmdChonSo As MSForms.CommandButton
''*********************************************************************************************

Private Sub cmdChonSo_Click()
    Call ChonSo
End Sub

2) Tại UserForm:

PHP:
Private priCmdChonSo(1 To 30) As New clsFormEvent

Private Sub UserForm_Initialize()
    Dim c As Byte
    For c = 1 To 30
        priCmdChonSo(c).cmdChonSo = Me("btn" & c)
    Next
End Sub

Chỉ đơn giản vậy thôi là giải quyết xong vấn đề.
 
Upvote 0
Em thấy nó đơn giản mà, đâu dùng gì quá trời code chi cho phí ạ?

1) Tại Class Module có tên clsFormEvent:

PHP:
Public WithEvents cmdChonSo As MSForms.CommandButton
''*********************************************************************************************

Private Sub cmdChonSo_Click()
    Call ChonSo
End Sub

2) Tại UserForm:
PHP:
Private priCmdChonSo(1 To 30) As New clsFormEvent

Private Sub UserForm_Initialize()
    Dim c As Byte
    For c = 1 To 30
        priCmdChonSo(c).cmdChonSo = Me("btn" & c)
    Next
End Sub

Chỉ đơn giản vậy thôi là giải quyết xong vấn đề.
1. Bạn đã chạy thử code của mình chưa hay bạn nghĩ là nó sẽ không có lỗi?

2. Cái thứ nhất là bạn ăn gian. Tôi làm code hủy các object tường minh. Và nữa, code của tôi không cần chỉnh sửa khi thêm button, bạn nhập cứng nhắc 30.

Tất nhiên người ta nói là 30 button chạy cùng 1 macro Chonso nhưng tôi hiểu là tùy theo nhấn nút nào mà code còn làm thêm một việc gì đó. Nếu 30 button đều chỉ làm Y HỆT một việc là gọn Chonso thì tạ̣o 30 buton để làm gì? Tôi không cho là người ta điên và dốt đến mức như thế. Người ta diễn đạt nhưng mình cũng nên hiểu người ta định làm gì. Có rất nhiều người mô tả rất qua loa.

3. Ngoài ra có một vấn đề tôi đã nói cách đây mấy năm. Có nhiều trường phái khi dùng class. Tôi theo trường phái là mọi dữ liệu của class đều PRIVATE, truy cập tới các trường đó thông qua các thuộc tính và phương thức của class. Bạn dùng PUBLIC.

Tôi đã nói rõ quan điểm của mình 9 năm 7 tháng trước. Và tôi luôn làm làm class với phong cách của mình


class.png

Tôi muốn tạo class, code bài bản chứ không muốn tạo code ngắn để thi thố. Có những cái bạn cho là "râu ria", bạn bỏ qua để thắc mắc với tôi. Để làm gì? Tôi luôn cho là dữ liệu của người hỏi luôn là dữ liệu ví dụ, thực tế có thể khác. Nếu tôi cũng viết code cho 30 commandbutton thì chắc chắn code sẽ ngắn hơn. Nếu tôi không viết code hủy các control thì code cũng ngắn hơn. Nếu tôi không viết class bài bản thì code cũng ngắn hơn.

Tôi luôn cố viết code để giải quyết vấn đề của chủ thớt, nhưng sao cho nó tổng quát, linh động, và nếu có thể thì bài bản.

Nếu bạn viết thêm code hủy các object tường minh, và sao cho không cần chỉnh sửa code khi thêm button. Lúc đó xem code còn ngắn như bây giờ nữa không. Và nên biết là tôi tạo class bài bản, còn bạn thì không.

Bạn hỏi nên tôi trả lời thôi. Tôi không có gì để hỏi lại bạn. Tôi cũng không muốn tranh luận. Ai có giải pháp khác, hoặc hay hơn thì trực tiếp nói chuyện với chủ thớt nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
1. Bạn đã chạy thử code của mình chưa hay bạn nghĩ là nó sẽ không có lỗi?

2. Cái thứ nhất là bạn ăn gian. Tôi làm code hủy các object tường minh. Và nữa, code của tôi không cần chỉnh sửa khi thêm button, bạn nhập cứng nhắc 30.

Tất nhiên người ta nói là 30 button chạy cùng 1 macro Chonso nhưng tôi hiểu là tùy theo nhấn nút nào mà code còn làm thêm một việc gì đó. Nếu 30 button đều chỉ làm Y HỆT một việc là gọn Chonso thì tạ̣o 30 buton để làm gì? Tôi không cho là người ta điên và dốt đến mức như thế. Người ta diễn đạt nhưng mình cũng nên hiểu người ta định làm gì. Có rất nhiều người mô tả rất qua loa.

3. Ngoài ra có một vấn đề tôi đã nói cách đây mấy năm. Có nhiều trường phái khi dùng class. Tôi theo trường phái là mọi dữ liệu của class đều PRIVATE, truy cập tới các trường đó thông qua các thuộc tính và phương thức của class. Bạn dùng PUBLIC.

Tôi đã nói rõ quan điểm của mình 9 năm 7 tháng trước. Và tôi luôn làm làm class với phong cách của mình


View attachment 280549

Tôi muốn tạo class, code bài bản chứ không muốn tạo code ngắn để thi thố. Có những cái bạn cho là "râu ria", bạn bỏ qua để thắc mắc với tôi. Để làm gì? Tôi luôn cho là dữ liệu của người hỏi luôn là dữ liệu ví dụ, thực tế có thể khác. Nếu tôi cũng viết code cho 30 commandbutton thì chắc chắn code sẽ ngắn hơn. Nếu tôi không viết code hủy các control thì code cũng ngắn hơn. Nếu tôi không viết class bài bản thì code cũng ngắn hơn.

Tôi luôn cố viết code để giải quyết vấn đề của chủ thớt, nhưng sao cho nó tổng quát, linh động, và nếu có thể thì bài bản.

Nếu bạn viết thêm code hủy các object tường minh, và sao cho không cần chỉnh sửa code khi thêm button. Lúc đó xem code còn ngắn như bây giờ nữa không. Và nên biết là tôi tạo class bài bản, còn bạn thì không.

Bạn hỏi nên tôi trả lời thôi. Tôi không có gì để hỏi lại bạn. Tôi cũng không muốn tranh luận. Ai có giải pháp khác, hoặc hay hơn thì trực tiếp nói chuyện với chủ thớt nhé.
Đơn giản là đơn giản, không cần phải đem dao mỗ trâu để giết gà. Vả lại nếu thêm một CommandButton với chức năng khác là tèo téo teo luôn. Trong khi mình xác định 30 là 30, nếu thêm bao nhiêu thì tăng thêm bấy nhiêu.
 
Upvote 0
Đơn giản là đơn giản, không cần phải đem dao mỗ trâu để giết gà.
Vả lại nếu thêm một CommandButton với chức năng khác là tèo téo teo luôn


Mục đích của bạn là gì? Là muốn chế giễu tôi?

Tôi chỉ chỉ ra sự khác biệt trong tác phong lập trình giữa tôi và bạn. Và tôi đề nghị bạn nếu có cái gì hay thì đề xuất trực tiếp với chủ thớt. Vì tôi không muốn tranh luận. Thế thôi. Chỉ vì thế mà bạn chế giễu tôi?

Vả lại nếu thêm một CommandButton với chức năng khác là tèo téo teo luôn. Trong khi mình xác định 30 là 30, nếu thêm bao nhiêu thì tăng thêm bấy nhiêu.

Bạn không đọc kỹ bài của tôi rồi. Tôi là người duy nhất trên GPE hướng dẫn rất rõ ràng.
Giả thiết: Những CommandButton nào có cùng một macro thì phải có tên với tiền tố "btn_" như mô tả. Các CommandButton khác không cần và không được có tiền tố "btn_". Nếu giả thiết khác thì lần sau rút kinh nghiệm mô tả.

Tôi chấm dứt tại đây.
 
Upvote 0
Mục đích của bạn là gì? Là muốn chế giễu tôi?
Ồ không không, trăm lần không, ngàn lần không, em chỉ đưa ra những sự kiện có sẵn trong Class lên thôi, chứ em tuổi gì mà dám như thế. Nếu có gì mạo phạm xin được bỏ qua cho.
 
Upvote 0
Web KT

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

Back
Top Bottom