[UserForm]ListView-Completed

Trạng thái
Không mở trả lời sau này.

Euler

Administrator
Thành viên BQT
Theo thông tin mình đọc được thì listview chỉ có trên Office 32bit. Tuy nhiên trên máy tính win 10 64bit office 2016 64bit thì lại thấy có ListView.
Vì vậy mình mở topic này để trình bày về ListView.
Bạn cần đăng nhập để thấy đính kèm

ListView có từ phiên bản Office 2000 trở đi. Đây không phải là control tiêu chuẩn của Excel, vì vậy bạn hãy thật cân nhắc khi dùng nó, rất có thể ở máy tính khác không sử dụng được.

1.
2.
3.
4.
5.
6. Thao tác với ListView
6.1
6.2
6.3
6.4

7.
 
1. Lấy control ListView ở đâ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 hình ảnh


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


2. Bài trí control ListView như thế nào?
Bạn click vào biểu tượng ListView:
Bạn cần đăng nhập để thấy hình ảnh

rồi vẽ trên UserForm:
Bạn cần đăng nhập để thấy hình ảnh
 
B

bvtvba

Guest
3. Khởi tạo ListView Control
Trong ví dụ dưới đây tôi sẽ khởi tạo các thông số cho ListView
Mã:
Private Sub UserForm_Initialize()
    With ListView1
        .View = lvwReport           ''Hien thi: lvwIcon/lvwList/lvwReport/lvwSmallIcon
        .LabelEdit = lvwManual      ''Bien tap Label
        .HideSelection = False      ''Che do tu dong huy chon True/False
        .AllowColumnReorder = True  ''Cho phep thay doi be ngang cot
        .FullRowSelect = True       ''Cho phep chon mot dong du lieu
        .Gridlines = True           ''Duong ke o
    End With
End Sub
Thuộc tính View sẽ chỉ định hình thù của ListView ra bên ngoài.
Thuộc tính LabelEdit: Có thể chỉ định là lvwAutomatic hoặc lvwManual. Nếu chỉ định là lvwAutomatic , bạn có thể chỉnh sửa dữ liệu nằm ở cột dữ liệu ngoài cùng bên trái mà bạn đã chọn (select). Nếu chọn là lvwManual thì bạn có thể vừa ấn F2 vừa chỉnh sửa dữ liệu.
Thuộc tính HideSelection thì giống như trong bài viết TreeView. Nếu chọn là True, có nghĩa là nếu bạn thao tác ra ngoài ListView thì hạng mục dữ liệu đang được chọn sẽ bị hủy. Nếu chọn là False, dù cho thao tác ra ngoài ListView, bạn vẫn biết hạng mục dữ liệu nào đang được chọn.
Thuộc tính FullRowSelect sẽ cho phép bạn chọn toàn bộ một dòng dữ liệu.
Thuộc tính Gridlines sẽ cho phép hiển thị dưới dạng ô lưới, nhìn rất đẹp mắt.
Bạn cần đăng nhập để thấy hình ảnh
 
4. Thiết định cột cho ListView
Chúng ta sẽ làm việc với ColumnHeaders Collections. Khi phương thức Add được thực thi, sẽ tạo ra cột dữ liệu mới trên ListView.
Mã:
Private Sub UserForm_Initialize()
    With ListView1
        .View = lvwReport           ''Hien thi: lvwIcon/lvwList/lvwReport/lvwSmallIcon
        .LabelEdit = lvwManual      ''Bien tap Label
        .HideSelection = False      ''Che do tu dong huy chon True/False
        .AllowColumnReorder = True  ''Cho phep thay doi be ngang cot
        .FullRowSelect = True       ''Cho phep chon mot dong du lieu
        .Gridlines = True           ''Duong ke o
        .ColumnHeaders.Add , "_Name", "Ten"
    End With
End Sub
Kết quả:
Bạn cần đăng nhập để thấy hình ảnh

Phương thức Add có cấu trúc như dưới đây:
Mã:
ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon
Tham số Index sẽ xác định vị trí của cột dữ liệu. Khi giản lược không viết, thì các cột dữ liệu sẽ được sắp xếp trình tự từ trái sang phải.
Mã:
        .ColumnHeaders.Add , "_Name", "Ten"
        .ColumnHeaders.Add , "_Age", "Tuoi"
        .ColumnHeaders.Add , "_Address", "DiaChi"
Bạn cần đăng nhập để thấy hình ảnh

Thêm index vào dòng code cuối:
Mã:
        .ColumnHeaders.Add , "_Name", "Ten"
        .ColumnHeaders.Add , "_Age", "Tuoi"
        .ColumnHeaders.Add 2, "_Address", "DiaChi"
