[UserForm]TreeView-Completed

Euler

Mod
Thành viên BQT
Topic này tôi sẽ thuyết minh về TreeView. Trên diễn đàn đã có một topic về . Tuy nhiên việc tìm hiểu code hiện nay vẫn còn hạn chế.
Lần này tôi sẽ giới thiệu về TreeView có sẵn trong thư viện của Excel.
Bạn cần đăng nhập để thấy đính kèm


TreeView Control có thể được sử dụng từ Office 2000 trở lên.
Tuy nhiên đây không phải là control tiêu chuẩn của Excel. Tức là tùy vào từng máy tính mà control này có hoặc không. Vì vậy các bạn cần lưu ý khi chia sẻ qua internet hoặc thậm chí trong nội bộ công ty, các máy tính có môi trường khác nhau dẫn tới có máy tính dùng được hoặc không dùng được.
Tôi hi vọng chúng ta sẽ thảo luận sâu hơn về vấn đề này (làm thế nào để các máy tính khác cũng sử dụng được) sau khi topic này được tôi trình bày xong.

Chúng tôi đã nghĩ rằng TreeView chỉ có trên Office 32bit. Tuy nhiên tôi kiểm tra và thấy rằng trên máy tính của tôi Office 2016 64bit có control tree view. Vì vậy mà tôi bắt đầu topic này.

1.
2.
3.
4.
5.
6.
7.
 

vbano1

SMod
Thành viên BQT
1. Lấy control TreeView ở đâu?
Trên ToolBox, bạn click chuột phải và chọn Additional Controls...
Bạn cần đăng nhập để thấy đính kèm


-Tìm Microsoft TreeView Control và tích chọn, ấn OK
Bạn cần đăng nhập để thấy đính kèm


-Tìm Microsoft ImageList Control và tích chọn, ấn OK.
Bạn cần đăng nhập để thấy đính kèm

Kết quả:
Bạn cần đăng nhập để thấy đính kèm


Chú ý, một số máy tính có thể không tìm thấy TreeView Control hay ImageList Control. Về vấn đề này, chúng ta sẽ bàn cách khắc phục sau khi topic này được trình bày xong mục 7.
//Hình ảnh bài viết do BTV Euler cung cấp.
Nguồn tham khảo :
 

Euler

Mod
Thành viên BQT
2. Bài trí control TreeView như thế nào?
Sau khi đã có các biểu tượng TreeViewImageList trên Toolbox, bạn chỉ cần click vào chúng rồi vẽ trên UserForm.
Đối với ImageList, thực tế nó không hiển thị trên UserForm, cho nên bạn đặt ở đâu trên UserForm cũng không sao hết.
Bạn cần đăng nhập để thấy hình ảnh

Bạn cần đăng nhập để thấy đính kèm

3. Chuẩn bị ImageList Control
Bước này, ta cần nạp hình ảnh vào ImageList.
-Về hinh ảnh, các bạn hãy save hai bức ảnh sau vào máy tính của các bạn.
Bạn cần đăng nhập để thấy hình ảnh

Bạn cần đăng nhập để thấy hình ảnh

lưu tên chúng lần lượt là book.jpgsheet.jpg, lưu cùng thư mục với file excel macro của các bạn.
Theo như hướng dẫn , thì các bạn có thể click chuột phải vào ImageList1, chọn property, ở đây các bạn vào property page để upload ảnh cho ImageList.
Bạn cần đăng nhập để thấy hình ảnh

Tuy nhiên thực tế trên máy tính của tôi, tôi không thấy chỗ nào để load ảnh vào ImageList.
Bạn cần đăng nhập để thấy hình ảnh


Vì vậy tôi sẽ can thiệp bằng code như sau:
Mã:
Private Sub UserForm_Initialize()
    Dim imgB, imgS As Object
    
    With ImageList1
        Set imgB = .ListImages.Add(1, "book", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "excel.jpg"))
        Set imgS = .ListImages.Add(2, "sheet", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "sheet.jpg"))
        
    End With
End Sub
Tôi giải thích về code trên:
Bạn cần đăng nhập để thấy đính kèm

Như vậy bước chuẩn bị của chúng ta đã xong.
Nguồn tham khảo:
 

giaiphapvba

Administrator
Thành viên BQT
4. Khởi tạo TreeView Control:
Ta cập nhật lại code của Private Sub UserForm_Initialize() :

