Access
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Access

Kiểm soát ListView Sự kiện Sắp xếp Kéo-Thả

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ế.

  1. 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 .

  2. Lưu Bảng với tên lvTables (lv là viết tắt của ListView).

  3. Mở Bảng trong Dạng xem Biểu dữ liệu.

  4. 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.

  5. Tạo và mở một Biểu mẫu mới trong Dạng xem Thiết kế.

  6. 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 .

  7. Thay đổi nhãn con Chú thích giá trị thành Bảng .

  8. 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.

  9. 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.

  10. 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 .

  11. 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.

  12. 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.

  13. 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 .

  14. 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 .

  15. 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.

  16. 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 (), 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 () 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, 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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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 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 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.



  1. Hướng dẫn điều khiển ActiveX ListView-01.
  2. Hướng dẫn điều khiển ListView-02.
  3. Gán hình ảnh cho các mục trong ListView.
  4. Kiểm soát ListView Sự kiện Sắp xếp Kéo-Thả
  5. Kiểm soát ListView với MS-Access TreeView
  6. Sự kiện kéo thả trên TreeView / ListView Controls

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Giới thiệu về Bảo trì Hồ sơ

  2. Cách mở bảng ở dạng xem thiết kế trong Microsoft Access

  3. Cách thay đổi màu nền của tiêu đề biểu mẫu trong Access 2016

  4. Cách đổi tên bảng trong Microsoft Access

  5. Giải pháp thay thế cho DCount và DLookup với MS SQL Server Backend