Dùng Class Module để tạo sự kiện người dùng

Liên hệ QC

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,905
Tôi đang trong những bước đầu tiên nghiên cứu về Class Module nên sẽ viết theo sự hiểu biết của tôi. Nếu có sai sót, mong các cao thủ bổ sung thêm
Mục đích của bài viết này là:
- Tạo sự kiện người dùng khi mà các sự kiện cung cấp sẳn không đáp ứng được nhu cầu
- Khi mà chúng ta có nhu cầu "thu gom" tất cả các code của 1 số object (có cùng chức năng) về chung thành 1 code
------------------------------------------------------------------------------------------------
Giả định tình huống thế này:
- Tôi có 1 Workbook bao gồm 9 sheet, trong đó có 1 sheet Menu và 8 sheet con
- Tại sheet Menu, tôi vẽ 8 CommandButton để link đến 8 sheet con
- Tại các sheet con, mỗi sheet tôi vẽ 1 CommandButton để link đến sheet Menu
Thông thường bài toán này người ta sẽ viết cho mỗi CommandButton 1 đoạn code riêng lẻ. Như vậy, nếu số lượng object càng nhiều thì code của chúng ta sẽ trở nên dài dòng
Đàng nào thì các đoạn code ấy cũng có chung 1 mục đích... Vậy liệu có cách nào gom toàn bộ chúng thành 1 code duy nhất hay không? Câu trả lời là: Hoàn toàn có thể nếu biết dùng đến Class Module
Chúng ta cùng tiến hành giải pháp nhé
- Cứ cho rằng toàn bộ các CommandButton đã được vẽ xong
- Chuỗi mà ta gõ trên Caption của CommandButton chính là tên của sheet cần link
Vậy code của chúng ta sẽ bao gồm 2 phần
1> Trong Class Module
Hãy chèn 1 Class Module và nhớ đặt tên cho nó (trong file tôi đặt tên là MyClass) rồi đặt vào nó đoạn code này:
PHP:
Public WithEvents CB As CommandButton
Private Sub CB_Click()
  On Error Resume Next
  Sheets(CB.Caption).Select
End Sub
2> Trong Module
Chèn 1 Module và đặt vào nó đoạn code này:
PHP:
Public Button() As New MyClass
Sub Auto_Open()
  Dim i As Long, Obj As OLEObject, Ws As Worksheet
  For Each Ws In ThisWorkbook.Worksheets
    For Each Obj In Ws.OLEObjects
      If InStr(Obj.progID, "Forms.CommandButton") Then
        ReDim Preserve Button(i)
        Set Button(i).CB = Obj.Object
        i = i + 1
      End If
    Next Obj
  Next Ws
End Sub
Vậy là xong! Hãy chạy Auto_Open rồi nhấn nút thử
Nếu có ý định cho hiện 1 sheet duy nhất, các sheet khác ẩn thì sửa lại code trong Class Module như sau:
PHP:
Public WithEvents CB As CommandButton
Private Sub CB_Click()
  Dim Sh As Worksheet
  On Error Resume Next
  Application.ScreenUpdating = False
  Set Sh = ActiveSheet
  Sheets(CB.Caption).Visible = True
  Sheets(CB.Caption).Select
  Sh.Visible = 2
  Application.ScreenUpdating = True
End Sub
Cũng chạy Auto_Open và thử bấm các nút
Điểm mấu chốt mà ta cần ghi nhớ trong toàn bộ code chỉ có 2 đoạn:
Public WithEvents CB As CommandButton (Khai báo)