Mã:
Private Sub UserForm_Initialize()
    Dim imgB, imgS
    
    With ImageList1
        Set imgB = .ListImages.Add(1, "book", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "excel.jpg"))
        Set imgS = .ListImages.Add(2, "sheet", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "sheet.jpg"))
        
    End With
    With TreeView1
        .Indentation = 14           ''Be ngang cua Indentation
        .LabelEdit = tvwManual     ''Cho phep Edit Label : tvwManual/tvwAutomatic
        .BorderStyle = ccNone       ''Type Line
        .HideSelection = False      ''Bo chon khi khong hoat dong
        .LineStyle = tvwRootLines  ''Hien thi Line cua Root: tvwRootLines
        .ImageList = ImageList1     ''Khoi tao ImageList
    End With
End Sub
Các dòng code 9,16 là các dòng lần này chúng ta thêm mới.
Ở đây chúng tôi lý giải hai tham số: LineStyle,Indentation như hình so sánh dưới đây.
Bạn cần đăng nhập để thấy đính kèm


Các tham số khác, chúng tôi muốn nhận được tương tác của các bạn lý giải giúp chúng tôi theo cách diễn giải sử dụng hình ảnh so sánh như ở trên.
Dưới đây là các tham số cần các bạn lý giải:

Mã:
        .LabelEdit = tvwManual     ''Cho phep Edit Label : tvwManual/tvwAutomatic
        .BorderStyle = ccFixedSingle      ''Type Line : ccNone/ccFixedSingle
        .HideSelection = False      ''Bo chon khi khong hoat dong : False/True
Mong nhận được chung sức đồng lòng từ các bạn. Hãy tương tác trực tiếp trong topic này. Chúng tôi sẽ dừng không cập nhật các phần tiếp theo trong 1 tuần để chờ các phản hồi của các bạn.
Nguồn tham khảo:
Hình ảnh bài viết do BTV Euler cung cấp.
 

Yukino Ichikawa

Thành viên
4. Khởi tạo TreeView Control:

Dưới đây là các tham số cần các bạn lý giải:

Mã:
        .LabelEdit = tvwManual     ''Cho phep Edit Label : tvwManual/tvwAutomatic
        .BorderStyle = ccFixedSingle      ''Type Line : ccNone/ccFixedSingle
        .HideSelection = False      ''Bo chon khi khong hoat dong : False/True
Em xin đóng góp ý kiến giải thích thuộc tính HideSelection:
Nếu thiết định là Flase, nếu anh/chị đang chọn vào một item nào đó trên TreeView, thì nó vẫn lưu lại ngay cả khi anh chị rời khỏi TreeView.
Nếu thiết định là True, nếu anh/ chị đang chọn vào một item nào đó trên TreeView, thì nó sẽ bị mất đi khi anh chị rời khỏi TreeView.

Ví dụ em đạng chọn vào VBA Excel. Lúc này em ấn nút bấm trên UserForm để hiện thông báo "OK", anh chị quan sát trên TreeView, cụ thể là mục VBA Excel, không còn dấu vết nào thể hiện là em đã chọn vào đây. Đây là trường hợp em thiết định :
Mã:
.HideSelection = True
Trong trường hợp em thiết định:
Mã:
.HideSelection = False
Anh chị thấy rằng dấu vết em đã chọn vào VBA Excel trên TreeView vẫn còn, nó có màu nền xám nhạt.
Bạn cần đăng nhập để thấy hình ảnh


Cụ thể:
Bạn cần đăng nhập để thấy hình ảnh


Không chỉ là khi click vào nút bấm trên UserForm. Khi em đang chọn vào một mục trên TreeView, em mở phần mềm Snipping Tool lên để chụp ảnh màn hình thì dấu tích em đã chọn trên TreeView cũng bị biến mất nếu thiết định thuộc tính này là True.
Bài viết được tham khảo từ:
 

vanthanhVBA

Thành viên
5. Tạo Node
Để tạo Node, ta sẽ sử dụng phương thức Add của Nodes Collection.
Cấu trúc:
TreeView.Nodes.Add [Relative], [Relationship], [Key], [Text], [Image], [SelectedImage]
Bạn cần đăng nhập để thấy hình ảnh

Tham số Relative: Khi sử dụng phương thức Add để đăng ký Node mới, ta cần chỉ định Node đó sẽ là Node Mẹ hay là Node Con.
Ví dụ, ở hình dưới đây, Node Mẹ là [HoTen]. Node Con là [TuHocVBA]. Ngoài ra [TuHocVBA] lại là Node Mẹ của các Node Con [SoThich], [Level].
Sau đây, sẽ là cách để chúng ta đăng ký các Node theo mối quan hệ như trên:

