Sắp xếp lại các dòng dữ liệu trong điều khiển ListView.
Trong tập trước của Hướng dẫn này, chúng ta đã học cách sắp xếp lại các Cột bằng cách bật tính năng này: AllowColumnReorder trên Trang thuộc tính. Tuy nhiên, việc chuyển vị trí một hàng được thực hiện bằng cách kéo và đặt nó trên một hàng khác. Để sắp xếp lại các hàng điều khiển ListView, hành động Kéo và Thả ListItem yêu cầu bật tính năng này trên Trang Thuộc tính. Nhưng chỉ điều này sẽ không hoạt động, cần Mã VBA để sắp xếp lại mặt hàng theo thứ tự yêu cầu.
Hãy để chúng tôi tạo một Biểu mẫu truy cập mẫu với các điều khiển và Mã VBA trong cơ sở dữ liệu của chúng tôi cho bài tập này. Hình ảnh mẫu của Biểu mẫu với Điều khiển ListBox và ListView được cung cấp bên dưới.
Chúng tôi đã tạo danh sách Bảng và Truy vấn (không phải Truy vấn Hành động) trong Hộp Danh sách. Việc chọn một trong các mục danh sách sẽ hiển thị các bản ghi ngay lập tức trên điều khiển ListView, như chúng ta thấy chúng trong dạng xem Biểu dữ liệu.
Nhiệm vụ thiết kế.
-
Tạo một Bảng mới với một trường Văn bản, với tên trường là Danh sách dữ liệu .
-
Lưu Bảng với tên lvTables (lv là viết tắt của ListView).
-
Mở Bảng trong Dạng xem Biểu dữ liệu.
-
Thêm một vài tên bảng và Chọn tên truy vấn từ cơ sở dữ liệu của bạn vào Bảng. Tôi đã nhập các Bảng từ cơ sở dữ liệu mẫu Northwind cho danh sách của mình.
Lưu ý: Phần đính kèm Trường không hợp lệ trong Điều khiển ListView. Tạo Truy vấn Chọn cho các bảng có trường phần đính kèm và chọn tất cả các trường ngoại trừ trường Phần đính kèm.
-
Tạo và mở một Biểu mẫu mới trong Dạng xem Thiết kế.
-
Chèn Điều khiển ListBox trên biểu mẫu, hiển thị Trang thuộc tính và thay đổi Tên của nó giá trị thuộc tính thành Danh sách0 .
-
Thay đổi nhãn con Chú thích giá trị thành Bảng .
-
Hiển thị Trang thuộc tính của điều khiển ListBox và đặt Nguồn hàng giá trị thuộc tính cho lvTables tên.
-
Kiểm tra xem Loại nguồn hàng có được đặt làm Bảng / Truy vấn hay không và giá trị thuộc tính Cột liên kết là 1. Nếu khác thì hãy thay đổi.
-
Chèn Điều khiển ListView từ Danh sách Điều khiển ActiveX và thay đổi Giá trị thuộc tính tên của nó thành ListView1 .
-
Thay đổi kích thước cả hai điều khiển như được hiển thị trên hình ảnh Biểu mẫu trình diễn ở trên.
-
Chèn một Nhãn phía trên các Điều khiển và thay đổi Giá trị Thuộc tính Tên và Phụ đề của nó thành Tiêu đề. Giá trị Phụ đề sẽ được thay đổi từ mã vba khi một Bảng hoặc Truy vấn được chọn từ ListBox.
-
Tạo Nút lệnh bên dưới Điều khiển và thay đổi giá trị thuộc tính Tên của nó thành cmdClose và giá trị thuộc tính Caption thành Đóng .
-
Nhấp chuột phải vào Điều khiển ListView, đánh dấu Đối tượng ListViewCtrl và chọn Thuộc tính .
-
Thay đổi cài đặt thuộc tính để phù hợp với cài đặt trong Chung Hình ảnh tab được cung cấp bên dưới.
-
Hình ảnh Bảng thuộc tính điều khiển ListView - Chế độ xem tab chung được đưa ra bên dưới:
Một số tùy chọn này chúng tôi đã thiết lập trong các phiên trước đó. Ở đây, chúng tôi cần các tùy chọn sau cho hành động Kéo thả của chúng tôi:
-
OLEDragAutomatic - 1
-
OLEDropManual - 1
-
FullRowSelect - True
-
HotTracking - Đúng
-
Đảm bảo rằng các cài đặt trên khớp với trang thuộc tính của bạn, sau đó lưu Biểu mẫu.
Hiển thị Mô-đun VBA của Biểu mẫu.
Mã VBA của mô-đun biểu mẫu.
Sao chép và dán Mã VBA sau vào Mô-đun, ghi đè các Dòng mã hiện có, nếu có:
Option Compare Database Option Explicit Dim lvwList As MSComctlLib.ListView Dim strTable As String Dim db As DAO.Database Dim rst As DAO.Recordset Private Sub Form_Load() Set lvwList = Me.ListView1.Object End Sub Private Sub Form_Unload(Cancel As Integer) On Error GoTo Form_Unload_Err Dim lvItem As ListItem Dim tmp As Long Dim criteria As String Dim strfield As String Dim flag As Boolean Dim fld As String If strTable = "" Then Set lvwList = Nothing Exit Sub End If Set db = CurrentDb Set rst = db.OpenRecordset(strTable, dbOpenDynaset) flag = False For Each lvItem In lvwList.ListItems tmp = lvItem.Index strfield = lvwList.ColumnHeaders(1).Text criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34) rst.FindFirst criteria If Not rst.NoMatch Then If (rst.Fields(strfield).Value = lvItem.Text) _ And (rst.Fields(1).Value = tmp) Then 'GoTo nextitem Else rst.Edit rst.Fields(1).Value = tmp rst.Update End If Else MsgBox "Item: " & tmp & " Not Found!" End If Next rst.Close Set lvwList = Nothing Set lvItem = Nothing Set rst = Nothing Set db = Nothing Form_Unload_Exit: Exit Sub Form_Unload_Err: MsgBox Err & " : " & Err.Description, , "Form_Unload()" Resume Form_Unload_Exit End Sub Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object) ' When a ColumnHeader object is clicked, the ListView control ' sorts the data of that column. On the first Click on the Column 'will sort in Ascending Order, second Click will sort in Descending With Me.ListView1 ' Set the SortKey to the Index of the ColumnHeader - 1 .SortKey = ColumnHeader.Index - 1 ' Set Sorted to True to sort the list. If .SortOrder = lvwAscending Then .SortOrder = lvwDescending Else .SortOrder = lvwAscending End If .Sorted = True End With End Sub Private Sub List0_Click() strTable = List0.Value Call LoadListView(strTable) End Sub Private Sub LoadListView(ByVal s_Datasource As String) On Error GoTo LoadListView_Err Dim j As Integer Dim tmpLItem As MSComctlLib.ListItem Dim strHeading As String strHeading = UCase(s_Datasource) With Me.Heading .caption = strHeading .FontName = "Courier New" .FontSize = 20 .FontItalic = True .FontBold = True End With 'Initialize ListView Control lvwList.ColumnHeaders.Clear lvwList.ListItems.Clear Set db = CurrentDb Set rst = db.OpenRecordset(s_Datasource, dbOpenSnapshot) 'Initialize ListView & Column Headers Property Values With lvwList .Font.Size = 10 .Font.Name = "Verdana" .Font.Bold = False .GridLines = True End With With lvwList 'Syntax: .ColumnHeaders.Add Index, Key, Text, Width in Pixels, Alignment, Icon For j = 0 To rst.Fields.Count - 1 .ColumnHeaders.Add , , rst.Fields(j).Name, IIf(j = 0, 3000, 1400), 0 Next End With Dim I As Long rst.MoveFirst Do While Not rst.BOF And Not rst.EOF 'Syntax: lvwList.ListItems.Add Index, Key, Text, Icon, SmallIcon Set tmpLItem = lvwList.ListItems.Add(, , rst.Fields(0).Value) 'Name column 'Syntax: tmpLItem.ListSubItems.Add Index, Key, Text, ReportIcon, ToolTipText With tmpLItem For j = 1 To rst.Fields.Count - 1 .ListSubItems.Add , , Nz(rst.Fields(j).Value, "") Next End With rst.MoveNext Loop rst.Close With lvwList If .ListItems.Count > 0 Then .ListItems(1).Selected = True End If End With Set db = Nothing Set rst = Nothing LoadListView_Exit: Exit Sub LoadListView_Err: MsgBox Err & " : " & Err.Description, , "LoadListView()" Resume LoadListView_Exit End Sub Private Sub ListView1_OLEDragOver(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer) 'Highlight the item when draged over it Set ListView1.DropHighlight = ListView1.HitTest(x, y) End Sub Private Sub ListView1_OLEDragDrop(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single) 'Item being dropped Dim lvwDrag As ListItem 'Item being dropped on Dim lvwDrop As ListItem 'Item being readded to the list Dim lvwTarget As ListItem 'Subitem reference in dropped item Dim lvwSub As ListSubItem 'Drop position Dim intTgtIndex As Integer Dim j As Integer Set lvwDrop = lvwList.HitTest(x, y) Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'For j = intTgtIndex To ListItems.Count 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub
Bạn đã quen với Mã VBA ở trên ngoại trừ các chương trình con mới được thêm vào: ListView1_OLEDragOver (), ListView1_OLEDragDrop (), Form_Unload (), và ListView1_ColumnClik () các thủ tục. Hai quy trình đầu tiên sẽ giúp chúng ta kéo một Item (hàng) và thả nó lên một Item khác để chèn nó vào một vị trí mới. Các thủ tục Form_Unload () và ListView1_ColumnClick () sẽ sắp xếp các Mục.
Các Hình ảnh sau đây cho thấy hành động Kéo và Thả theo chuỗi thực hiện của nó
Hình ảnh đầu tiên bên dưới cho thấy chuỗi hành động kéo và thả. ListItem, với EmployeeID 7, được người dùng kéo lên và thả xuống ListItem có ID 3.
Hình ảnh thứ hai cho thấy sự di chuyển của ListItem theo thứ tự ngược lại.
Khi con trỏ chuột di chuyển qua một hàng có mục được kéo, giữa hàng nguồn và hàng đích, sẽ đánh dấu lần lượt trên đường lên.
Hành động Kéo và Thả trong Ảnh.
Hàng có ID nhân viên 7 bị loại bỏ trên Mục có ID nhân viên 3 ở trên.Phân tích phân đoạn mã VBA khôn ngoan.
Một lựa chọn mục từ ListBox thủ tục sự kiện List0_Click () chạy và tải các bản ghi vào Điều khiển ListView.
Private Sub List0_Click() Dim strTable As String strTable = List0.Value Call LoadListView(strTable) End Sub
Tên Bảng / Truy vấn đã chọn lưu trong strTable biến chuỗi. LoadListView () chương trình con chạy với biến strTable làm tham số. Chúng tôi đã xem qua Mã này nhiều lần trong các phiên trước đó và bạn có thể truy cập các Trang đó bằng các Liên kết được cung cấp ở cuối trang này để biết chi tiết. Bạn có thể tìm thấy một vài thay đổi nhỏ mà tôi đã thực hiện trong Quy tắc này.
Chúng tôi đã không sử dụng Điều khiển danh sách hình ảnh trong tập này, Biểu tượng, SmallIcon Các giá trị tham số trong Phương thức ListItems.Add () và ReportIcon, TooltipText giá trị tham số trong phương thức ListSubItems.Add () cũng không được sử dụng.
Hãy để chúng tôi xem điều gì đang xảy ra trong ListView1_OLEDragOver () và ListView1_OLEDragDrop () Phân đoạn mã VBA.
Thủ tục ListView1_OLEDragOver ().
Private Sub ListView1_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer) 'Highlight the item when draged over it Set ListView1.DropHighlight = ListView1.HitTest(x, y) End Sub
Quy trình này tự động thực hiện khi bạn cố gắng nhấp và giữ vào một hàng, bắt đầu kéo và di chuyển qua các hàng khác trên đường hướng tới hàng đích. Hành động kéo di chuyển qua một hàng khác, nó sẽ được đánh dấu.
ListView1.HitTest (x, y) hàm đọc tọa độ x, y xác định vị trí hàng trên Điều khiển ListView và đánh dấu hàng đó. Quá trình này tiếp tục khi bạn ở trên các hàng khác cho đến khi bạn thả nó xuống hàng mục tiêu bằng cách nhả nút chuột. Hành động thả sẽ kích hoạt ListView1_OLEDragDrop () thủ tục và thực hiện thay đổi của hàng nguồn đối với các thủ tục.
Thủ tục ListView1_OLEDragDrop.
Private Sub ListView1_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single) 'Item being dragged Dim lvwDrag As ListItem 'Item being dropped on Dim lvwDrop As ListItem 'Item being added to the list Dim lvwTarget As ListItem 'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) 'save the source item Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub
Hãy để chúng tôi xem xét từng phần thủ tục này và hiểu điều gì đang xảy ra ở đó. Đoạn mã sau khai báo các Biến đối tượng cần thiết để xử lý hành động Kéo và Thả:
'Item being dragged Dim lvwDrag As ListItem 'Item being dropped on Dim lvwDrop As ListItem 'Reference of the Item being added to the list Dim lvwTarget As ListItem 'Subitem reference used in For . . .Next loop Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item
Ba Đối tượng tạm thời ListItem đầu tiên khai báo với các tên khác nhau.
lvwDrag Đối tượng ListItem sẽ giữ bản sao của hàng mà chúng ta chọn để kéo đến một vị trí mới.
lvwDrop Đối tượng ListItem sẽ lưu tham chiếu của hàng mà chúng ta thả mục danh sách đã kéo vào đó.
Trong quá trình thay đổi hành động ListItems, chúng tôi sẽ xóa mục Nguồn khỏi vị trí ban đầu của nó, sau đó tạo nó ở vị trí đích, với số Chỉ mục ListItem nguồn. Các tham chiếu của ListItem mới này lưu trong lvwTarget Biến đối tượng ListItem.
lvwSub Biến được khai báo dưới dạng một Biến đối tượng sắp xếp theo thứ tự trong thẻ Đối. . .Next Vòng. Vòng lặp này yêu cầu trình tự lần lượt qua ListSubItems, (Cột thứ 2 trở đi) từ đối tượng lvwDrag. Mặc dù chúng tôi đã xóa ListItem ban đầu, chúng tôi vẫn lưu một bản sao của nó trong đối tượng lvwDrag ListItem.
Số lvwDrop ListItem Index được lưu trong intTgtIndex Biến đổi.
lvwList.HitTest (x, y) Hàm đọc tọa độ x, y của Điều khiển ListView và xác định ListItem đích nơi chúng ta đã thả ListItem nguồn và tạo một bản sao của nó trong Đối tượng lvwDrop.
Trước tiên, chúng tôi sẽ chọn một ListItem trước khi kéo nó đến vị trí mới.
lvwList.SelectedItem Thuộc tính sẽ được đặt là True. Với sự trợ giúp của trạng thái thuộc tính này, chúng tôi tạo một bản sao của ListItem đã chọn vào lvwDrag Đối tượng ListItem. Phân đoạn mã tiếp theo xác thực cả Đối tượng ListItem Nguồn và Mục tiêu.
Kiểm tra xác thực đối với hành động kéo thả.
'Ignore overlapping drag or drop Item actions, 'OR drag and drop happens on the same ListItem. If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If
Đoạn mã trên xác nhận hành động kéo và thả. Nếu những hành động này không bắt đầu hoặc kết thúc trên một mục hợp lệ thì Đối tượng lvwDrop hoặc lvwDrag hoặc cả hai sẽ trống. Hoặc một động thái không hợp lệ khác có thể xảy ra khi người dùng di chuyển một hàng lên hoặc xuống nhưng có thể đổi ý và thả lại trên cùng một hàng. Việc phát hiện những kiểu di chuyển sai này sẽ chấm dứt chương trình.
Nếu kiểm tra trên chứng minh là hợp lệ thì chương trình sẽ tiếp tục thực hiện quy trình tiếp theo để sắp xếp lại các Hàng.
'Save the dropped position ListItem Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True
Chín dòng mã thực thi ở trên (các dòng khác là nhận xét) các hành động hơi đơn giản.
intTgtIndex =lvwDrop.Index câu lệnh lưu số Chỉ mục của ListItem mục tiêu trong intTgtIndex Biến đổi.
Vì chúng ta đã lưu listItem hàng nguồn trong đối tượng tạm thời lvwDrag, bước tiếp theo là xóa ListItem nguồn khỏi Điều khiển ListView. Thủ tục ListItems.Remove () được gọi, với câu lệnh lvwList.ListItems.Remove lvwDrag.Index .
Nói tóm lại, hành động Kéo thả là để xóa một ListItem khỏi vị trí ban đầu của nó và tạo lại nó tại vị trí mục tiêu với số chỉ mục của hàng mục tiêu.
Câu lệnh Đặt lvwTarget =lvwList.ListItems.Add (intTgtIndex,, lvwDrag.Text) tạo ListItem mới với số chỉ mục vị trí mục tiêu intTgtIndex và Văn bản giá trị của Source ListItem đã được lưu trong Đối tượng lvwDrag trước đó.
Trong khi tạo ListItem lần đầu tiên, chúng tôi chỉ sử dụng hai giá trị này, chỉ mục và Văn bản các giá trị tham số. Chúng tôi đã không sử dụng các tùy chọn tham số khác Khóa, Biểu tượng, và SmallIcon nếu không, chúng ta cũng phải bao gồm các giá trị tham số đó từ đối tượng lvwDrag.
Theo ví dụ về Kéo thả Hình ảnh hiển thị ở trên, chúng tôi đã di chuyển ListItem thứ 7 và bỏ nó vào ListItem thứ 3. Sau đó, chúng tôi đã xóa Mục thứ 7 (hoặc ListItem nguồn) khỏi Điều khiển ListView. Đã tạo một ListItem mới với chỉ mục mục tiêu số 3.
Bây giờ, có hai mục có cùng Chỉ mục số 3, mục hiện có có chỉ mục số 3 và mục mới chúng ta đã tạo với chỉ mục số 3. Tất cả thông tin khác được lấy từ Đối tượng lvwDrag (hoặc Mục danh sách thứ 7 được lưu trong lvwDrag Đối tượng trước đó).
Hệ thống tự động tăng ListItem 3 hiện có trở đi cho các số thứ tự tiếp theo 3,4,5. . . đến 4,5,6. . . và di chuyển chúng về phía trước để tạo khoảng trống cho mục đến để chèn vào giữa.
Tác động của việc Xóa hàng và tạo hàng ở nơi khác.
Giả sử rằng chúng ta thực hiện chuyển động đó theo thứ tự ngược lại, chẳng hạn như kéo ListItem số 3 từ trên xuống và thả nó vào mục số 7 thì điều gì sẽ xảy ra?
Đương nhiên, chúng tôi sẽ xóa Mục thứ 3 và sẽ cố gắng tạo một mục mới với chỉ mục số 7 ở vị trí mới. Khi mục số 3 bị xóa, mục số 4 trở đi sẽ chuyển lên hoặc 4,5,6,7,8,9 sẽ trở thành 3,4,5,6,7,8 (để tạo tất cả các mục theo thứ tự) hoặc sớm hơn mục có chỉ số 7 sẽ trở thành 6.
Khi chúng ta tạo Item mới với chỉ số 7, 7,8 hiện có sẽ trở thành 8,9 một lần nữa. Khi chúng ta xem chuyển động của các hàng trong khi xóa hàng và thời gian tạo, ví dụ đầu tiên sẽ di chuyển hàng mục tiêu xuống để nhường chỗ cho mục đến. Trong ví dụ thứ hai được giải thích (chuyển từ 3 đến 7), hàng đích sẽ di chuyển lên trên.
Lưu ý: Xem t he Nhân viên ID giá trị để đặt nó làm đầu mối cho việc ListItem chuyển xuống hoặc di chuyển lên khi chúng tôi sắp xếp lại ListItem.
Tôi đã đề cập đến ListItem ở khắp mọi nơi trong các hoạt động kéo-thả. ListItem chỉ tham chiếu đến Cột đầu tiên của Hàng ListView. Các giá trị cột khác là ListSubItems hoặc các mục con của ListItem. Điều đó có nghĩa là bạn sẽ chỉ có thể Kéo và Thả Cột đầu tiên. Các cột hoặc ListSubItems khác sẽ được di chuyển trong ListItem với mã VBA.
Điều này đúng nếu bạn chưa bật FullRowSelection trên Trang thuộc tính Điều khiển ListView trên Chung Tab.
Nếu được bật, bạn có thể chọn bất kỳ cột nào, nhưng Hệ thống đề cập đến Chỉ mục ListItem cho mục đích sắp xếp lại Hàng. So sánh hai hình ảnh trên với một bộ hai hình ảnh mẫu khác, hình ảnh thứ ba và thứ tư từ đầu trang này.
Hành động Kéo và Thả sẽ không hoạt động nếu hai giá trị thuộc tính sau không được Đặt trên Trang Thuộc tính Điều khiển ListView trên Chung Tab:
- ccOLEDragAutomatic =1
- ccOLEDropManual =1
Năm câu lệnh tiếp theo sẽ di chuyển ListSubItems, nếu có, vào ListItem mới được tạo ở vị trí mới.
Tiếp theo, ListItem mới tạo được tô sáng.
Tiếp theo, tất cả các đối tượng tạm thời được tạo sẽ bị xóa khỏi bộ nhớ.
Lưu ý: Một điểm quan trọng khác cần lưu ý ở đây là sự sắp xếp này là tạm thời và bị mất khi bạn đóng Biểu mẫu hoặc tải một Bảng / Truy vấn khác trên Điều khiển ListView.
Nếu chúng ta muốn thứ tự đã thay đổi của ListItems vẫn tồn tại vĩnh viễn hoặc cho đến khi thứ tự được thay đổi vào lần sau, thì chúng ta phải có thể cập nhật số thứ tự được lập chỉ mục hiện tại trên chính bảng đó. Chúng tôi đã thêm một trường Số nguyên mới với ID tên trường trên Bảng Nhân viên.
Màn hình mẫu với dữ liệu Nhân viên được sắp xếp lại theo thứ tự bảng chữ cái được đưa ra dưới đây:
Vì trường ID nhân viên là trường Đánh số tự động và được liên kết với các bảng có liên quan khác, chúng tôi đã thêm Trường số mới với ID tên trường. Giá trị trường này được đặt ban đầu bằng các số thứ tự giống nhau từ ID nhân viên theo cách thủ công. Giá trị trường này ban đầu sẽ theo thứ tự này. Tuy nhiên, dữ liệu ListView Rows có thể thay đổi thứ tự của chúng khi bạn sắp xếp lại dữ liệu trên ListView Control do hành động Kéo và Thả.
Nhìn vào Nhân viênQ Truy vấn SQL được cung cấp bên dưới:
SELECT [FirstName] & " " & [LastName] AS EmployeeName, Employees.ID, Employees.EmployeeID, Employees.TitleOfCourtesy, Employees.Title, Employees.Address, Employees.City, Employees.Region, Employees.PostalCode, Employees.Country, Employees.HomePhone, Employees.Extension, Employees.Notes FROM Employees ORDER BY Employees.ID;
Truy vấn trên được sử dụng làm Nguồn dữ liệu cho Điều khiển ListView và chúng được sắp xếp trên Trường ID. Trường ID được cập nhật với thứ tự thay đổi của Số chỉ mục trên Điều khiển ListView. Quá trình cập nhật chạy từ Form_Unload () Quy trình sự kiện khi bạn đóng Biểu mẫu. Phương pháp này đảm bảo rằng khi bạn mở Điều khiển ListView vào lần tiếp theo, dữ liệu sẽ theo thứ tự bạn đã sắp xếp lại lần trước.
Form_Unload () Quy trình sự kiện Mã VBA.
Private Sub Form_Unload(Cancel As Integer) Dim lvItem As ListItem Dim tmp As Long Dim criteria As String Dim strfield As String Dim fld As String If strTable = "" Then Set lvwList = Nothing Exit Sub End If Set db = CurrentDb Set rst = db.OpenRecordset(strTable, dbOpenDynaset) For Each lvItem In lvwList.ListItems tmp = lvItem.Index strfield = lvwList.ColumnHeaders(1).Text 'EmployeeName criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34) rst.FindFirst criteria If Not rst.NoMatch Then If (rst.Fields(strfield).Value = lvItem.Text) And (rst.Fields(1).Value = tmp) Then 'GoTo nextitem Else rst.Edit rst.Fields(1).Value = tmp 'replace ID number rst.Update End If Else MsgBox "Item: " & tmp & " Not Found!" End If Next rst.Close Set lvwList = Nothing Set lvItem = Nothing Set rst = Nothing Set db = Nothing End Sub
Kiểm tra Tên nhân viên Giá trị trường trong hình ảnh trên. Chúng được sắp xếp theo thứ tự bảng chữ cái. Giá trị trường ID mới trên Bảng Nhân viên sẽ được cập nhật với chuỗi số chỉ mục Danh mục Kiểm soát ListView hiện tại của họ.
Nếu bạn lưu ý những điểm sau, bạn có thể dễ dàng hiểu những gì chúng tôi làm với đoạn mã trên:
-
Văn bản của ListItem (cột đầu tiên) giá trị tham số là tên nhân viên và được sắp xếp theo thứ tự bảng chữ cái.
-
ListItems trên ListView Control có số chỉ mục từ 1 đến 9 theo thứ tự hiển thị trên màn hình, tức là số chỉ mục của mục đầu tiên là 1 và mục cuối cùng là 9. Dữ liệu gốc trên giá trị trường ID Bảng Nhân viên không phải là theo thứ tự này.
-
Chúng tôi lấy Văn bản Giá trị (Tên nhân viên) của ListItem đầu tiên và tìm kiếm tên trên bảng.
-
Khi bản ghi được tìm thấy, số Chỉ mục của ListItem hiện tại được cập nhật (thay thế) trên trường ID trên bảng.
-
Quá trình này được lặp lại cho tất cả các bản ghi còn lại trên bảng.
Hãy để chúng tôi xem qua Mã VBA. Ở phần đầu, chúng ta kiểm tra xem Bảng / Truy vấn dữ liệu nguồn đã được tải vào Điều khiển ListView hay chưa?
Nếu strTable Biến không được khởi tạo bằng tên Truy vấn thì Điều khiển ListView sẽ trống. Nếu trường hợp này xảy ra thì người dùng đã mở Biểu mẫu và đóng Biểu mẫu mà không chọn tên Truy vấn để tải dữ liệu vào điều khiển ListView. Form_Unload Thủ tục sự kiện bị hủy bỏ tại thời điểm này và đóng biểu mẫu.
Nếu điều khiển ListView có dữ liệu thì bước tiếp theo được thực hiện và mở truy vấn dữ liệu nguồn Nhân viên để cập nhật.
Bước tiếp theo là xem qua từng ListItem và cập nhật số chỉ mục trong trường ID của bản ghi Nhân viên.
Đầu tiên, số chỉ mục hàng hiện tại được lưu trong tmp Biến đổi.
Tên lvwList.ColumnHeader đầu tiên EmployeeName và tên của nhân viên được lấy từ ListItem.Text thành một biểu thức trong Tiêu chí biến chuỗi, như EmployeeName ="Andrew Fuller".
Tiêu chí tìm kiếm đầu tiên lệnh tìm kiếm bảng dữ liệu Nguồn để tìm bản ghi có tên đã cho. Khi bản ghi được tìm thấy, số Chỉ mục ListItem hiện tại được cập nhật trên Trường ID.
Quá trình này được lặp lại cho tất cả các hàng trên Điều khiển ListView và khi hoàn thành, Biểu mẫu sẽ được đóng.
Lần tới khi bạn tải các bản ghi từ Truy vấn này vào Điều khiển ListView, chúng sẽ được hiển thị theo thứ tự giống như khi bạn đóng biểu mẫu lần trước.
Lưu ý:Ở đây Truy vấn trở nên cần thiết để sắp xếp dữ liệu trên trường ID và hiển thị chúng theo thứ tự đã thay đổi trên Điều khiển ListView.
Tất cả công việc này là để lưu dữ liệu theo thứ tự được sắp xếp cuối cùng để lần sau khi bạn mở Biểu mẫu, dữ liệu trên Điều khiển ListView sẽ theo thứ tự đó.
Windows Explorer Giống như Phương pháp Sắp xếp.
Trong Windows Explorer, bạn có thể sắp xếp danh sách được hiển thị theo Thứ tự Tăng dần hoặc Giảm dần bằng cách nhấp vào bất kỳ Tiêu đề Cột nào. Tiêu đề Cột sẽ hoạt động giống như Nút chuyển đổi. Các nhấp chuột lặp lại vào Tiêu đề Cột sẽ Sắp xếp dữ liệu cột theo Thứ tự Tăng dần / Giảm dần theo ListView1_ColumnClick () sau Thủ tục sự kiện:
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object) ' When a ColumnHeader object is clicked, the ListView control is ' sorted by the subitems of that column. With Me.ListView1 ' Set the SortKey to the Index of the ColumnHeader - 1 .SortKey = ColumnHeader.Index - 1 If .SortOrder = lvwAscending Then .SortOrder = lvwDescending Else .SortOrder = lvwAscending End If ' Set Sorted to True to sort the list. .Sorted = True End With End Sub
Lưu ý: Sắp xếp tất cả dữ liệu chỉ ở chế độ so sánh văn bản. ListItems và ListSubItems Thêm () Tham số thứ ba của phương thức, thông tin được hiển thị trên Điều khiển ListView là Văn bản gõ phím. Giá trị Ngày và Số đều chỉ được coi là Văn bản.
Windows Explorer lưu thứ tự sắp xếp cuối cùng của các mục trong thư mục. Khi chúng ta mở lại thư mục đó, danh sách sẽ được hiển thị theo thứ tự đã sắp xếp trước đó.
Với Form_Unload () Quy trình sự kiện, tính năng này của Windows Explorer có thể thực hiện được trên Bảng nhân viên. Khi bạn đóng Biểu mẫu sau khi sắp xếp trên bất kỳ cột nào mà trình tự thứ tự đã lập chỉ mục sẽ được lưu trên Bảng nhân viên trong trường ID. Truy vấn NVQ luôn sắp xếp dữ liệu trên trường ID khi được mở.
Cơ sở dữ liệu Demo được đính kèm để Tải xuống. Có hai hình thức demo trong Cơ sở dữ liệu. Biểu mẫu đầu tiên minh họa việc mở Bảng và Truy vấn trong Điều khiển ListView để xem dữ liệu trong Dạng xem Biểu dữ liệu. Biểu mẫu thứ hai chỉ sử dụng Nhân viênQ Chỉ truy vấn để Kéo, Thả, Sắp xếp và lưu thứ tự sắp xếp cuối cùng của dữ liệu để sử dụng trong tương lai.
- Hướng dẫn điều khiển ActiveX ListView-01.
- Hướng dẫn điều khiển ListView-02.
- Gán hình ảnh cho các mục trong ListView.
- Kiểm soát ListView Sự kiện Sắp xếp Kéo-Thả
- Kiểm soát ListView với MS-Access TreeView
- Sự kiện kéo thả trên TreeView / ListView Controls