Set Button(i).CB = Obj.Object (thiết lập để chúng "bắt tay" nhau)
Không có chúng thì toàn bộ sẽ "tan rã"
------------------------------------------------------------------------------------------------
Tóm lại công việc của chúng ta chỉ là:
- Đặt 2 đoạn code vào đúng vị trí
- Đặt tên cho Class Module
- Vẽ các CommandButton và gõ tên sheet cần link vào caption của chúng
- Chạy Auto_Open để khởi động việc "thu gom"
Điểm thú vị ở đây là:
- Chỉ có các CommandButton (thuộc ActiveX Control) mới bị ảnh hưởng bởi code này (các object khác hoàn toàn không bị ảnh hưởng)
- Với các CommandButton, chỉ cái nào có caption là tên sheet mới bị ảnh hưởng bởi code này
------------------------------------------------------------------------------------------------
Xin lưu ý với các bạn rằng:
- Việc dùng CommandButton để link với các sheet không phải là mục đích chính của bài viết này (chỉ lấy ví dụ để minh họa), vì thế mà tôi đã không đặt nó vào chung với topic: Tạo nút nhấn để link đến các sheet
- Mục đích chính của bài viết này là hướng dẩn cách dùng Class Module để tự tạo 1 sự kiện người dùng
- Code này chỉ thuộc dạng cơ bản, có thể tùy biến đề áp dụng cho rất nhiều bài toán khác
------------------------------------------------------------------------------------------------
Chỉ với 1 bài viết thì chưa đủ để nói về EventClass, vậy nên rất mong các cao thủ khác cùng góp sức hoàn thiện bài viết này
 

File đính kèm

  • CmdEventClass_1.xls
    84 KB · Đọc: 575
  • CmdEventClass_2.xls
    86.5 KB · Đọc: 468
Về kỹ thuật lập trình Class các thành viên cần hiểu tốt về đối tượng. Khởi tạo, Các thành phần, Giải phóng khỏi vùng nhớ....

Bài viết cũng như ví dụ của anh Tuấn thiếu một thủ tục rất quan trọng đó là giải phóng biến đối tượng khỏi vùng nhớ. Việc này sẽ dẫn tới Windows bị chiếm dụng vùng nhớ. Anh nên bổ sung vào bài viết và vào ví dụ không thì những thành viên mới học sẽ hiểu và làm sai dẫn tới ứng dụng sau này project của họ có thể "phá sản".

Các thành viên có thể tham khảo thêm bài viết và các ví dụ trong đường dẫn dưới đây:
http://www.giaiphapexcel.com/forum/showthread.php?3868-Class-module-Kỹ-thuật-Tạo-và-Wrap-đối-lượng

Một chút góp ý với mong muốn tất cả các thành viên cùng học để nâng cao kiến thức lập trình trong Excel.
(Hình như anh không đọc những bài em đã viết về Class).
 
Lần chỉnh sửa cuối:
Upvote 0
Về kỹ thuật lập trình Class các thành viên cần hiểu tốt về đối tượng. Khởi tạo, Các thành phần, Giải phóng khỏi vùng nhớ....

Bài viết cũng như ví dụ của anh Tuấn thiếu một thủ tục rất quan trọng đó là giải phóng biến đối tượng khỏi vùng nhớ. Việc này sẽ dẫn tới Windows bị chiếm dụng vùng nhớ. Anh nên bổ sung vào bài viết và vào ví dụ không thì những thành viên mới học sẽ hiểu và làm sai dẫn tới ứng dụng sau này project của họ có thể "phá sản".

Các thành viên có thể tham khảo bài viết và các ví dụ trong đường dẫn dưới đây:
http://www.giaiphapexcel.com/forum/showthread.php?3868-Class-module-K%E1%BB%B9-thu%E1%BA%ADt-T%E1%BA%A1o-v%C3%A0-Wrap-%C4%91%E1%BB%91i-l%C6%B0%E1%BB%A3ng
(Hình như anh không đọc những bài em đã viết về Class).