Kết quả: Vị trí cột Address (DiaChi) sẽ thay đổi.
Bạn cần đăng nhập để thấy hình ảnh


Tham số Key: Để làm việc với cột, ta đặt tên cho cột theo Key, đảm bảo không trùng nhau.

Tham số Text: Là tên cột được hiển thị ra bên ngoài. Tên này có thể trùng nhau.

Tham số Width: Độ rộng cho cột. Nếu giản lược không viết gì, máy tính sẽ tự động chia đều độ rộng bình quân cho các cột.

Tham số Alignment: Tên cột hiển thị trên cột được sắp xếp về bên trái hay bên phải hay nằm ở giữa cột sẽ do tham số này quyết định.
(lvwColumnLeft, lvwColumnRight, lvwColumnCenter ).
Khi giản lược, không viết gì, thì giá trị mặc định là lvwColumnLeft -tên cột sẽ hiển thị về bên trái của côt.
Ví dụ:
Mã:
        .ColumnHeaders.Add , "_Name", "Ten"
        .ColumnHeaders.Add , "_Age", "Tuoi", , lvwColumnCenter
        .ColumnHeaders.Add 2, "_Address", "DiaChi", , lvwColumnRight
Bạn cần đăng nhập để thấy hình ảnh

Nguồn:
 
T

thanhphong

Guest
5. Load dữ liệu vào ListView
Data của ListView Cotrol được thao tác bằng ListItems Collections. Khi thêm data (dữ liệu) vào ListView, chúng ta dùng phương thức Add của ListItems Collections. Điều phải chú ý là khi các bạn chọn chế độ hiển thị của listview là lvwReport, thì ListItems Collections là cột thứ 1 (cột dữ liệu ngoài cùng bên trái). Từ cột dữ liệu thứ 2 trở đi được gọi là SubItems Collections.
Bạn cần đăng nhập để thấy hình ảnh

Đây là đoạn code, ở đây tôi thêm code cho nút bấm CommandButton1:
Mã:
Private Sub CommandButton1_Click()
    With ListView1
        ''Dong du lieu thu 1
        With .ListItems.Add
            .Text = "tuhocvba"
            .SubItems(1) = 36
            .SubItems(2) = "HaNoi"
        End With
        ''Dong du lieu thu 2
        With .ListItems.Add
            .Text = "thanhphong"
            .SubItems(1) = 28
            .SubItems(2) = "HaNoi"
        End With
        ''Dong du lieu thu 3
        With .ListItems.Add
            .Text = "NhanSu"
            .SubItems(1) = 41
            .SubItems(2) = "HCM"
        End With
    End With
End Sub

Private Sub UserForm_Initialize()
    With ListView1
        .View = lvwReport           ''Hien thi: lvwIcon/lvwList/lvwReport/lvwSmallIcon
        .LabelEdit = lvwManual      ''Bien tap Label
        .HideSelection = False      ''Che do tu dong huy chon True/False
        .AllowColumnReorder = True  ''Cho phep thay doi be ngang cot
        .FullRowSelect = True       ''Cho phep chon mot dong du lieu
        .Gridlines = True           ''Duong ke o
        'Them cot
        .ColumnHeaders.Add , "_Name", "Ten"
        .ColumnHeaders.Add , "_Age", "Tuoi", , lvwColumnCenter
        .ColumnHeaders.Add , "_Address", "DiaChi", , lvwColumnCenter
    End With
End Sub
Hoặc bạn có thể sửa lại code cho nút bấm theo cách sau, ở đây tôi nạp dữ liệu theo từng cột:
Mã:
Private Sub CommandButton1_Click()
    With ListView1
        ''Cot du lieu thu 1
        .ListItems.Add Text:="tuhocvba"
        .ListItems.Add Text:="thanhphong"
        .ListItems.Add Text:="NhanSu"
        ''Cot du lieu thu 2
        .ListItems(1).SubItems(1) = 38
        .ListItems(2).SubItems(1) = 28
        .ListItems(3).SubItems(1) = 41
        ''Cot du lieu thu 3
        .ListItems(1).SubItems(2) = "HaNoi"
        .ListItems(2).SubItems(2) = "HaNoi"
        .ListItems(3).SubItems(2) = "HCM"
    End With
End Sub
Nguồn tham khảo và dịch:
 
6. Thao tác với ListView
6.1 Xác định Item nào đang được chọn và lấy thông tin của Item đó

Điều chúng ta quan tâm là khi có một dòng dữ liệu được chọn (select) trên ListView thì làm thế nào để ta xác định được dòng dữ liệu đó.
Mã:
Private Sub ListView1_ItemClick(ByVal Item As MSComctlLib.ListItem)
    MsgBox Item & vbCrLf & Item.SubItems(1) & vbCrLf & Item.SubItems(2)