TreeView.Nodes.Add "HoTen", [Relationship], [Key], "TuHocVBA", [Image], [SelectedImage]
TreeView.Nodes.Add "TuHocVBA", [Relationship], [Key], "SoThich", [Image], [SelectedImage]
TreeView.Nodes.Add "TuHocVBA", [Relationship], [Key], "Level", [Image], [SelectedImage]

Ngoài ra, Node [DiaChi] không có mối quan hệ mẹ con với Node [HoTen], ta sẽ giản lược tham số Relative.

TreeView.Nodes.Add , [Relationship], [Key], "HoTen", [Image], [SelectedImage]
TreeView.Nodes.Add , [Relationship], [Key], "DiaChi", [Image], [SelectedImage]

Như bạn có thể nhìn thấy từ code này, chuỗi ký tự được chỉ định cho tham số Text sẽ hiển thị ra bên ngoài TreeView cho người dùng nhìn thấy.
Điều phải chú ý ở đây là, tham số Relative mà bạn chỉ định, đó không phải là chuỗi ký tự của tham số Text, mà là chuỗi ký tự được chỉ định cho tham số Key.
Tham số Text là chuỗi ký tự hiển thị tên Node ra bên ngoài cho người dùng thấy, do đó các node có tham số Text giống nhau là điều hoàn toàn có thể. Nhưng để quản lý các Node, mỗi Node cần có một mã định danh để phân biệt được với các Node khác, thì ta cần có tham số Key, tương tự như mã chứng minh nhân dân, nó là duy nhất, không được trùng nhau. Do đó, ta sẽ dùng tên dùng cho tham số Key để sử dụng cho tham số Relative.

Đầu tiên, ta sẽ đăng ký hai Node Mẹ là HoTenDiaChi. Hãy chú ý nhìn vào tham số Key.
TreeView.Nodes.Add , [Relationship], "_HoTen", "HoTen", [Image], [SelectedImage]
TreeView.Nodes.Add , [Relationship], "_DiaChi", "DiaChi", [Image], [SelectedImage]

Tham số Key ở trên ta chỉ định là [_HoTen], thực ra không có ý nghĩa gì cao siêu cả. Ở đây ta viết tiếng việt, nếu dùng tiếng anh thì bạn cũng lưu ý rằng, chúng ta không nên dùng Key là [Name] mà nên viết là [_Name] để tránh trùng với các từ khóa của VBA. Vì vậy thông thường có một luật bất thành văn khi viết code, tham số Key thường được viết thêm bằng một dấu gạch nối "_".

Bây giờ ta sẽ đăng ký các Node con là [TuHocVBA], [SoThich], [Level].
TreeView.Nodes.Add "_HoTen", [Relationship], "thvba", "TuHocVBA", [Image], [SelectedImage]
TreeView.Nodes.Add "thvba", [Relationship], , "SoThich", [Image], [SelectedImage]
TreeView.Nodes.Add "thvba", [Relationship], , "Level", [Image], [SelectedImage]

Ở đây, hai node là [SoThich] và [Level] không phải là Node mẹ, cho nên tham số Key có thể được giản lược đi. Bạn có thể chỉ định tham số Key cho tất cả các Node trong TreeView, nhưng lưu ý là các Key là duy nhất, không được trùng nhau. Nếu không chú ý điều này thì phương thức Add (khi chỉ định tham số Key mà lại là Key trùng nhau) sẽ xảy ra lỗi.
Khi đăng ký Node con, cần chú ý là không được quên tham số Relationship (cấp bậc). Khi đăng ký node con, thì tham số Relationship sẽ được chỉ định bởi hằng số tvwChild (Con).

TreeView.Nodes.Add , , "_HoTen", "HoTen", [Image], [SelectedImage] 'Key, Text
TreeView.Nodes.Add , , "_DiaChi", "DiaChi", [Image], [SelectedImage] 'Key, Text
TreeView.Nodes.Add "_HoTen", tvwChild, "thvba", "TuHocVBA", [Image], [SelectedImage] 'Relative, Relationship, Key, Text
TreeView.Nodes.Add "thvba", tvwChild, , "SoThich", [Image], [SelectedImage] 'Relative, Relationship, Key, Text
TreeView.Nodes.Add "thvba", tvwChild, , "Level", [Image], [SelectedImage] 'Relative, Relationship, Key, Text

tvwChild là một hằng số cho nên khi viết ta không dùng dấy nháy nháy "".