Vâng! Bởi vậy tôi rất muốn các cao thủ như bạn bổ sung thêm
Có điều nên viết ở mức đơn giản nhất để "tầm thấp" như tôi có thể hiểu và áp dụng được... Có hiểu được bước đầu thì mới có khả năng tự mình tùy biến như ý muốn, đúng không?
Nói ra bạn đừng cười, chứ bài viết của bạn cho trong link trên tôi cũng từng đọc qua mà... hỏng hiểu tí nào (cũng có thể vì tôi chưa từng được đào tạo qua các trường lớp chính quy)
Hi... Hi...
------------------------
Chân thành cảm ơn sự góp ý của bạn và cũng rất mong nhận được những bài viết "ngon, bổ" nhưng "rẻ" từ bạn và các cao thủ khác
------------------------
Mình hỏi thêm: Với code trên, ta phải sửa hoặc thêm gì vào thì mới hợp lý (giải phóng đối tượng khỏi vùng nhớ như thế nào?)
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng! Bởi vậy tôi rất muốn các cao thủ như bạn bổ sung thêm
Có điều nên viết ở mức đơn giản nhất để "tầm thấp" như tôi có thể hiểu và áp dụng được... Có hiểu được bước đầu thì mới có khả năng tự mình tùy biến như ý muốn, đúng không?
Nói ra bạn đừng cười, chứ bài viết của bạn cho trong link trên tôi cũng từng đọc qua mà... hỏng hiểu tí nào (cũng có thể vì tôi chưa từng được đào tạo qua các trường lớp chính quy)
Hi... Hi...
------------------------
Chân thành cảm ơn sự góp ý của bạn và cũng rất mong nhận được những bài viết "ngon, bổ" nhưng "rẻ" từ bạn và các cao thủ khác
------------------------
Mình hỏi thêm: Với code trên, ta phải sửa hoặc thêm gì vào thì mới hợp lý (giải phóng đối tượng khỏi vùng nhớ như thế nào?)

Vì biết anh là "người truyền giáo" rất tốt nên cũng hy vọng anh giúp được rất nhiều thành viên GPE. Đúng là bài viết của em trong link trên mang tính giới thiệu như là "có một thứ như thế", anh có thể để ý về tạo và giải phóng đối tượng, dù là cơ bản nhưng cái đó không thể bỏ được anh ạ. Hy vọng bài viết này giúp ích cho nhiều người.
 
Upvote 0
1 bài tập

Gữi các bạn 1 bài tập nghiên cứu chơi
- Trên bảng tính, tôi có vài ComboBox và 1 SpinButton
- Các ComboBox này chuyên dùng để nhập các số nguyên(Number)
- Khi tôi đặt con trỏ chuột vào 1 ComboBox nào đó rồi bấm SpinButton thì giá trị trong ComboBox sẽ tăng hoặc giảm 1 đơn vị (tùy theo ta bấm SpinButton theo chiều nào)


untitled.JPG

------------------------------------
Xem như là 1 bài tập thực hành về Class Event, các bạn hãy nghiên cứu xem
 

File đính kèm

  • Combo_Text1.xls
    23 KB · Đọc: 192
Upvote 0
Em có 1 điều này nói ra hơi khó nghe nhưng không nói thì hơi ấm ức.
Đồng ý là Class làm việc này rất tốt nhưng chưa đúng với nhiệm vụ của Class lắm.
Anh cần Sub cho ComandButton thì nếu có nhiều sheet thì quả thật sẽ có nhiều code phải chép đi chép lại thật. Nhưng vẫn còn cách khác như Hyperlink hay dùng Button của Form, như 2 đoạn code sau đây cũng vậy. Nó cũng ngắn gọn và có thể áp dụng cho bao nhiêu button cũng được.
Sheet Menu:
Mã:
Private Sub CommandButton1_Click()
If ComboBox1 = "" Then Exit Sub
Sheets(ComboBox1.Value).Select
End Sub
Module:
Mã:
Sub Menu()
Sheet1.Select
End Sub
Nói cho đúng thì Class phải làm và thay đổi gì đó mà ngay cả những lệnh bình thường thì Sub phải chịu thua thì nó mới có giá trị được.
Cũng như bài tiếp theo anh bảo dùng Class nhưng vẫn có cách đơn giản hơn là dùng Sub mà.
Mã:
Public combo As Byte
 
Private Sub SpinButton1_SpinDown()
Dim obj As OLEObjects
If combo = 0 Then Exit Sub
For i = 1 To ActiveSheet.OLEObjects.Count
    If ActiveSheet.OLEObjects(i).Name = "ComboBox" & combo Then Cells(3, i) = Cells(3, i) - 1
Next
End Sub
 
Private Sub SpinButton1_SpinUp()
Dim obj As OLEObjects
If combo = 0 Then Exit Sub
For i = 1 To ActiveSheet.OLEObjects.Count
    If ActiveSheet.OLEObjects(i).Name = "ComboBox" & combo Then Cells(3, i) = Cells(3, i) + 1
Next
End Sub
 
Private Sub ComboBox1_GotFocus()
combo = 1
End Sub
 
Private Sub ComboBox2_GotFocus()
combo = 2
End Sub
 