End Sub
Bạn cần đăng nhập để thấy hình ảnh


6.2 Xóa một Item ra khỏi ListView
Để xóa dữ liệu trên ListView ta dùng phương thức Remove của ListItems Collections. Tham số truyền vào là giá trị Index của dữ liệu cần xóa.
Ở đây tôi thêm một nút bấm nữa trên UserForm có tên là: CommandButton2.
Mã:
Private Sub CommandButton2_Click()
    With ListView1
        If MsgBox("Ban co muon xoa Item: " & .SelectedItem & " dang duoc chon hay khong?", 36) = vbYes Then
            .ListItems.Remove .SelectedItem.Index
        End If
    End With
End Sub
Tôi chọn vào một Item bất kỳ trên ListView. Ở đây, tôi chọn vào Item cuối cùng trên ListView.
Sau đó ấn vào nút CommandButton2.
Bạn cần đăng nhập để thấy hình ảnh

Vì máy tính tôi đang cài đặt ngôn ngữ tiếng nhật cho nên thay vì hiển thị Yes/No thì nó hiển thị はい/いいえ , bạn không cần quan tâm tới điều này.
Tôi chọn Yes và kết quả là dòng dữ liệu đó đã được xóa đi.
Bạn cần đăng nhập để thấy hình ảnh


6.3 Thay đổi dữ liệu
Bạn thêm đoạn code sau vào UserForm.
Mã:
Private Sub ListView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer)
    If KeyCode = 113 Then ListView1.StartLabelEdit
End Sub
Lúc này với dòng dữ liệu mà bạn đang chọn, bạn ấn F2 thì lập tức có thể biên tập lại dữ liệu ListItem của dòng đó.
Bạn cần đăng nhập để thấy hình ảnh

(còn nữa)
 
T

thanhphong

Guest
6.4 Sắp xếp dữ liệu
Đối với ListView, chúng ta có thể click vào tiêu đề tên cột, khi đó dữ liệu của cột dữ liệu đó sẽ được sắp xếp tuần tự tăng dần hoặc ngược lại.
Nhưng chú ý, điều đó không diễn ra tự động, mà chúng ta phải thêm code cho ListView.
  • SortKey: Thuộc tính này sẽ sắp xếp dữ liệu theo tiêu chuẩn.
  • SortOrder: Thuộc tính này sẽ sắp xếp tăng dần/giảm dần.
  • Sorted: Thiết định thuộc tính này là True.
Khi click vào tiêu đề cột, sẽ phát sinh sự kiện ColumnClick . Khi đó , cái ColumnHeader Object mà đã được người dùng click vào sẽ được lưu vào trong tham số ColumnHeader. Ta cần chỉ định cho thuộc tính SortKey giá trị index của cột dữ liệu mà chúng ta đã click trừ đi 1:
Index của ColumnHeader Object -1 .
Tiếp theo, chúng ta sẽ chỉ định cho thuộc tính SortOrderlvwAscending (xếp tăng dần) hoặc lvwDescending (xếp giảm dần). Và chỉ định thuộc tính SortedTrue.
Mã:
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
    With ListView1
        .SortKey = ColumnHeader.Index - 1
        .SortOrder = .SortOrder Xor lvwDescending
        .Sorted = True
    End With
End Sub
Điều ta phải chú ý trong đoạn code trên chính là dòng code số 3. Giá trị index của cột dữ liệu ngoài cùng bên trái là 1. Tuy nhiên SortKey lại được đếm bắt đầu từ 0. Vì vậy mà ở đây ta phải thực hiện phép trừ cho 1.
Trong code trên tôi dùng logic .
Có thể nói ngắn gọn như thế này:
Mã:
        If .SortOrder = lvwAscending Then
            .SortOrder = lvwDescending
        Else
            .SortOrder = lvwAscending
        End If
Nếu sắp xếp đang là giảm giần thì chuyển thành tăng dần và ngược lại.
Kết quả thể hiện như sau:
Bạn cần đăng nhập để thấy hình ảnh

Bạn có thể click vào cột bất kỳ, không nhất thiết phải click vào cột ngoài cùng bên trái. Dữ liệu của cột mà bạn click sẽ được sắp xếp lại.
 

Euler

Administrator
Thành viên BQT
7. Ví dụ về sử dụng control ListView trong thực tiễn
Sau đây ta sẽ sử dụng ListView để hiển thị/không hiển thị comment trên Excel.
Bạn cần đăng nhập để thấy đính kèm


Khởi tạo UserForm, nạp comment vào ListView:
Mã:
Private Sub UserForm_Initialize()
    
    With ListView1
        ''Property
        .View = lvwReport           ''Hie thi
        .LabelEdit = lvwManual      ''Bien tap Label
        .HideSelection = False      ''Tu dong huy select
        .AllowColumnReorder = True  ''Cho phep thay doi be rong cua cot
        .FullRowSelect = True       ''Select ca dong du lieu
        .Gridlines = True           ''Hien thi duong luoi
        ''Tao truong du lieu
        .ColumnHeaders.Add , "_Address", "DiaChi", 46
        .ColumnHeaders.Add , "_View", "HienThi", 46
        .ColumnHeaders.Add , "_Text", "NoiDung", 126
        ''Lay comment
        Call GetComments
        CheckBox1 = Application.DisplayCommentIndicator > 0
    End With
End Sub
Dòng code 17:
Để hiển thị toàn bộ comment trong một sheet của Excel ta có thuộc tính DisplayCommentIndicator của Application Object. Thuộc tính này là 0 thì các comment không hiển thị, nếu là 1 thì các comment sẽ được hiển thị. Giá trị khởi tạo của checkbox1 sẽ phản ánh trạng thái này.

Thủ tục lấy comment:
Mã:
Sub GetComments()   ''Lay tat ca comment
    Dim Memo
    With ListView1
        .ListItems.Clear
        For Each Memo In ActiveSheet.Comments
            With .ListItems.Add
                .Text = Memo.Parent.Address(0, 0)
                .SubItems(1) = Memo.Visible
                .SubItems(2) = Memo.Text
            End With
        Next Memo
        If .ListItems.Count > 0 Then .ListItems(1).Selected = True
    End With
End Sub
Chú ý, thủ tục này được viết trong UserForm.

Xử lý của CheckBox:
1. CheckBox1: Cho hiển thị/không hiển thị các comment trên sheet của Excel.
2. CheckBox2: Cho hiển thị/không hiển thị của comment trên ListView.

Mã:
Private Sub CheckBox1_Click()   ''[Hien thi comment]
    Dim SelectedRow As Long
    Application.DisplayCommentIndicator = (CheckBox1 + 1) * (-2) + 1
    With ListView1
        If .ListItems.Count = 0 Then Exit Sub
        SelectedRow = ListView1.SelectedItem.Index
        Call GetComments
        ListView1.ListItems(SelectedRow).Selected = True
    End With
End Sub
Dòng code số 3 sẽ khiến chúng ta hơi phân vân một chút. Nó có tác dụng là làm hiển thị/không hiển thị các comment trên sheet của Excel.
Nếu viết code bằng If hay Select Case thì có lẽ dễ hiểu hơn. CheckBox nếu được select nó có giá trị là -1, nếu không được select nó có giá trị là 0.

Khi thủ tục GetComments được gọi thì ListView sẽ bị Clear, không còn lưu trữ thông tin gì. Cũng tại thủ tục GetComments sẽ nạp lại cho ListView (sau khi đã clear thì nạp lại thông tin).
Vì lý do đã bị Clear trước đó cho nên dòng code số 8 trả lại giá trị dòng đã được selected trước đó.

Mã:
Private Sub CheckBox2_Click()   ''[Khong hien thi Author]
    Dim i As Long, buf As String
    With ListView1
        If .ListItems.Count = 0 Then Exit Sub
        If CheckBox2 Then
            For i = 1 To .ListItems.Count
                buf = Range(.ListItems(i)).Comment.Text
                If Right(Left(buf, InStr(buf, vbLf) - 1), 1) = ":" Then
                    .ListItems(i).SubItems(2) = Mid(buf, InStr(buf, vbLf) + 1)
                End If
            Next i
        Else
            For i = 1 To .ListItems.Count
                .ListItems(i).SubItems(2) = Range(.ListItems(i)).Comment.Text
            Next i
        End If
    End With
End Sub
Phần code trên sẽ tách bỏ tác giả (Author) hoặc giữ nguyên như bình thường.

Select tới Cells có comment:
Trên UserForm, bạn click vào dòng bất kỳ trên ListView, ta mong muốn trên sheet Excel sẽ được select vào cells chứa comment tương ứng với dòng trên ListView đó:
Mã:
Private Sub ListView1_DblClick()
    Range(ListView1.SelectedItem).Select
End Sub
Delete Comment:
Trên UserForm, bạn click vào dòng bất kỳ trên ListView, bạn ấn phím Delete, đồng thời comment trên sheet của Excel bị xóa và dòng dữ liệu trên ListView cũng bị xóa:
Mã:
Private Sub ListView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer)
    With ListView1
        If .ListItems.Count = 0 Then Exit Sub
        If KeyCode = 46 Then
            Range(.SelectedItem).ClearComments
            Call GetComments
        End If
    End With
End Sub
Download File demo: .
Nguồn tham khảo:
 
Trạng thái
Không mở trả lời sau này.
Top