Chúng ta còn các tham số ImageSelectedImage.
Tham số Image: Chúng ta chỉ định Icon (biểu tượng) cho trạng thái Node không được chọn (UnSelect).
Tham số SelectedImage: Chỉ định Icon (biểu tượng) cho trạng thái Node được chọn (select).
Trên Windows ta thường thấy điều này, ví dụ khi bạn click vào Folder, Folder được mở ra thì trạng thái icon của Folder đó sẽ được thay đổi đúng không nào. Như vậy, Folder chưa được mở thì Icon của nó là tham số Image. Folder đã được mở thì Icon của nó là tham số SelectedImage. Lần này trong code của chúng ta, ta không chỉ định tham số SelectedImage nhưng cách dùng thì tương tự như tham số Image.

Để chỉ định tham số Image, ta dùng ảnh đã đăng ký trên ImageList Control. Hãy nhớ lại, , từng bức ảnh được chúng ta chỉ định bằng Key. Và bây giờ, để chỉ định cho tham số Image, ta sẽ dùng cái tên Key đó để chỉ định bức ảnh icon mà ta muốn hiển thị.
Các Node [HoTen], [DiaChi] sẽ dùng key là [book], node [TuHocVBA] sẽ dùng key là [sheet].

TreeView.Nodes.Add , , "_HoTen", "HoTen", "book"
TreeView.Nodes.Add , , "_DiaChi", "DiaChi", "book"
TreeView.Nodes.Add "_HoTen", tvwChild, "thvba", "TuHocVBA", "sheet"
TreeView.Nodes.Add "thvba", tvwChild, , "SoThich"
TreeView.Nodes.Add "thvba", tvwChild, , "Level"
Bạn cần đăng nhập để thấy hình ảnh
Các Node [SoThich], [Level] không được chỉ định tham số Image. Vì vậy khi hiển thị nó có một khoảng trống ở bên trái. Việc này có thể giải quyết bằng hàm API nhưng điều đó là không cần thiết. Khi thiết kế TreeView, bạn nên để hiển thị Icon một cách đầy đủ cho tất cả các Node, để danh sách hiển thị đồng đều và đẹp mắt.

Phương thức Add như trên thật là nhiều tham số, viết code thật là rắc rối. Để ngắn gọn, chúng ta có thể viết như dưới đây:
With TreeView1.Nodes
.Add Key:="_HoTen", Text:="HoTen", Image:="book"
.Add Key:="_DiaChi", Text:="DiaChi", Image:="book"
.Add Relative:="_HoTen", Relationship:=tvwChild, Key:="thvba", Text:="TuHocVBA", Image:="sheet"
.Add Relative:="thvba", Relationship:=tvwChild, Text:="SoThich"
.Add Relative:="thvba", Relationship:=tvwChild, Text:="Level"
End With

Bạn hãy thử copy code trên và chạy thử nhé. Trên UserForm ta sẽ đặt một nút bấm là CommandButton1. Khi Click vào nút bấm thì sẽ tạo ra các Node.
Mã:
Private Sub CommandButton1_Click()
    With TreeView1.Nodes
        .Add Key:="_HoTen", Text:="HoTen", Image:="book"
        .Add Key:="_DiaChi", Text:="DiaChi", Image:="book"
        .Add Relative:="_HoTen", Relationship:=tvwChild, Key:="thvba", Text:="TuHocVBA", Image:="sheet"
        .Add Relative:="thvba", Relationship:=tvwChild, Text:="SoThich"
        .Add Relative:="thvba", Relationship:=tvwChild, Text:="Level"
    End With
End Sub
File demo:
Nguồn tham khảo:
 

Yukino Ichikawa

Thành viên
Để luyện tập tạo Node, mọi người luyện tập các bài tập dưới đây nhé.
Bạn cần đăng nhập để thấy hình ảnh

Bạn cần đăng nhập để thấy hình ảnh
Bạn cần đăng nhập để thấy hình ảnh
 

vanthanhVBA

Thành viên
Lời giải bài tập 1:
Bạn cần đăng nhập để thấy hình ảnh

Lời giải bài tập 1:
Private Sub CommandButton1_Click()
    With TreeView1.Nodes
        .Clear
        .Add Key:="_Lop1A", Text:="Lop 1A", Image:="book"

        .Add Key:="_Lop1B", Text:="Lop 1B", Image:="book"

        .Add Relative:="_Lop1A", Relationship:=tvwChild, Key:="to1a", Text:="To 1", Image:="sheet"

        .Add Relative:="_Lop1A", Relationship:=tvwChild, Key:="to2a", Text:="To 2", Image:="sheet"

        .Add Relative:="_Lop1B", Relationship:=tvwChild, Key:="to1b", Text:="To 1", Image:="sheet"
        .Add Relative:="_Lop1B", Relationship:=tvwChild, Key:="to2b", Text:="To 2", Image:="sheet"

    End With
End Sub
Lời giải bài tập 2:
Bạn cần đăng nhập để thấy hình ảnh