Private Sub ComboBox3_GotFocus()
combo = 3
End Sub
Về phần đề và ý nghĩa ra đề thì hình như chưa ổn lắm.
Em thấy Class dùng để thay đổi thuộc tính như hàm Property gì đó thì hợp lý hơn.
Mã:
Property Get Names(intX As Integer, intY As Integer) As Variant
    ' Statement here.
    Names = intX + intY
End Property
Với Class thì em cũng đang tìm hiểu nhưng nó không hề giống với các hàm từ trước đến giờ. Chúng đều có cú pháp hay ví dụ gì đó để mình tìm hiểu sự thay đổi. Còn Class thì không như vậy. Nó mới và thay đổi rất kì lạ.
Cứ như là định nghĩa lại cho máy hiểu vậy?
Em nghĩ như vậy đó. Có gì mạo phạm xin lượng thứ cho. Em cũng muốn nâng cao thuật toán nhưng đến Class thì cũng hơi khó trèo qua thiệt.
Như muốn gọi 1 Class trong Module thì chỉ cần gọi tên của Class mà ta hay quên đặt là Class1, Class2 trong khung Project - VBAProject
Cách gọi thì dùng "Dim ikj As New Class1" như vậy.
Việc còn lại thì ikj.Name(3,4) vậy đó.
Module:
Mã:
Sub thu()
Dim ikj As New Class1
MsgBox ikj.Names(3, 4)
End Sub
Class:
Mã:
Property Get Names(intX As Integer, intY As Integer) As Variant
    Names = intX + intY
End Property
Khi viết xong tên biến cho Class. Mọi người thử nhập tên biến rồi chấm 1 cái sẽ thấy có 1 cái Name xuất hiện ra kế bên. Y như khi ta gọi hàm WorksheetFunction vậy đó. Đó gọi là Class đã được liên kết hoàn chỉnh và được gọi.
Giờ thì ta xây dựng lên từ đây. Và nếu có thể thì yêu cầu né né mấy cái nào có thể viết bằng Sub ra nha. Học vậy dễ bị tẩu lắm. Với lại làm giảm sự hứng thú với Class nhiều lắm. Ví dụ như những cái API hoặc Function nào quá đặc biệt và tổng quát (tức là quá dài) thì có thể đặt trong Class nhằm giúp gọi chúng ra dễ dàng hơn. Cũng dễ quản lý hơn nữa.

Tạm thời thì em chỉ mới hiểu đến đây. Từ từ bổ sung kiến thức tiếp sao nha! +-+-+-+
Thân.
 

File đính kèm

  • Combo_Text1.xls
    35 KB · Đọc: 200
  • Menu_Select.xls
    43.5 KB · Đọc: 217
Lần chỉnh sửa cuối:
Upvote 0
Khai báo cho "i" một cái nhé, sẽ không bị lỗi tại File "Combo_Text1".
 
Upvote 0
Thằng Class vẫn khủng khiếp như ngày nào. Đây là 1 đoạn code về Class tạo Dialog để mở file dạng TXT. Nhìn vào ngâm cú mà cứ như đi vào rừng già ấy. Khiếp thật nhỉ?

Nhưng nó chưa hoàn hảo đâu. Vì còn thiếu Class đọc nhiều loại Font khác nữa. Thật là mê thì có nhưng để viết được thế này thì phải học tiếp như thế nào nhỉ?
Thôi ngồi cậm cụi đọc code típ.

Nguồn: http://www.vbaccelerator.com/home/V...Dialog_Minimum_Code_zip_cCommonDialog_cls.asp

Chúc buổi tối vui vẽ nha!
 

File đính kèm

  • Dialog.rar
    60.7 KB · Đọc: 294
Lần chỉnh sửa cuối:
Upvote 0
Khai báo cho "i" một cái nhé, sẽ không bị lỗi tại File "Combo_Text1".

Tôi chạy chả có lỗi gì cả.
Lỗi hay không là do có câu Option Explicit hay không, và cái này là tuỳ thiết lập mỗi máy của mỗi người. Không thể chạy trên máy mình bị lỗi rồi kết luận được.
 
