sql >> データベース >  >> RDS >> Access

ListViewコントロールのドラッグドロップソートイベント

    ListViewControlでのデータの行の再配置。

    このチュートリアルの前のエピソードでは、次の機能を有効にして列を再配置する方法を学びました: AllowColumnReorder プロパティシートのオプション。ただし、行の再配置は、ドラッグして別の行に配置することで実行されます。 ListViewコントロール行を再配置するには、ListItemのドラッグアンドドロップアクションで、プロパティシートでこの機能を有効にする必要があります。ただし、これだけでは機能しません。アイテムを必要な順序に並べ替えるには、VBAコードが必要です。

    この演習では、データベースにコントロールとVBAコードを含むサンプルアクセスフォームを作成しましょう。 ListBoxおよびListViewコントロールを備えたフォームのサンプル画像を以下に示します。

    リストボックスにテーブルとクエリ(アクションクエリではない)のリストを作成しました。リストアイテムの1つを選択すると、DataSheetビューに表示されるように、レコードがListViewコントロールに即座に表示されます。

    設計タスク。

    1. DataListというフィールド名で単一のテキストフィールドを持つ新しいテーブルを作成します 。

    2. lvTablesという名前でテーブルを保存します (lvはListViewを表します)。

    3. データセットビューでテーブルを開きます。

    4. いくつかのテーブル名を追加し、データベースからテーブルにクエリ名を選択します。リストのNorthwindサンプルデータベースからテーブルをインポートしました。

      注: 添付ファイル ListViewControlのフィールドが無効です。添付ファイルフィールドのあるテーブルの選択クエリを作成し、添付ファイルフィールドを除くすべてのフィールドを選択します。

    5. デザインビューで新しいフォームを作成して開きます。

    6. フォームにリストボックスコントロールを挿入し、プロパティシートを表示して、その名前を変更します。 List0へのプロパティ値 。

    7. 子ラベルを変更するキャプション テーブルの値 。

    8. ListBoxコントロールのプロパティシートを表示し、行ソースを設定します lvTablesへのプロパティ値 名前。

    9. 行ソースタイプがテーブル/クエリとして設定されており、バインドされた列のプロパティ値が1であるかどうかを確認します。異なる場合は変更します。

    10. ActiveXコントロールリストからListViewコントロールを挿入し、そのNameプロパティ値を ListView1に変更します。 。

    11. 上記のデモフォームの画像に示されているように、両方のコントロールのサイズを変更します。

    12. コントロールの上にラベルを挿入し、その名前とキャプションのプロパティ値を見出しに変更します。 リストボックスからテーブルまたはクエリを選択すると、キャプション値がvbaコードから変更されます。

    13. コントロールの下にコマンドボタンを作成し、そのNameプロパティ値を cmdCloseに変更します。 Captionプロパティ値を閉じる

    14. ListViewコントロールを右クリックし、ListViewCtrlオブジェクトを強調表示します オプションを選択し、プロパティを選択します 。

    15. 一般の設定と一致するようにプロパティ設定を変更します 以下のタブ画像。

    16. ListViewコントロールのプロパティシートの画像-一般的なタブビューを以下に示します:

      これらのオプションのいくつかは、以前のセッションですでに設定しています。ここでは、ドラッグドロップアクションに次のオプションが必要です。

      • OLEDragAutomatic-1

      • OLEDropManual-1

      • FullRowSelect-True

      • HotTracking-True

    上記の設定がプロパティシートと一致していることを確認してから、フォームを保存してください。

    フォームのVBAモジュールを表示します。

    フォームモジュールのVBAコード。

    次のVBAコードをコピーしてモジュールに貼り付け、既存のコード行がある場合は上書きします。

    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
    
    

    新しく追加されたサブルーチンListView1_OLEDragOver()、ListView1_OLEDragDrop()、Form_Unload()、を除いて、上記のVBAコードに精通しています。 およびListView1_ColumnClik() 手順。最初の2つの手順は、アイテム(行)をドラッグして別のアイテムの上にドロップし、新しい場所に挿入するのに役立ちます。プロシージャForm_Unload()およびListView1_ColumnClick()は、アイテムを並べ替えます。

    次の画像は、実行シーケンスでのドラッグアンドドロップアクションを示しています

    以下の最初の画像は、ドラッグアンドドロップアクションシーケンスを示しています。 EmployeeID 7のListItemはユーザーによって上にドラッグされ、ID3のListItemの上にドロップされます。

    2番目の画像は、ListItemの逆順の移動を示しています。

    マウスポインタがドラッグされたアイテムのある行の上を移動すると、ソース行とターゲット行の間で、上に行く途中で次々にハイライト表示されます。

    写真のドラッグアンドドロップアクション。

    従業員ID7の行は、上記の従業員ID3のアイテムにドロップされます。

    VBAコードのセグメントごとの分析。

    ListBoxからのアイテム選択List0_Click()イベントプロシージャが実行され、レコードがListViewコントロールにロードされます。

    Private Sub List0_Click()
    Dim strTable As String
    
    strTable = List0.Value
    
      Call LoadListView(strTable)
    
    End Sub

    選択したテーブル/クエリ名がstrTableに保存されます 文字列変数。 LoadListView() サブルーチンは、パラメーターとしてstrTable変数を使用して実行されます。以前のセッションでこのコードを複数回確認しました。詳細については、このページの下部にあるリンクを使用してこれらのページにアクセスしてください。このコードで私が行ったいくつかの小さな変更が見つかるかもしれません。

    このエピソードでは、ImageListコントロールを使用していません。 Icon、SmallIcon ListItems.Add()メソッドおよび ReportIcon、TooltipTextのパラメーター値 ListSubItems.Add()メソッドのパラメーター値も使用されません。

    ListView1_OLEDragOver()で何が起こっているかを見てみましょう およびListView1_OLEDragDrop() VBAコードセグメント。

    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 

    この手順は、行をクリックして押したまま、ターゲット行に向かう途中で他の行をドラッグして移動しようとすると、自動的に実行されます。ドラッグアクションは、強調表示される別の行に移動します。

    ListView1.HitTest(x、y) 関数は、ListViewコントロール上の行の位置を決定するx、y座標を読み取り、その行を強調表示します。このプロセスは、他の行の上にあるときに、マウスボタンを離してターゲット行にドロップするまで続きます。ドロップアクションは、 ListView1_OLEDragDrop()をトリガーします プロシージャを実行し、ソース行の切り替えプロシージャを実行します。

    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

    この手順を部分的に確認し、そこで何が起こっているのかを理解しましょう。次のコードセグメントは、ドラッグアンドドロップアクションを処理するために必要なオブジェクト変数を宣言しています。

    '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
    

    最初の3つのListItem一時オブジェクトは異なる名前で宣言します。

    lvwDrag ListItemオブジェクトは、新しい場所にドラッグするために選択した行のコピーを保持します。

    lvwDrop ListItemオブジェクトは、ドラッグされたリストアイテムをドロップした行の参照を保存します。

    ListItemsアクションの切り替え中に、元の場所からソースアイテムを削除してから、ソースのListItemインデックス番号を使用してターゲットの場所に作成します。この新しいListItemの参照は、 lvwTargetに保存されます ListItemオブジェクト変数。

    lvwSub Forでシーケンスオブジェクト変数として宣言された変数。 。 。次へ ループ。このループでは、lvwDragオブジェクトからListSubItems(2列目以降)を1つずつ順番に並べる必要があります。元のListItemを削除しましたが、そのコピーをlvwDragListItemオブジェクトに保存しました。

    lvwDropListItemインデックス番号はintTgtIndexに保存されます 可変。

    lvwList.HitTest(x、y) 関数は、ListViewコントロールのx、y座標を読み取り、ソースListItemをドロップしたターゲットListItemを識別し、lvwDropオブジェクトにそのコピーを作成します。

    新しい位置にドラッグする前に、まずListItemを選択します。

    lvwList.SelectedItem プロパティはTrueに設定されます。このプロパティステータスを使用して、選択したListItemのコピーを lvwDragに作成します。 ListItemオブジェクト。次のコードセグメントは、ソースとターゲットの両方のListItemオブジェクトを検証します。

    ドラッグアンドドロップアクションの検証チェック。

    '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
    

    上記のコードセグメントは、ドラッグアンドドロップアクションを検証します。これらのアクションが有効なアイテムで開始または終了しなかった場合、lvwDropまたはlvwDragオブジェクト、あるいはその両方が空になります。または、ユーザーが行を上下に移動するときに別の無効な移動が発生する可能性がありますが、気が変わって同じ行にドロップする可能性があります。このような間違った動きを検出すると、プログラムは終了します。

    上記のテストが有効であることが証明された場合、プログラムは行を再配置するために次の手順を実行し続けます。

    '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

    上記の9行の実行可能コード(他の行はコメントです)のアクションはやや簡単です。

    intTgtIndex =lvwDrop.Index ステートメントは、ターゲットListItemのインデックス番号を intTgtIndexに保存します 可変。

    ソース行listItemは一時オブジェクトlvwDragにすでに保存されているので、次のステップは、ListViewコントロールからソースListItemを削除することです。 ListItems.Remove()プロシージャ ステートメントlvwList.ListItems.RemovelvwDrag.Index を使用して、が呼び出されます。 。

    つまり、ドラッグアンドドロップアクションは、ListItemを元の場所から削除し、ターゲット行のインデックス番号を使用してターゲットの場所に再度作成することです。

    ステートメントSetlvwTarget =lvwList.ListItems.Add(intTgtIndex、、lvwDrag.Text) ターゲットロケーションインデックス番号intTgtIndexとTextを使用して新しいListItemを作成します 以前にlvwDragオブジェクトに保存されたSourceListItemの値。

    ListItemを初めて作成するときは、インデックスとテキストの2つの値のみを使用しました。 パラメータ値。他のパラメータオプションキー、アイコンは使用していません およびSmallIcon それ以外の場合は、lvwDragオブジェクトからもこれらのパラメータ値を含める必要があります。

    上記のドラッグドロップの例の画像に従って、7番目のListItemを移動し、3番目のListItemにドロップしました。その後、ListViewコントロールから7番目のアイテム(またはソースListItem)を削除しました。ターゲットインデックス番号3の新しいListItemを作成しました。

    これで、同じインデックス番号3の2つのアイテムがあり、既存のアイテムはインデックス番号3で、新しいアイテムはインデックス番号3で作成しました。他のすべての情報はlvwDragオブジェクト(またはlvwDragに保存された7番目のListItem)から取得されます。以前のオブジェクト)。

    システムは、既存のListItem3以降を次のシーケンス番号3,4,5に自動的にインクリメントします。 。 。 4,5,6に。 。 。前方に移動して、入ってくるアイテムを間に挿入するためのスペースを確保します。

    行を削除して別の場所に作成した場合の影響。

    ListItem番号3を上からドラッグしてアイテム番号7にドロップするなど、逆の順序で移動するとします。

    当然、3番目のアイテムを削除し、新しい場所にインデックス番号7の新しいアイテムを作成しようとします。アイテム番号3が削除されると、アイテム番号4以降が上にシフトするか、4,5,6,7,8,9が3,4,5,6,7,8(すべてのアイテムを順番に作成するため)またはそれ以前になります。インデックス番号7のアイテムは6になります。

    インデックス番号7の新しいアイテムを作成すると、既存の7,8は再び8,9になります。行の削除と作成時に行の移動を監視する場合、最初の例では、ターゲット行を下に移動して、着信アイテムに道を譲ります。説明した2番目の例(3から7に移動)では、宛先行が上に移動します。

    注: 見る ListItemを再配置するときにListItemが下に移動したり上に移動したりするための手がかりとして配置するための従業員ID値。

    ドラッグドロップ操作の至る所でListItemについて言及しました。 ListItemは、ListView行の最初の列のみを参照します。他の列の値は、ListSubItemsまたはListItemの子アイテムです。つまり、最初の列のみをドラッグアンドドロップできます。他の列またはListSubItemsは、VBAコード付きのListItemの下に移動されます。

    これは、 FullRowSelectionを有効にしていない場合に当てはまります。 一般のListViewコントロールプロパティシート タブ。

    有効にすると、任意の列を選択できますが、システムは行の並べ替えの目的でListItemインデックスを参照します。上記の2つの画像を、このページの上部にある3番目と4番目の画像の2つのサンプル画像の別のセットと比較します。

    一般のListViewコントロールプロパティシートで次の2つのプロパティ値が設定されていない場合、ドラッグアンドドロップアクションは機能しません。 タブ:

    • ccOLEDragAutomatic =1
    • ccOLEDropManual =1

    次の5つのステートメントは、 ListSubItemsを移動します もしあれば、新しい場所に新しく作成されたListItemに。

    次に、新しく作成されたListItemが強調表示されます。

    次に、作成されたすべての一時オブジェクトがメモリからクリアされます。

    注: ここで注意すべきもう1つの重要な点は、この配置は一時的なものであり、フォームを閉じるか、ListViewコントロールに別のテーブル/クエリをロードすると失われることです。

    ListItemsの変更された順序を永続的にしたい場合、または次に順序が変更されるまで、テーブル自体の現在のインデックス付き注文番号を更新できる必要があります。 Employeesテーブルにフィールド名IDを持つ新しい整数フィールドを追加しました。

    従業員データをアルファベット順に並べ替えたサンプル画面を以下に示します。

    従業員IDフィールドは自動番号フィールドであり、他の関連テーブルとリンクされているため、フィールド名IDを持つ新しい番号フィールドを追加しました。このフィールド値は、最初は従業員IDと同じシーケンス番号で手動で設定されます。このフィールド値は、最初はこの順序になります。ただし、ドラッグアンドドロップアクションにより、ListViewコントロールでデータを再配置すると、ListView行のデータの順序が変わる場合があります。

    EmployeesQを見てください 以下に示すSQLのクエリ:

    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;
    

    上記のクエリは、ListViewコントロールのデータソースとして使用され、IDフィールドで並べ替えられます。 IDフィールドは、ListViewコントロールのインデックス番号の変更された順序で更新されます。更新プロセスはForm_Unload()から実行されます フォームを閉じるときのイベント手順。この方法により、次回ListViewコントロールを開いたときに、データが前回並べ替えた順序になります。

    Form_Unload() イベントプロシージャ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

    従業員名を確認してください 上の画像のフィールド値。それらはアルファベット順に並べられています。 Employeesテーブルの新しいIDフィールド値は、現在のListViewControlListItemインデックス番号シーケンスで更新されます。

    次の点に注意すると、上記のコードで何が行われるかを簡単に理解できます。

    1. ListItemの(最初の列)テキスト パラメータ値は従業員名であり、アルファベット順に並べられています。

    2. ListViewコントロールのListItemには、画面に表示される順序で1から9までのインデックス番号があります。つまり、最初のアイテムのインデックス番号は1で、最後のアイテムのインデックス番号は9です。EmployeesTableIDフィールド値の元のデータはこの順序で。

    3. テキストを取得します 最初のListItemの値(従業員名)を入力し、テーブルで名前を検索します。

    4. レコードが見つかると、現在のListItemのインデックス番号がテーブルのIDフィールドで更新(置換)されます。

    5. このプロセスは、テーブルの残りのすべてのレコードに対して繰り返されました。

    VBAコードを見てみましょう。最初に、ソースデータテーブル/クエリがListViewコントロールにロードされたかどうかを確認しますか?

    strTableの場合 変数がクエリ名で初期化されていない場合、ListViewコントロールは空です。この場合、ユーザーはフォームを開いて、クエリ名を選択せず​​にフォームを閉じて、データをListViewコントロールにロードします。 Form_Unload イベントプロシージャはこの時点で中止され、フォームを閉じます。

    ListViewコントロールにデータがある場合、次のステップが実行され、ソースデータクエリEmployeesQを開いて更新します。

    次のステップは、各ListItemを調べて、EmployeesレコードのIDフィールドのインデックス番号を更新することです。

    まず、現在の行インデックス番号が tmpに保存されます 可変。

    最初のlvwList.ColumnHeader名EmployeeName と従業員の名前 ListItem.Textから取得されます 基準の式に EmployeeName ="AndrewFuller"のような文字列変数。

    rst.FindFirst Criteria コマンドは、ソースデータテーブルを検索して、指定された名前のレコードを見つけます。レコードが見つかると、現在のListItemインデックス番号がIDフィールドで更新されます。

    このプロセスは、ListViewコントロールのすべての行に対して繰り返され、終了するとフォームが閉じられます。

    次回、このクエリからListViewコントロールにレコードをロードすると、前回フォームを閉じたときと同じ順序でレコードが表示されます。

    注: IDフィールドのデータを並べ替えて、ListViewコントロールに変更された順序で表示するには、ここでクエリが必要になりました。

    この作業はすべて、最後に並べ替えられた順序でデータを保存するためのものでした。これにより、次にフォームを開いたときに、ListViewコントロールのデータがその順序になります。

    Windowsエクスプローラーのような並べ替え方法。

    Windowsエクスプローラーでは、任意の列見出しをクリックして、表示されたリストを昇順または降順で並べ替えることができます。列ヘッダーは、トグルボタンのように機能します。列ヘッダーを繰り返しクリックすると、列データが次の ListView1_ColumnClick()で昇順/降順で並べ替えられます。 イベント手順:

    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

    注: すべてのデータの並べ替えは、テキスト比較モードのみです。 ListItems およびListSubItems Add() メソッドの3番目のパラメーターであるListViewコントロールに表示される情報はテキストです。 タイプ。日付と数値はすべてテキストのみとして扱われます。

    Windowsエクスプローラーは、最後に並べ替えられたアイテムの順序をフォルダーに保存します。そのフォルダを再度開くと、リストは以前にソートされた順序で表示されます。

    Form_Unload()を使用 イベント手順Windowsエクスプローラーのこの機能は、従業員テーブルで可能になります。列を並べ替えた後でフォームを閉じると、インデックス付けされた順序シーケンスが従業員テーブルのIDフィールドに保存されます。 EmployeesQクエリは、開いたときに常にIDフィールドのデータを並べ替えます。

    デモデータベースはダウンロード用に添付されています。データベースには2つのデモフォームがあります。最初のフォームは、データセットビューでデータを表示するためにListViewコントロールでテーブルとクエリを開く方法を示しています。 2番目のフォームは、 EmployeesQのみを使用します ドラッグ、ドロップ、並べ替え、および将来の使用のためにデータの最後の並べ替え順序を保存するために、単独でクエリを実行します。



    1. ActiveX ListViewControlTutorial-01。
    2. ListViewコントロールチュートリアル-02。
    3. ListViewアイテムへの画像の割り当て。
    4. ListViewコントロールのドラッグドロップソートイベント
    5. MS-AccessTreeViewを使用したListViewコントロール
    6. TreeView/ListViewはドラッグドロップイベントを制御します

    1. SQL Server(T-SQL)の既存のテーブルに外部キー制約を追加する方法

    2. 特定のID値によるMysqlの順序

    3. Dockerコンテナ上のPostgreSQLデータベースに接続します

    4. SQL ORDER BY