Giới thiệu.
Tiếp tục từ Hướng dẫn điều khiển ActiveX ListView-01 của tuần trước.
Trong phần Hướng dẫn này, chúng ta sẽ học cách tìm kiếm và tìm các giá trị hàng và cột cụ thể và hiển thị chúng trên Điều khiển nhãn trên Biểu mẫu. Điều này rất hữu ích khi chúng ta có một khối lượng lớn dữ liệu trong điều khiển ListView. Chúng ta cũng sẽ tìm hiểu cách sử dụng một số cài đặt thuộc tính ListView.
Trước hết, chúng ta sẽ thấy việc sắp xếp lại các cột dễ dàng như thế nào, giống như chúng ta làm với Access Datasheet View theo cách chúng ta muốn chúng có trên Điều khiển ListView. Chúng tôi đã thêm một số TextBox, ComboBox, Command Buttons và Label để lựa chọn các tham số tìm kiếm và hiển thị kết quả tìm kiếm dễ dàng hơn.
Tôi đã thực hiện một số thay đổi đối với dữ liệu demo của tuần trước. Các giá trị cột đầu tiên tôi đã lấy từ Bảng nhân viên của cơ sở dữ liệu mẫu Northwind.accdb. Đã tạo một Truy vấn để kết hợp các Giá trị LastName và FirstName với tên trường là Student và EmployeeID được sử dụng làm Khóa (X01, X02 ...).
Trước khi thực hiện các thao tác tìm kiếm, chúng tôi sẽ kiểm tra cách sắp xếp lại các cột bằng phương pháp kéo và thả.
Lưu ý: Nếu bạn chưa xem qua Trang hướng dẫn trước đó và muốn tiếp tục với phiên này, hãy truy cập Trang hướng dẫn điều khiển ListView-01 và tải xuống cơ sở dữ liệu demo từ cuối Trang đó.
Giải nén tệp và mở Cơ sở dữ liệu. Biểu mẫu Demo sẽ ở Chế độ xem Bình thường.
-
Mở Cơ sở dữ liệu của bạn, với Biểu mẫu Demo của phiên cuối cùng hoặc Biểu mẫu mà bạn đã tạo, mở nó ở Dạng xem Thường.
Bây giờ, chúng tôi sẽ cố gắng kéo và di chuyển một cột từ giữa danh sách (giả sử cột Trọng lượng) và thả nó vào Tuổi và xem điều gì sẽ xảy ra. Điều dự kiến sẽ xảy ra là cột Tuổi sẽ chuyển sang bên phải và chèn cột đến vào vị trí của nó.
-
Di chuyển con trỏ chuột trên Tiêu đề Cột với tên Trọng lượng, nhấp và giữ nút chuột trái. Khi bạn nhấn nút chuột trái, tiêu đề cột sẽ di chuyển xuống một chút.
-
Bây giờ, hãy thử kéo cột sang bên trái và thả nó vào cột Tuổi .
Sẽ không có gì xảy ra vì chúng tôi chưa bật tính năng này trong Trang thuộc tính và đó là cài đặt duy nhất, chúng tôi cần thay đổi để tính năng này hoạt động.
-
Thay đổi Biểu mẫu trong Dạng xem Thiết kế.
-
Nhấp chuột phải vào Điều khiển ListView và đánh dấu tùy chọn Đối tượng ListViewCtrl và chọn Thuộc tính.
-
Có một tùy chọn ' AllowColumnReorder ' phía bên phải. Đặt dấu kiểm để chọn nó, sau đó nhấp vào Áp dụng tiếp theo là nút OK để đóng Chế độ xem thuộc tính.
-
Bây giờ, hãy thử lặp lại các bước 2 và 3 ở trên và xem điều gì sẽ xảy ra.
Đó là cài đặt duy nhất bạn cần để bật tính năng này trên Điều khiển ListView. Có lẽ bạn đang nghĩ, sắp xếp lại các hàng thì sao ?.
Chức năng đó cần lập trình một số Thủ tục Sự kiện như chúng ta đã làm trước đó trong Sự kiện Kéo-Thả Điều khiển TreeView. Phần đó chúng tôi sẽ thực hiện sau một thời gian.
-
Bạn có thể thử nghiệm với bất kỳ cột nào để di chuyển đến bất kỳ đâu bạn muốn, bao gồm cả cột đầu tiên.
Lưu ý: Trước khi bạn thả cột nguồn, hãy xem cột đích được bao phủ bởi khung cột đến trước khi cố gắng thả. Nếu không, cột đến có thể chuyển sang vị trí cột tiếp theo ở phía bên phải.
Tiếp theo, chúng ta sẽ học cách tìm kiếm một số thông tin từ ListView một cách nhanh chóng, giả sử rằng chúng ta có một khối lượng lớn dữ liệu trong đó.
Chúng tôi đã thêm chương trình con vào Mô-đun Tutorial-01 để tải Tên tiêu đề cột vào Hộp tổ hợp trên biểu mẫu có màu nền đỏ. Tên Cột sẽ được sử dụng để tìm giá trị cột (Tuổi, Chiều cao, Cân nặng hoặc Lớp học) của học sinh.
Mã VBA mới được thêm vào mô-đun lớp biểu mẫu.
Quy trình VBA mới sau đây được thêm vào Mô-đun lớp của Biểu mẫu Hướng dẫn của tuần trước:
txtColCombo tạo danh sách Nhãn tiêu đề cột (tên trường) trong ComboBox. Một trong những chi tiết này về Tuổi, Chiều cao, Cân nặng, của Học sinh hoặc Lớp có thể được tìm thấy cùng với tên của học sinh như một phần của hoạt động tìm kiếm.
Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub
Combobox sẽ không được tải với giá trị mặc định của tên Tiêu đề Cột. Nếu được chọn, giá trị cột đó của Sinh viên được hiển thị trong Nhãn lớn bên dưới Tên sinh viên. Nếu nó được để trống, thao tác tìm kiếm sẽ chỉ tìm thấy tên của học sinh.
Phương thức thao tác tìm kiếm rất linh hoạt và nhanh chóng. Chúng tôi có hai phương pháp để tìm bản ghi.
Tìm bản ghi bằng cách cung cấp văn bản tìm kiếm. Văn bản tìm kiếm có thể là từ bất kỳ cột nào hoặc là văn bản có đầy đủ hoặc một phần một vài ký tự từ bên trái. Vì chúng ta có hai danh mục thành viên đối tượng liên tiếp trong điều khiển ListView: ListItem - cột đầu tiên và các cột khác là ListSubItems. Thao tác tìm kiếm Văn bản trên các đối tượng này được thực hiện riêng biệt.
Một nhóm tùy chọn với hai CheckBox được cung cấp bên cạnh TextBox đầu vào văn bản tìm kiếm trên Biểu mẫu để chọn các tùy chọn tìm kiếm. Tùy chọn đầu tiên được chọn theo mặc định và tìm kiếm được thực hiện trên Cột đầu tiên ( ListItem ) để tìm kiếm văn bản đã cho.
Chọn tùy chọn thứ hai để tìm kiếm văn bản trong ListSubItem cột .
Lưu ý: Việc sắp xếp lại các cột sẽ không thay đổi các đối tượng mà chỉ thay đổi vị trí hiển thị của chúng. Kéo một ListSubItem và đưa nó vào cột đầu tiên sẽ không thay đổi nó thành một ListItem đối tượng.
Nếu bạn muốn truy xuất một giá trị không xác định từ một cột cụ thể, hãy chọn tên cột từ ComboBox được cung cấp bên dưới TextBox đầu tiên trên Biểu mẫu cho văn bản tìm kiếm. Ví dụ:bạn không biết số đo Chiều cao của một học sinh và muốn tìm hiểu, hãy chọn tên cột Chiều cao từ ComboBox.
Sau khi đặt (các) giá trị trên, hãy nhấp vào Tìm mục Nút lệnh để thực hiện thao tác tìm kiếm. Nếu tìm kiếm thành công, thì kết quả sẽ được hiển thị trong điều khiển Nhãn lớn bên dưới Nút lệnh.
Nhấp vào nút Lệnh [Tìm mục].
Gọi SearchAndFind () Thủ tục .
Private Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lvwList.ListItems.Item(j).Selected = True lblMsg.caption = msgText End If End Sub
Ở đầu chương trình, cả Tên sinh viên và Tên cột ( 0ptional ), được sao chép từ các Hộp văn bản vào các Biến strFind và strColName tương ứng sau khi kiểm tra xác thực.
Lưu ý: Tên cột Thuộc tính Không có trong Danh sách của Hộp tổ hợp được đặt thành Có. Bạn có thể chọn một Giá trị hợp lệ từ danh sách hoặc nhập nó vào hoặc để trống hộp tổ hợp. Nếu bạn nhập một giá trị khác không có trong danh sách, nó sẽ không được chấp nhận.
Dựa trên Tùy chọn tìm kiếm đã chọn (1 - ListItem hoặc 2 - ListSubItem), phương pháp quét được chuyển hướng đến (các) Đối tượng được chỉ định.
Sử dụng một trong các phương pháp tìm kiếm này sẽ tìm thấy Đối tượng ListItem hoặc hàng chứa văn bản tìm kiếm. Giá trị chỉ mục của ListItem được lưu trong Biến J để sử dụng sau này trong chương trình.
Lưu ý: Hệ thống tự động tạo chỉ mục số tự động tại thời điểm các mục kiểm soát ListView được điền.
ListItem.Text giá trị được truy xuất. Thông tin này được kết hợp với ColumnHeader đầu tiên. Văn bản (như Sinh viên:Robert King) và được thêm vào chuỗi Msgtext để hiển thị trong điều khiển Nhãn trên Biểu mẫu.
Nếu Tên tiêu đề cột được chọn trong ComboBox, thì GetColVal () Hàm được gọi với Đối tượng ListItem và giá trị Văn bản Tiêu đề Cột dưới dạng tham số. Tùy chọn này phù hợp để truy xuất thông tin chưa biết về một Học sinh, chẳng hạn như Chiều cao của học sinh, từ hồ sơ.
Mã VBA hàm GetColVal ().
Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function
Hàm trên yêu cầu hai tham số. Tham số đầu tiên là ListItem, nơi tên của Học sinh được tìm thấy. Tham số thứ hai là Tên cột. Tuổi, Chiều cao, Cân nặng, Lớp học của học sinh được chọn các giá trị được lưu trữ trong ListItem.ListSubItems Các đối tượng. Hàm xem qua lvwList.ColumnHeader giá trị để tìm tên cột phù hợp, khi tìm thấy số chỉ mục cột đó được sử dụng để truy xuất giá trị cột từ Đối tượng ListSubItems và trả về giá trị cho chương trình đang gọi.
Quy trình nhấp vào nút lệnh [Tìm theo phím].
Chúng tôi đã thêm một phương pháp khác để tìm Tên của Học sinh bằng cách sử dụng Khóa-Giá trị Duy nhất của ListItem nếu được sử dụng trong khi tạo Danh sách ListItem. Mặc dù nó là tùy chọn, nhưng tốt hơn là thêm Giá trị chuỗi khóa duy nhất (nên bắt đầu bằng một ký tự trong bảng chữ cái) hơn là bỏ qua nó.
Ví dụ:nếu chúng ta phải tìm thông tin của ai đó bằng số nhận dạng của họ như Số An sinh Xã hội, Số Chứng minh Nhân dân Quốc gia, Số Hộ chiếu hoặc Số Giấy phép Lái xe, v.v., một trong những thông tin này có thể được sử dụng làm Giá trị khóa cho ListItem. Tìm một bản ghi với Giá trị Duy nhất này rất dễ dàng và nhanh chóng hơn là phương pháp tìm kiếm theo từng văn bản ở trên.
Quy trình sự kiện cmdKey_Click ().
Calls FindByKey() Subroutine.
Private Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") If len(lvKeyVal) > 0 then On Error Resume Next Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!",vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Như bạn có thể thấy trong chương trình con ở trên, chúng tôi có thể trực tiếp tìm thấy ListItem tên của Học sinh ở đâu, với việc sử dụng Khóa-giá trị , với một câu lệnh duy nhất: Đặt lvItem =lvwList.ListItems.Item (xKeyVal).
Dòng Tiếp theo đọc Văn bản Mục lục (hoặc tên của Sinh viên) vào Biến txt . Hai dòng tiếp theo tạo văn bản tin nhắn có Tên học sinh trong biến chuỗi msgText.
Tiếp theo Nếu. . .Sau đó câu lệnh kiểm tra xem một Giá trị Tên Cột có được nhập vào điều khiển hộp tổ hợp hay không. Nếu nó được tìm thấy, thì hãy gọi GetColVal () Hàm với các tham số bắt buộc để tìm giá trị cột và truy xuất giá trị đó trong varColVal Biến và quay lại chương trình đang gọi. Tên Cột và giá trị của nó được truy xuất được thêm vào biến chuỗi msgText để hiển thị trên điều khiển Nhãn trên Biểu mẫu.
Câu lệnh tiếp theo làm nổi bật bản ghi Hàng của Sinh viên như một dấu hiệu trực quan rằng mục được tìm kiếm được tìm thấy trong hàng. Giá trị msgText được hiển thị trong Thuộc tính chú thích của nhãn trên Biểu mẫu.
Mã VBA đầy đủ trên mô-đun biểu mẫu.
Option Compare Database Option Explicit Dim lvwList As MSComctlLib.ListView 'ListView Control Dim lvwItem As MSComctlLib.ListItem ' Dim ObjImgList As MSComctlLib.ImageList Const prfx As String = "K" Private Sub Form_Load() Call LoadListView Call txtColCombo End Sub Private Function LoadListView() 'Populate the ListView control with Student Details Dim db As DAO.Database Dim rst As DAO.Recordset Dim intCounter As Integer Dim strKey As String 'Assign ListView Control on Form to lvwList Object Set lvwList = Me.ListView1.Object With lvwList .AllowColumnReorder = True .Enabled = True .Font = "Verdana" .Font.Bold = True .Font.Size = 9 .ForeColor = vbBlack .BackColor = vbWhite End With 'Create Column Headers for ListView With lvwList .ColumnHeaders.Clear 'initialize header area 'Syntax: .ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon .ColumnHeaders.Add , , "Student", 2500 .ColumnHeaders.Add , , "Age", 1200 .ColumnHeaders.Add , , "Height", 1200 .ColumnHeaders.Add , , "weight", 1200 .ColumnHeaders.Add , , "Class", 1200 End With 'Initialize ListView Control While lvwList.ListItems.Count > 0 lvwList.ListItems.Remove (1) Wend 'Student Names and Ids are taken from Employees Table 'through the StudentQ Query. Set db = CurrentDb Set rst = db.OpenRecordset("StudentQ", dbOpenDynaset) With lvwList Do While Not rst.EOF And Not rst.BOF intCounter = rst![EmployeeID] strKey = "X" & Format(intCounter, "00") 'Key Value sample: X01 'Syntax: .ListItems.Add(Index, Key, Text, Icon, SmallIcon) Set lvwItem = .ListItems.Add(, strKey, rst![Student]) With lvwItem 'Syntax: .Add Index,Key,Text,Report Icon,TooltipText .ListSubItems.Add , strKey & CStr(intCounter), CStr(5 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 1), CStr(135 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 2), CStr(40 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 3), ("Class:" & Format(intCounter, "00")) End With rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing Set lvwItem = Nothing End With lvwList.Refresh End Function Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub Private Sub cmdFind_Click() Call SearchAndFind End Sub Private Sub cmdKey_Click() Call FindByKey End Sub Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub Public Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found in the List!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lblMsg.caption = msgText lvwList.ListItems.Item(j).Selected = True End If End Sub Public Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") On Error Resume Next If Len(lvKeyVal) > 0 Then Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!", vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Tải xuống Cơ sở dữ liệu Demo từ Liên kết sau:
- Hướng dẫn Điều khiển Microsoft TreeView
- Tạo Menu Truy cập với Điều khiển TreeView
- Gán hình ảnh cho các nút TreeView
- Gán hình ảnh cho các nút TreeView-2
- Dấu kiểm Kiểm soát TreeView Thêm Xóa
- Quyền truy cập thả xuống TreeView ImageCombo
- Sắp xếp lại các nút TreeView bằng cách kéo và thả
- Kiểm soát ListView với MS-Access TreeView
- Sự kiện kéo thả trong điều khiển ListView
- Kiểm soát TreeView với các biểu mẫu con