Upvote 0
Po-Pikachu đã viết:
Anh cần Sub cho ComandButton thì nếu có nhiều sheet thì quả thật sẽ có nhiều code phải chép đi chép lại thật. Nhưng vẫn còn cách khác như Hyperlink hay dùng Button của Form, như 2 đoạn code sau đây cũng vậy
Nói cho đúng thì Class phải làm và thay đổi gì đó mà ngay cả những lệnh bình thường thì Sub phải chịu thua thì nó mới có giá trị được.
Cũng như bài tiếp theo anh bảo dùng Class nhưng vẫn có cách đơn giản hơn là dùng Sub mà.

Có lẽ anhtuan muốn giới thiệu class cho mọi người tiếp cận từ dễ đến khó, từ đơn giản đến phức tạp.
Nhớ lại khi xưa, khi mình giới thiệu vòng lặp For - Next, bài đầu tiên là dùng For tính giai thừa của 1 số, trong khi Excel đã có hàm sẵn. Không phải ai cũng có thể chỉ cần đọc chăm chú vào những đoạn code làm sẵn dài ngoằng mà hiểu đâu Po à.
 
Upvote 0
Em có 1 điều này nói ra hơi khó nghe nhưng không nói thì hơi ấm ức.
.
Bạn hãy tưởng tượng thế này: Nếu có 100 ComboBox thì bạn sẽ viết code thế nào đây?
------------------
Gữi bạn 1 file ví dụ về Class Module!
Bạn hãy cho biết nếu viết bằng cách thông thường (không dùng Class) thì bạn sẽ viết thế nào?
 

File đính kèm

  • ColorPicker_Class.xls
    57.5 KB · Đọc: 185
Lần chỉnh sửa cuối:
Upvote 0
Thằng Class vẫn khủng khiếp như ngày nào. Đây là 1 đoạn code về Class tạo Dialog để mở file dạng TXT. Nhìn vào ngâm cú mà cứ như đi vào rừng già ấy. Khiếp thật nhỉ?

Nhưng nó chưa hoàn hảo đâu. Vì còn thiếu Class đọc nhiều loại Font khác nữa. Thật là mê thì có nhưng để viết được thế này thì phải học tiếp như thế nào nhỉ?
Thôi ngồi cậm cụi đọc code típ.

Nguồn: http://www.vbaccelerator.com/home/V...Dialog_Minimum_Code_zip_cCommonDialog_cls.asp

Chúc buổi tối vui vẽ nha!

Lập trình Class Module không hề khó đâu bạn. Về kỹ thuật của chỉ vài cái thôi: Property Get, Let; WithEvents...
Lập trình Class Module để tạo ra một đối tượng, đối tượng này để làm một việc gì đó. Các bạn vẫn dùng Range("A1").Value để gán giá trị hay RANGE("A1").Formula để gán công thức...Range là một Class làm việc với Cell trong Worksheet đó bạn à.
Lập trình Class Module để chúng ta tiếp cận lập trình .NET. Lập trình .NET tất cả đều là Class chứ không phải dạng viết thủ tục bình thường.
Độ khó của Class Module là do nghiệp vụ của nó mà thôi, ví dụ bạn viết class để tính 1 + 1 = 2, hay viết class để tính hàm tối ưu f(x) = 10 + 4x1 + 5 X2 - 7X3 => Min.

File "Dialog" bạn gửi là người ta dùng các hàm Windows API để lập trình, với dân lập trình API thì mấy cái đó không có gì khó cả vì nó mới chỉ là khai báo kiểu dữ liệu rồi lắp vào hàm API của Windows là xong thôi chứ chưa phải luồn các ngóc ngách gì.

Để học Class căn bản các bạn tạm đừng xem code từ các trang nước ngoài như vbaccelerator rồi để mà sợ, vì nó là ứng dụng nhỏ hoàn chỉnh. Họ không phải viết để học class. Nó dành cho những nhà phát triển, mà những nhà phát triển thì Class đương nhiên ai cũng hiểu rồi. Nó giống như đi học tiếng Anh, mới đi học bạn đã vào lớp bằng C rồi thì sao mà học được.

Tôi chắc chắn rằng, những ai đã biết lập trình VBA (không phải chuyên gia) thì cũng sẽ biết lập trình Class Module vì nó không khó, nó là một dạng lập trình đối tượng các bạn chịu khó đọc tài liệu học về nó là được.
Đừng nhìn kêu khó mà phải tìm hiểu nó thực sự đã!
 