Lời giải bài tập 2:
Private Sub CommandButton2_Click()
    With TreeView1.Nodes
        .Clear
        .Add Key:="_Khoi1", Text:="Khoi 1", Image:="book"

        .Add Key:="_Khoi2", Text:="Khoi 2", Image:="book"

        .Add Relative:="_Khoi1", Relationship:=tvwChild, Key:="_Lop1A", Text:="Lop 1A", Image:="sheet"
        .Add Relative:="_Khoi1", Relationship:=tvwChild, Key:="_Lop1B", Text:="Lop 1B", Image:="sheet"


        .Add Relative:="_Khoi2", Relationship:=tvwChild, Key:="_Lop2A", Text:="Lop 2A", Image:="sheet"
        .Add Relative:="_Khoi2", Relationship:=tvwChild, Key:="_Lop2B", Text:="Lop 2B", Image:="sheet"

        .Add Relative:="_Lop1A", Relationship:=tvwChild, Key:="_Lop1ATo1", Text:="To 1", Image:="sheet"
        .Add Relative:="_Lop1A", Relationship:=tvwChild, Key:="_Lop1ATo2", Text:="To 2", Image:="sheet"
        
        .Add Relative:="_Lop1B", Relationship:=tvwChild, Key:="_Lop1BTo1", Text:="To 1", Image:="sheet"
        .Add Relative:="_Lop1B", Relationship:=tvwChild, Key:="_Lop1BTo2", Text:="To 2", Image:="sheet"
        
        .Add Relative:="_Lop2A", Relationship:=tvwChild, Key:="_Lop2ATo1", Text:="To 1", Image:="sheet"
        .Add Relative:="_Lop2A", Relationship:=tvwChild, Key:="_Lop2ATo2", Text:="To 2", Image:="sheet"
        
        .Add Relative:="_Lop2B", Relationship:=tvwChild, Key:="_Lop2BTo1", Text:="To 1", Image:="sheet"
        .Add Relative:="_Lop2B", Relationship:=tvwChild, Key:="_Lop2BTo2", Text:="To 2", Image:="sheet"
    End With
End Sub
 

vbano1

SMod
Thành viên BQT
Lời giải bài tập 3:
Bài tập 3 không khó nhưng dài, nên tôi xin phép đưa ra một phần lời giải.
Bạn cần đăng nhập để thấy hình ảnh


Mã:
Private Sub CommandButton3_Click()
    With TreeView1.Nodes
        .Clear
        .Add Key:="_File1", Text:="File 1", Image:="book"
        .Add Key:="_File2", Text:="File 2", Image:="book"
        
        .Add Relative:="_File1", Relationship:=tvwChild, Key:="_File1Sheet1", Text:="Sheet 1", Image:="sheet"
        .Add Relative:="_File1", Relationship:=tvwChild, Key:="_File1Sheet2", Text:="Sheet 2", Image:="sheet"
        
        .Add Relative:="_File2", Relationship:=tvwChild, Key:="_File2Sheet1B", Text:="Sheet 1B", Image:="sheet"
        .Add Relative:="_File2", Relationship:=tvwChild, Key:="_File2Sheet2B", Text:="Sheet 2B", Image:="sheet"
        
        .Add Relative:="_File1Sheet1", Relationship:=tvwChild, Key:="_File1Sheet1Range1", Text:="Range 1", Image:="sheet"
        .Add Relative:="_File1Sheet1", Relationship:=tvwChild, Key:="_File1Sheet1Range2", Text:="Range 2", Image:="sheet"
        
        .Add Relative:="_File1Sheet1Range1", Relationship:=tvwChild, Key:="_File1Sheet1Range1Cell1", Text:="Cells 1", Image:="sheet"
        .Add Relative:="_File1Sheet1Range1", Relationship:=tvwChild, Key:="_File1Sheet1Range1Cell2", Text:="Cells 2", Image:="sheet"
    End With
End Sub
Tổng kết phần tạo node:
Các bạn nên chỉ định key cho mỗi node, chú ý key phải mang tính duy nhất, không trùng lặp.
Các Node đầu tiên là những Node không có cha mẹ, cấu trúc tạo Node sẽ có dạng:
Mã:
.Add Key:="_Khoi1", Text:="Khoi 1", Image:="book"
Nó không có từ khóa quan hệ nào hết, chỉ có key, tên hiển thị (text), hình ảnh hiển thị (image).​

Một Node B là con của Node A thì cách tạo như sau:
Mã:
.Add Relative:="_KeyNodeA", Relationship:=tvwChild, Key:="_KeyNodeB", Text:="NodeBName", Image:="sheet"
Cả hai từ khóa quan hệ đều xuất hiện, là con của ai (Relative), xác định quan hệ là con (Relationship), và ba từ khóa cơ bản: Key, Text, Image.​
 

vanthanhVBA

Thành viên
6. Thao tác với control TreeView
Khi chúng ta select vào một Node, làm thế nào để xác định được Node đang được select?

Đầu tiên, chúng ta có một sự kiện khi click vào một Node.
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    MsgBox Node
End Sub
Bạn cần đăng nhập để thấy hình ảnh

Ở trên tôi select vào Node Range 1. Lập tức hộp thoại thông báo hiện ra, cho biết tên Node mà tôi đang select.
Chính xác của Code trên phải viết là:
Mã:
MsgBox Node.Text
Tuy nhiên tôi đã giản lược thuộc tính Text và VBA vẫn hiểu và làm việc được và nó làm việc với thuộc tính mặc định của Node, đó chính là Text.

Chúng ta nhận thấy để di chuyển qua lại giữa các Node, các bạn có thể sử dụng phím mũi tên trái phải hoặc mũi tên lên xuống (←,→,↑,↓) và sự kiện click vẫn được phát sinh.
Khi bạn click vào các dấu [+] hay [-] trên TreeView để hiện ra danh sách các Node thì sự kiện click không được phát sinh. Chỉ có danh sách các Node là hiện ra hay thu lại mà thôi.

Các thuộc tính hay dùng
Thuộc tính Count: Đây không phải là thuộc tính của Node Object, mà là thuộc tính của Nodes Collection.​
Bạn cần đăng nhập để thấy hình ảnh

Thuộc tính Index: Mỗi Node đều có một chỉ mục (số thứ tự).​
Ta có thể làm việc với một Node thông qua chỉ định làm việc với Node có Index là...., hoặc chỉ định làm việc với Node có tên là ...​
Tuy nhiên, tên Node ở đây không phải là Text, mà tham số tên Node ở đây là Key, nó là tên Node nhưng không bị trùng lặp, có như vậy thì mới xác định là làm việc được với Node nào. Ví dụ phải chỉ định là Nodes("_File1"), trong đó "_File1" là Key của Node đó.​
Ngoài ra, chỉ số Index không hiển thị theo tuần tự, chỉ số này được tạo tuần tự trong quá trình ta đăng ký Node. Node nào được đăng ký trước thì sẽ có chỉ số Index nhỏ, rồi cứ thế tăng dần.​
Hãy xem ví dụ dưới đây, bạn sẽ hiểu:​
Mã:
Private Sub CommandButton2_Click()
    Dim i As Long, buf As String
    For i = 1 To TreeView1.Nodes.Count
        buf = buf & TreeView1.Nodes(i) & vbCrLf
    Next i
    MsgBox buf
End Sub
Bạn cần đăng nhập để thấy hình ảnh

(Còn nữa)
 

Yukino Ichikawa

Thành viên
6. Thao tác với control TreeView
(tiếp theo)
Thuộc tính Parent: Thuộc tính này sẽ trả về Node mẹ của Node hiện tại.​
Nodes("thvba").Parent là Nodes("_HoTen").​
Tuy nhiên Node DiaChi không có Node mẹ. Giá trị thuộc tính Parent khi đó sẽ trả về giá trị là Nothing.​
Cùng với đó nếu ta sử dụng Msgbox Node.Parent, khi chúng ta click vào Node DiaChi thì sẽ xảy ra lỗi do trên nó không có Node nào. Hàm Msgbox cũng không thể hiển thị ra là Nothing.​
Vì vậy để phán đoán thuộc tính Parent có trả về giá trị Nothing, nhất thiết phải qua bước kiểm tra thông qua toán tử Is.​
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
If Node.Parent Is Nothing Then
    MsgBox "Khonng co me"
Else
    MsgBox Node.Parent
End If
End Sub
Bạn cần đăng nhập để thấy hình ảnh


Thuộc tính Children và Child: Thuộc tính này trả về Node con của Node hiện tại.​
Thuộc tính Children sẽ cho ta biết Node đó có bao nhiêu Node con. Ví dụ: Children của node HoTen là 1. Children của Node TuHocVBA là 2. Children của Node DiaChi là 0.​
Thuộc tính Child sẽ trả về Node con đầu tiên của Node hiện tại.​
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)

    If Node.Children > 0 Then

        MsgBox Node.Child

    Else

        MsgBox "Khong co Node con"

    End If

End Sub
Bạn cần đăng nhập để thấy hình ảnh

(Còn nữa)
 

vanthanhVBA

Thành viên
6. Thao tác với control TreeView
(tiếp theo)
Thuộc tính FullPath, Root:
Thuộc tính FullPath sẽ trả về đường dẫn của Node đó.​
Thuộc tính Root sẽ trả về Node tổ tiên của nó.​
Hãy xem ví dụ dưới đây:​
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    MsgBox "FullPath: " & Node.FullPath & vbCrLf & _
           "Root: " & Node.Root
End Sub
Bạn cần đăng nhập để thấy hình ảnh


Hiển thị danh sách các Node con
Để hiển thị danh sách các Node con ta sử dụng thuộc tính Expanded của Node Object.
Tôi có ba ví dụ như sau: Trường hợp 1 không có dòng code 15 và 16. Trường hợp 2 chỉ có dòng code 15, không có dòng code 16. Trường hợp 3 có cả dòng code 15 và dòng code 16.
Mã:
Private Sub CommandButton1_Click()
    With TreeView1.Nodes
        .Clear
        .Add Key:="_HoTen", Text:="HoTen", Image:="book"

        .Add Key:="_DiaChi", Text:="DiaChi", Image:="book"

        .Add Relative:="_HoTen", Relationship:=tvwChild, Key:="thvba", Text:="TuHocVBA", Image:="sheet"

        .Add Relative:="thvba", Relationship:=tvwChild, Text:="SoThich"

        .Add Relative:="thvba", Relationship:=tvwChild, Text:="Level"
        
    End With
        TreeView1.Nodes("_HoTen").Expanded = True
        TreeView1.Nodes("thvba").Expanded = True
End Sub
Bạn cần đăng nhập để thấy hình ảnh

(Còn nữa)
 

Yukino Ichikawa

Thành viên
6. Thao tác với control TreeView
(tiếp theo)
Xóa Node
Đối với việc xóa Node, chúng ta sẽ dùng câu lệnh Remove, một câu lệnh trong Nodes Collection. Để sử dụng câu lệnh Remove, cần chỉ định số hiệu index của Node cần xóa. Nếu chỉ định bằng Node Object thì sẽ xảy ra lỗi, hãy chú ý điều này.
Ở ví dụ dưới đây, ta sẽ thực hiện xóa Node đang được select.
Mã:
Private Sub CommandButtonDel_Click()
    With TreeView1
        If MsgBox("Ban muon xoa: " & vbCrLf & .SelectedItem, 36) = vbYes Then
            .Nodes.Remove .SelectedItem.Index
        End If
    End With
End Sub
Bạn cần đăng nhập để thấy hình ảnh

Để xác định Node nào đang được select, ta có thể dùng thuộc tính SelectedItem của TreeView Control. Thuộc tính này sẽ trả về Node Object.
Phương thức Remove cần được chỉ định tham số bằng số hiệu Index cho nên ta dùng SelectedItem.Index .
Tất nhiên, nếu bạn muốn xóa toàn bộ các Node thì bạn có thể dùng câu lệnh Clear như sau: TreeView1.Nodes.Clear .
 

tuhocvba

Administrator
Thành viên BQT
7. Ví dụ về sử dụng control TreeView trong thực tiễn
(Phần 1)
Ở ví dụ này, tôi sẽ cho hiển thị toàn bộ các workbook đang được mở và các sheet của file Excel tương ứng trên TreeView.
Bạn cần đăng nhập để thấy hình ảnh

Mã:
Private Sub UserForm_Initialize()
    Dim imgB, imgS
    
    With ImageList1
        Set imgB = .ListImages.Add(1, "book", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "excel.jpg"))
        Set imgS = .ListImages.Add(2, "sheet", LoadPicture(ThisWorkbook.Path & Application.PathSeparator & "sheet.jpg"))
        
    End With
    
    Dim wb, ws
    With TreeView1
        .Indentation = 14
        .LabelEdit = tvwManual
        .BorderStyle = ccNone
        .HideSelection = False
        .LineStyle = tvwRootLines
        .ImageList = ImageList1
        For Each wb In Workbooks
            .Nodes.Add(Key:=wb.Name, Text:=wb.Name, Image:="book").Expanded = True
            For Each ws In wb.Worksheets
                .Nodes.Add Relative:=wb.Name, Relationship:=tvwChild, _
                           Key:=wb.Name & "!" & ws.Name, Text:=ws.Name, Image:="sheet"
            Next ws
        Next wb
    End With
End Sub
 

vanthanhVBA

Thành viên
7. Ví dụ về sử dụng control TreeView trong thực tiễn
(Phần 2)
Tiếp nối phần trước, ở phần này tôi sẽ lấy thông tin của sheet mà được người dùng select.
Đoạn code chính là:
Mã:
Worksheets("Sheet1").UsedRange.Address
Kết hợp vào TreeView ta có code:
Mã:
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
    Dim BookName As String, SheetName As String
    If Node.Children = 0 Then
        BookName = Node.Parent
        SheetName = Node
        TextBox1 = Workbooks(BookName).Worksheets(SheetName).UsedRange.Address
    Else
        TextBox1 = ""
    End If
End Sub
Ở đây, tôi dùng thêm Textbox1 trên UserForm để hiển thị thông tin Range nào của Sheet đã được sử dụng.
Kết quả:
Bạn cần đăng nhập để thấy hình ảnh
 

Yukino Ichikawa

Thành viên
7. Ví dụ về sử dụng control TreeView trong thực tiễn
(Phần 3)
Xóa sheet mà người dùng đang select trên TreeView.
Mã:
Private Sub CommandButton1_Click()
    Dim BookName As String, SheetName As String
    With TreeView1
        If .SelectedItem.Children > 0 Then    ''[*1]
            MsgBox "Hay select vao sheet ma ban muon xoa", vbExclamation
            Exit Sub
        End If
        BookName = .SelectedItem.Parent    ''[*2]
        SheetName = .SelectedItem
        If MsgBox(SheetName & " :Ban muon xoa sheet nay?", 36) = vbYes Then    ''[*3]
            Application.DisplayAlerts = False
            Workbooks(BookName).Worksheets(SheetName).Delete
            Application.DisplayAlerts = True
        End If
    End With
End Sub
Bạn cần đăng nhập để thấy hình ảnh

Tuy nhiên, mặc dù Sheet sẽ được xóa nhưng TreeView thì lại không được cập nhật. Do đó chúng ta cần phải có một thủ tục reset lại TreeView để cập nhật thông tin mới nhất cho nó. Ngoài ra nội dung ô Textbox1 phải được clear sau khi chúng ta tiến hành xóa sheet mà người dùng đã select.
Mã:
Private Sub UserForm_Initialize()
    With TreeView1
        .Indentation = 14
        .LabelEdit = tvwManual
        .BorderStyle = ccNone
        .HideSelection = False
        .LineStyle = tvwRootLines
        .ImageList = ImageList1
    End With
    Call ResetTreeView
End Sub

Private Sub CommandButton1_Click()
    Dim BookName As String, SheetName As String
    With TreeView1
        If .SelectedItem.Children > 0 Then
            MsgBox "Hay chon sheet de xoa", vbExclamation 'Truong hop nguoi dung select vao Book
            Exit Sub
        End If
        BookName = .SelectedItem.Parent
        SheetName = .SelectedItem
        If MsgBox(SheetName & " :Ban muon xoa sheet nay?", 36) = vbYes Then
            Application.DisplayAlerts = False
            Workbooks(BookName).Worksheets(SheetName).Delete
            Application.DisplayAlerts = True
        End If
    End With
    Call ResetTreeView
End Sub

Private Sub ResetTreeView()
    Dim wb, ws
    With TreeView1
        .Nodes.Clear
        For Each wb In Workbooks
            .Nodes.Add(Key:=wb.Name, Text:=wb.Name, Image:="book").Expanded = True
            For Each ws In wb.Worksheets
                .Nodes.Add Relative:=wb.Name, Relationship:=tvwChild, _
                           Key:=wb.Name & "!" & ws.Name, Text:=ws.Name, Image:="sheet"
            Next ws
        Next wb
        .Nodes(1).Selected = True
        TextBox1 = ""
    End With
End Sub
Download file demo .
 

USA_Covid19

Thành viên tích cực
Hướng dẫn khắc phục lỗi không sử dụng được Additional controls để chèn các control !
Bước 1: Vào Start chọn như hình
Bạn cần đăng nhập để thấy hình ảnh


Bước 2 : Tiếp theo chọn thẻ compatibility tick chọn Run this program in compatibility mode for sau đó chọn win bạn đang dùng
Bạn cần đăng nhập để thấy hình ảnh

Bước 3 : Mở excel và kiểm tra
 

Euler

Mod
Thành viên BQT
@USA_Covid19 : Mình có làm theo cách của bạn nhưng không tìm thấy Microsoft TreeView (win7 64bit + office2013 64bit)
Bạn cần đăng nhập để thấy hình ảnh
 

USA_Covid19

Thành viên tích cực
@Euler cách của mình chỉ áp dụng khi không hiện được hộp thoại additional controls thôi còn vấn đề này mình sẽ test thử trên office 64 và win 64 !
 
Top