Lần chỉnh sửa cuối:
Upvote 0
Chuyện gì mới thì cũng khó bác ah. Thôi làm quen dần dần tới khi nào rành rồi thì lại thấy mấy bài viết hôm nay thật ngớ ngẩn. hihi :D
Nếu nhiều commandbutton thì em sẽ dùng đến "frmClr.ActiveControl.Name" thằng này dùng cũng được đó. Nhưng phải có lệnh kích hoạt nó.
Để tự động thì em kèm vào sự kiện UserForm_MouseMove(..).
Các code sau khi hình thành thì sẽ như sau:
Mã:
Private Sub NoColor_Click()
  frmClr.Sample.BackStyle = 0
End Sub
 
Private Sub UserForm_Initialize()
  Dim Cmd As Control, iColor, i As Long
  iColor = Array(1, 53, 52, 51, 49, 11, 55, 56, 9, 46, 12, 10, 14, 5, _
                 47, 16, 3, 45, 43, 50, 42, 41, 13, 48, 7, 44, 6, 4, _
                 8, 33, 54, 15, 38, 40, 36, 35, 34, 37, 39, 2, 17, 18, _
                 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
  For Each Cmd In frmClr.Controls
    If Cmd.Tag = "ColorCB" Then
      Cmd.BackColor = ThisWorkbook.Colors(iColor(i))
      i = i + 1
    End If
  Next Cmd
End Sub
Private Sub cmdExit_Click()
  Unload Me
End Sub
 
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
frmClr.Sample.BackColor = frmClr.Controls(frmClr.ActiveControl.Name).BackColor
End Sub
Ah quên, dùng thằng ActiveControl thì không thể có Frame được. Vì nó sẽ đọc thấy cái Frame chứ không thấy Command.
Bác nói là can thiệp cell trên bảng tính được. Vậy nếu em cần thay đổi màu Cell theo giá trị của nó thì sao?
Tức là nếu ô [C3]=3 hoặc bằng 4,v.v.v... thì màu của ô này ([C3].InteriorColorIndex) bằng đúng giá trị tại ô đó luôn.
Thì viết Class chuyển màu thế nào hả bác?
Giống như vầy nè. Nhưng không dựa vào hàm thời gian hay kích hoạt Select từ bên ngoài.
Thân.
 

File đính kèm

  • Time_Color.xls
    29 KB · Đọc: 84
  • ColorPicker_Class.xls
    56 KB · Đọc: 86
Lần chỉnh sửa cuối:
Upvote 0
Chuyện gì mới thì cũng khó bác ah. Thôi làm quen dần dần tới khi nào rành rồi thì lại thấy mấy bài viết hôm nay thật ngớ ngẩn. hihi :D
Nếu nhiều commandbutton thì em sẽ dùng đến "frmClr.ActiveControl.Name" thằng này dùng cũng được đó. Nhưng phải có lệnh kích hoạt nó.
Để tự động thì em kèm vào sự kiện UserForm_MouseMove(..).
Các code sau khi hình thành thì sẽ như sau:
Mã:
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
frmClr.Sample.BackColor = frmClr.Controls(frmClr.ActiveControl.Name).BackColor
End Sub
Ah quên, dùng thằng ActiveControl thì không thể có Frame được. Vì nó sẽ đọc thấy cái Frame chứ không thấy Command.
Bác nói là can thiệp cell trên bảng tính được. Vậy nếu em cần thay đổi màu Cell theo giá trị của nó thì sao?
Tức là nếu ô [C3]=3 hoặc bằng 4,v.v.v... thì màu của ô này ([C3].InteriorColorIndex) bằng đúng giá trị tại ô đó luôn.
Thì viết Class chuyển màu thế nào hả bác?
Giống như vầy nè. Nhưng không dựa vào hàm thời gian hay kích hoạt Select từ bên ngoài.
Thân.
Bạn xem lại đi! Nó hoạt động đâu có giống cái tôi đã gữi!
Ý tôi không phải bảo bạn giải quyết bài toán này (vì có nhiều cách) mà muốn nhấn mạnh với bạn rằng: "Trong 1 số trường hợp cụ thể nào đó, nếu không dùng Class thì sẽ tự mình gây khó khăn cho mình... Trong khi với Class, ta giải quyết nhanh gọn"
Với bài này, nếu không dùng Class mà bạn làm được y chang như file tôi gữi thì.... Hi... hi...
------------------------------------
Nhắc lại: Các bạn hãy xem bài số #5 như là 1 bài tập và hãy giải quyết nó bằng cách dùng Class Module nhé
 
Lần chỉnh sửa cuối:
Upvote 0
File ColorPicker_Class.xls chạy được mà. Em đã thử và thấy nó chạy đó thôi. Sự kiện MoveMouse hơi chậm hơn dùng Class thiệt. Không tin thì thử khoá dòng "frmClr.Sample.BackColor = frmClr.Controls(frmClr.ActiveControl.Name).BackColor" trong Form thử xem. Nó sẽ Break liền đó.

Em thử bài tập 2 bằng Class như sau nó không nhận nhỉ? Em hiểu sai ở chổ nào vậy? Giải thích cụ thể được không?
Thân.
 

File đính kèm

  • Combo_Text1.xls
    37 KB · Đọc: 42
Upvote 0
ColorPicker - Chọn màu từ Userform

Bạn hãy tưởng tượng thế này: Nếu có 100 ComboBox thì bạn sẽ viết code thế nào đây?
------------------
Gữi bạn 1 file ví dụ về Class Module!
Bạn hãy cho biết nếu viết bằng cách thông thường (không dùng Class) thì bạn sẽ viết thế nào?

Từ file gốc của bác anhtuan1066 tôi nâng cấp thêm như sau:
+ Khi mở form, tự nhận màu trong vùng lựa chọn cho nút bám và cửa sổ "Sample"
+ Khi di chuột trên các nút màu, vùng lựa chọn và cửa sổ Sample tạm nhận màu luôn. Chỉ nhận chính thức khi nhấn chuột vào nút đó, giống như Office 2007.
+ Code trong Class sửa lại để phù hợp với nâng cấp.

File này ngoài mục đích ứng dụng, tôi muốn nhấn mạnh vai trò của việc dùng Class Module.
 

File đính kèm

  • ColorPicker.rar
    21.8 KB · Đọc: 178
Upvote 0
File ColorPicker_Class.xls chạy được mà. Em đã thử và thấy nó chạy đó thôi. Sự kiện MoveMouse hơi chậm hơn dùng Class thiệt. Không tin thì thử khoá dòng "frmClr.Sample.BackColor = frmClr.Controls(frmClr.ActiveControl.Name).BackColor" trong Form thử xem. Nó sẽ Break liền đó..
Tôi đâu có nói là chạy không được!
Tôi nói nó chạy không giống!
Hình như bạn chưa hiểu ý tôi thì phải
???
Trong 1 số trường hợp cụ thể nào đó, nếu không dùng Class thì sẽ tự mình gây khó khăn cho mình... Trong khi với Class, ta giải quyết nhanh gọn"
Nếu bắt buộc phải làm GIỐNG Y CHANG với file của tôi thì bạn làm sao?

Em thử bài tập 2 bằng Class như sau nó không nhận nhỉ? Em hiểu sai ở chổ nào vậy? Giải thích cụ thể được không?
Thân.
Nghiên cứu tiếp đi
- Sao lại cho code vào sự kiện Workbook_SheetSelectionChange nhỉ? Lý ra bạn phải cho vào Auto_Open để tự kích hoạt nó chứ
- Bạn viết Public WithEvents CB As ComboBox thì CB làm gì có sự kiện GotFocus ?? Có chăng là dùng MouseUp
- Khi đặt con trỏ vào Combo, hãy Set Combo mà ta thu gom chính = với Combo trong Class
 
Upvote 0
Em thử bài tập 2 bằng Class như sau nó không nhận nhỉ? Em hiểu sai ở chổ nào vậy? Giải thích cụ thể được không?
Thân.
Mình gợi ý thế này:
1> Trong Class Module
PHP:
Public WithEvents CB As ComboBox
Private Sub CB_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  Set Cbo = CB
End Sub
2> Trong Module
PHP:
Public Combo() As New Class1, Cbo As ComboBox
Sub Auto_Open()
  Dim i As Long, Obj As OLEObject
  For Each Obj In ActiveSheet.OLEObjects
    If TypeOf Obj.Object Is ComboBox Then
      ReDim Preserve Combo(i)
      Set Combo(i).CB = Obj.Object
      i = i + 1
    End If
  Next
End Sub
Phần còn lại để điểu khiển SpinButton bạn tự làm nhé! Chỉ là Cbo.Value = Val(Cbo.Value) + 1 (hoặc -1) thôi
 
Upvote 0
Nếu bắt buộc phải làm GIỐNG Y CHANG với file của tôi thì bạn làm sao?


Nghiên cứu tiếp đi
- Sao lại cho code vào sự kiện Workbook_SheetSelectionChange nhỉ? Lý ra bạn phải cho vào Auto_Open để tự kích hoạt nó chứ
- Bạn viết Public WithEvents CB As ComboBox thì CB làm gì có sự kiện GotFocus ?? Có chăng là dùng MouseUp
- Khi đặt con trỏ vào Combo, hãy Set Combo mà ta thu gom chính = với Combo trong Class

Giờ em chẳng biết phải làm sao nữa rùi. Thôi quay lại hỏi vài cái chưa biết cái đã.
Khi nào thông rồi chắc chắn nó sẽ ra thôi.
Trường PrevInterior dùng để nạp dữ liệu vào đâu vậy?
Sao em không thấy nó bên Class vậy?
Còn khi nhấn vào No Color thì Sample im re luôn. Có MouseMove cũng không được nữa. Vậy phải khắc phục sao nhỉ?
Sau khi bỏ bớt vài thứ chẳng hiểu để làm gì thì code chạy như sau:
+Nạp màu lên Button dựa trên ArraryColor.
+Tự chọn màu khi chuột chạy hiện cả trên Form và trên Selection. Nếu Click chọn 1 màu thì nó sẽ ngừng trên Selection.
+Nạp lại chế độ NoColor cho Sample.
Thân.
 

File đính kèm

  • ColorPicker.rar
    20.9 KB · Đọc: 72
Lần chỉnh sửa cuối:
Upvote 0
Giờ em chẳng biết phải làm sao nữa rùi. Thôi quay lại hỏi vài cái chưa biết cái đã.
Khi nào thông rồi chắc chắn nó sẽ ra thôi.
Trường PrevInterior dùng để nạp dữ liệu vào đâu vậy?
Sao em không thấy nó bên Class vậy?
Còn khi nhấn vào No Color thì Sample im re luôn. Có MouseMove cũng không được nữa. Vậy phải khắc phục sao nhỉ?
hân.
Nếu là tôi thì tôi làm vầy
1> Trong Class Module
PHP:
Public WithEvents CB As CommandButton
Private Sub CB_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  frmClr.Sample.BackColor = CB.BackColor
  frmClr.Sample.BackStyle = 1
  Selection.Interior.Color = CB.BackColor
End Sub
2> Trong Form
PHP:
Dim Buttons() As New MyClass, CllColor As Long
PHP:
Private Sub NoColor_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  frmClr.Sample.BackStyle = 0
End Sub
PHP:
Private Sub UserForm_Initialize()
  Dim Cmd As Control, iColor, i As Long
  On Error Resume Next
  CllColor = Selection(1, 1).Interior.Color
  iColor = Array(1, 53, 52, 51, 49, 11, 55, 56, 9, 46, 12, 10, 14, 5, _
                 47, 16, 3, 45, 43, 50, 42, 41, 13, 48, 7, 44, 6, 4, _
                 8, 33, 54, 15, 38, 40, 36, 35, 34, 37, 39, 2, 17, 18, _
                 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
  For Each Cmd In frmClr.Patt.Controls
    If Cmd.Tag = "ColorCB" Then
      Cmd.BackColor = ThisWorkbook.Colors(iColor(i))
      ReDim Preserve Buttons(i)
      Set Buttons(i).CB = Cmd
      i = i + 1
    End If
  Next Cmd
  frmClr.Sample.BackColor = CllColor
End Sub
Lưu ý: Code của Nguyễn Duy Tuân vẫn bị 1 lỗi khi vùng Selection có chứa 2 màu đấy nhé
 

File đính kèm

  • Test.xls
    61 KB · Đọc: 87
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom