Access
 sql >> Baza danych >  >> RDS >> Access

Obsługa zdarzeń przeciągania i upuszczania kontrolki ListView

Wprowadzenie.

Znamy operacje przeciągania i upuszczania w kontrolce TreeView w programie Ms-Access, który zmienia rozmieszczenie węzłów. Wszystkie rekordy podstawowe dla węzłów kontrolnych Treeview pochodzą z jednej tabeli dostępu. Zawsze aktualizujemy Identyfikator rodzica węzła źródłowego wartość pola, z wartością identyfikatora węzła docelowego w tym samym rekordzie tabeli, aby dokonać zmiany pozycji w kontrolce TreeView. Zapisy nie są fizycznie nigdzie przenoszone.

Tutaj, po dodaniu kontrolki ListView wraz z kontrolką TreeView, planujemy pracować z dwiema różnymi tabelami dostępu.

  1. lvCategory – Kod i opis kategorii.
  2. lvProducts – Produkty z uwzględnieniem kategorii.

W ten sposób łatwiej jest zrozumieć relacje między obiema tabelami. Jakie zmiany musimy wprowadzić i gdzie, kiedy jeden element produktu (element ListView) zostanie przeniesiony z jednej kategorii do drugiej w kontrolce TreeView.

lvCategory Tabela dostępu zawiera 20 rekordów dla węzłów TreeView i lvProducts Tabela ma 45 dla kontrolki ListView. Co najmniej jeden rekord w tabeli Produkty jest bezpośrednio powiązany z kategorią produktu w tabeli Kategoria. Relacja między nimi została zaktualizowana o wartość pola identyfikatora kategorii (CID) w ParentID tabeli produktów tak, aby zmiana kategorii produktu odzwierciedlała się natychmiast w kontrolce ListView.

Tabela danych demonstracyjnych została pobrana z Microsoft Access Sample Database Northwind.accdb i podzielona na dwie części.

Na podstawie wartości pola ParentID, rekordów lvProduct, możemy filtrować i wyświetlać wszystkie powiązane elementy produktów w kontrolce ListView, gdy węzeł kategorii zostanie wybrany w kontrolce TreeView.

Tematy, które omówiliśmy do tej pory.

Poniżej znajdują się główne tematy w TreeView , Lista obrazów , ImageCombo, i ListView Sterowanie, które omówiliśmy do tej pory w MS-Access:

  1. Samouczek sterowania Microsoft TreeView
  2. Tworzenie menu dostępu za pomocą TreeView Control
  3. Przypisywanie obrazów do kontrolki TreeView
  4. Przypisywanie obrazów do TreeView Control-2
  5. Kontrola TreeView Zaznacz opcję Dodaj usuń węzły
  6. Rozwijane menu dostępu TreeView ImageCombo
  7. Ponownie rozmieszczaj węzły TreeView przez przeciąganie i upuszczanie
  8. Kontrola ListView z MS-Access TreeView

Zadanie przeciągania ListView.

Jeśli chodzi o operację przeciągania i upuszczania ListView, jest to proste ćwiczenie porównujące tę samą metodę w samej kontrolce TreeView. Ponieważ akcja Drag Drop obejmuje zarówno kontrolki TreeView, jak i ListView, używamy tej samej procedury zdarzenia TreeView0_OLEDragDrop() z prostym kodem VBA.

Elementy produktu wymienione w kontrolce ListView należą do bieżącego elementu kategorii wybranego w kontrolce TreeView.

Użytkownik wybiera określony element produktu z kontrolki ListView, jeśli uważa, że ​​należy on do innego elementu kategorii, a następnie przeciągnij go i upuść na docelowy element kategorii w kontrolce TreeViewC.

Przeniesiony element produktu ListView zostanie dodany do listy elementów należących do zmienionej kategorii. Wartość pola ParentID rekordu produktu zostanie zaktualizowana o docelowy identyfikator rekordu kategorii (wartość CID).

Jest to tylko akcja jednokierunkowa, zawsze przenieś element ListView z jednej kategorii i upuść go w innym węźle kategorii w kontrolce TreeView.

Demo ListView przeciągnij i upuść Formularz dostępu frmListViewDrag’ s próbne uruchomienie Obraz ekranu jest podany poniżej:

Na powyższym obrazku Napoje Wybrano kategorię w TreeView. Produkty należące do kategorii Napoje zostały wymienione w kontrolce ListView.

Widok projektu powyższego formularza:

Lista nazw kontroli w formularzu jest podana poniżej:

  1. Kontrola TreeView:TreeView0
  2. Kontrola ListView:ListView0
  3. Kontrola ImageList:ImageList3
  4. Przycisk polecenia:cmdClose

Kod VBA na frmListViewDrag Moduł klasowy:

Option Compare Database
Option Explicit

Dim tv As MSComctlLib.TreeView
Dim lvList As MSComctlLib.ListView
Dim imgList As MSComctlLib.ImageList
Const Prfx As String = "X"

Private Sub Form_Load()
Dim db As DAO.Database
Dim tbldef As TableDef

    Set tv = Me.TreeView0.Object
    tv.Nodes.Clear
    
    Set imgList = Me.ImageList3.Object
    
With tv
    .Font.Size = 9
    .Font.Name = "Verdana"
    .ImageList = imgList 'assign preloaded imagelist control
 End With
    
    Set lvList = Me.ListView0.Object
    lvList.ColumnHeaders.Clear
    lvList.ListItems.Clear
    lvList.Icons = imgList
    
    Set db = CurrentDb
    Set tbldef = db.TableDefs("lvProducts")
    
    'Initialize ListView & Column Headers Property Values
     With lvList
        .ColumnHeaderIcons = imgList
        .Font.Size = 9
        .Font.Name = "Verdana"
        .Font.Bold = False
        
        'ColumnHeaders.Add() Syntax:
        'lvList.ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon
        'Alignment: 0 - Left, 1 - Right, 2 - Center
        .ColumnHeaders.Add 1, , tbldef.Fields(1).Name, 2600, 0, 5
        .ColumnHeaders.Add 2, , tbldef.Fields(3).Name, 2600, 0, 5
        .ColumnHeaders.Add 3, , tbldef.Fields(4).Name, 1440, 1, 5
    End With
    
    Set db = Nothing
    Set tbldef = Nothing

    
   LoadTreeView 'Create TreeView Nodes

End Sub

Private Sub LoadTreeView()
    Dim Nod As MSComctlLib.Node
    Dim firstCatID As Long
    Dim strCategory As String
    Dim strCatKey As String
    Dim strBelongsTo As String
    Dim strSQL As String
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    
    'Initialize treeview nodes
     tv.Nodes.Clear
     
    'Initialize Listview nodes
    While lvList.ListItems.Count > 0
          lvList.ListItems.Remove (1)
    Wend
    
    strSQL = "SELECT lvCategory.CID, lvCategory.Category, "
    strSQL = strSQL & "lvcategory.BelongsTo FROM lvCategory ORDER BY lvCategory.CID;"
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    If Not rst.BOF And Not rst.EOF Then
        rst.MoveFirst
        firstCatID = rst!CID
    Else
        Exit Sub
    End If
    ' Populate all Records as Rootlevel Nodes
    Do While Not rst.BOF And Not rst.EOF
            strCatKey = Prfx & CStr(rst!CID)
            strCategory = rst!Category
            
            Set Nod = tv.Nodes.Add(, , strCatKey, strCategory, 1, 2)
            Nod.Tag = rst!CID
        rst.MoveNext
    Loop
    
    'In the second pass of the the same set of records
    'Move Child Nodes under their Parent Nodes
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
        strBelongsTo = Nz(rst!BelongsTo, "")
        If Len(strBelongsTo) > 0 Then
            strCatKey = Prfx & CStr(rst!CID)
            strBelongsTo = Prfx & strBelongsTo
            strCategory = rst!Category
            
            Set tv.Nodes.Item(strCatKey).Parent = tv.Nodes.Item(strBelongsTo)
        End If
        rst.MoveNext
    Loop
    rst.Close
    
    ' Populate ListView Control with Product details
    ' of the first Category Item
    LoadListView firstCatID
    
End Sub


Private Sub LoadListView(ByVal CatID)
    Dim strProduct As String
    Dim strPKey As String
    Dim intcount As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim strSQL As String
    
    ' Initialize ListView Control
    While lvList.ListItems.Count > 0
        lvList.ListItems.Remove (1)
    Wend
   
     strSQL = "SELECT lvProducts.* FROM lvProducts "
     strSQL = strSQL & "WHERE (lvProducts.ParentID = " & CatID & ") "
     strSQL = strSQL & "ORDER BY lvProducts.[Product Name];"
    
    'Open filtered Products List for selected category
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    Do While Not rst.BOF And Not rst.EOF
        intcount = intcount + 1
        strProduct = rst![Product Name]
        strPKey = Prfx & CStr(rst!PID)
        
        'List Item Add() Syntax:
        'lvList.ListItems.Add Index,Key,Text,Icon,SmallIcon
        Set tmpLItem = lvList.ListItems.Add(, strPKey, strProduct, , 3) 'first column
            lvList.ForeColor = vbBlue
            
            'List second column sub-item Syntax:
            'tmpLItem.ListSubItems.Add Column - Index, Key, Text, ReportIcon, ToolTipText
            tmpLItem.ListSubItems.Add 1, strPKey & CStr(intcount), Nz(rst![Quantity Per Unit], ""), 6
            
            'List third column sub-item
            tmpLItem.ListSubItems.Add 2, strPKey & CStr(intcount + 1), Format(rst![list Price], "0.00"), 6, "In Local Currency."
        rst.MoveNext
    Loop
    
    Set db = Nothing
    Set rst = Nothing
    
    If intcount > 0 Then lvList.ListItems(1).Selected = True
    
End Sub

Private Sub TreeView0_NodeClick(ByVal Node As Object)
Dim Cat_ID As String
Cat_ID = Node.Tag

LoadListView Cat_ID

End Sub

Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long)
    Set tv.SelectedItem = Nothing
End Sub

Private Sub TreeView0_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer)
On Error GoTo TreeView0_OLEDragOver_Err

    Dim nodSelected As MSComctlLib.Node
    Dim nodOver As MSComctlLib.Node
    
    If tv.SelectedItem Is Nothing Then
        'Select a node if one is not selected
        Set nodSelected = tv.HitTest(X, Y)
        If Not nodSelected Is Nothing Then
            nodSelected.Selected = True
        End If
    Else
        If tv.HitTest(X, Y) Is Nothing Then
        'do nothing
        Else
            'Highlight the node the mouse is over
            Set nodOver = tv.HitTest(X, Y)
            Set tv.DropHighlight = nodOver
        End If
    End If
    
TreeView0_OLEDragOver_Exit:
Exit Sub

TreeView0_OLEDragOver_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragOver()"
Resume TreeView0_OLEDragOver_Exit
End Sub


Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Private Sub TreeView0_OLECompleteDrag(Effect As Long)
    Set tv.DropHighlight = Nothing
End Sub

Private Sub cmdClose_Click()
    DoCmd.Close
End Sub

Znane segmenty kodu VBA.

W Form_Load() Procedura zdarzenia, inicjujemy kontrolki TreeVew, ListView, ImageList. Tworzy nagłówki kolumn kontrolki ListView, przed wypełnieniem elementów List w kontrolce Listview. Na końcu tej procedury wywołujemy podprogram LoadTreeView().

LoadTreeView() podprogram wypełnia węzły kategorii produktów w kontrolce TreeView rekordami z lvCategory Stół. Ładowanie węzłów w kontrolce TreeView jest procesem dwuetapowym. Dlaczego tak jest, zamiast robić to za jednym zamachem? Ten aspekt został szczegółowo wyjaśniony na wcześniejszej stronie, 7. link na liście linków podanych powyżej, jeśli chcesz przez nią przejść. Powtórzenie ich wszystkich tutaj może nie być właściwe.

Na końcu powyższego podprogramu LoadListView() podprogram został wywołany z wartością CID pierwszego rekordu kategorii 1 jako parametr.

Rekordy produktów z wartością pola ParentID 1 zostały przefiltrowane i wymienione w kontrolce ListView. Ta procedura została szczegółowo wyjaśniona w poście z zeszłego tygodnia, 8. pozycja na liście linków podanej powyżej.

Podprogramy akcji przeciągnij i upuść.

Następujące podprogramy powiązane z akcją „Przeciągnij i upuść” zostaną wykonane automatycznie w kolejności przedstawionej poniżej:

  1. TreeView0_OLEStartDrag()
  2. TreeView0_OLEDragOver()
  3. TreeView0_OLEDragDrop()
  4. TreeView0_OLECompleteDrag()

Pierwsza i ostatnia podprogramy inicjują zaangażowane węzły i odpowiednio resetują ich status na końcu.

Drugi, podprogram OLEDragOver() działa jak procedura zdarzenia MouseMove i śledzi ruch myszy podczas operacji przeciągania i upuszczania. Podświetla NodeText, gdy mysz znajduje się nad węzłem i śledzi jego trajektorię do momentu zwolnienia lewego przycisku myszy.

Sam kod procedury TreeView0_OLEDragDrop() znajduje się poniżej.

Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Akcja przeciągania i upuszczania krok po kroku.

Procedura TreeView0_OLEDragDrop() jest wykonywana natychmiast po zwolnieniu lewego przycisku myszy w celu zakończenia akcji upuszczania. Na początku kodu odniesienia do aktywnego i docelowego węzła TreeView zostały zapisane w tv_nodSource i tv_nodTarget odpowiednio zmienne obiektowe.

Następnie sprawdzamy, czy element ListItem został upuszczony na prawidłowy węzeł TreeView, czy nie. Jeśli zostanie upuszczony na ten sam źródłowy węzeł kategorii lub na pusty obszar w kontrolce TreeView, to te ruchy nie są prawidłowe. Jeśli został upuszczony w pustym obszarze kontrolki TreeView, wówczas tv_nodTarget zmienna obiektu będzie zawierać wartość Nic. W takim przypadku wyświetla komunikat i wychodzi z Programu.

Następnie wartości klucza źródła i węzła docelowego TreeView są zapisywane w dwóch zmiennych łańcuchowych. Jeśli oba klucze są takie same, wówczas element ListItem został przeciągnięty i upuszczony na jego własny węzeł nadrzędny (węzeł kategorii) w kontrolce TreeView. Wykonywanie programu jest przerywane od dalszego kontynuowania.

Jeśli oba klucze są różne, nadszedł czas, aby zaktualizować zmianę w identyfikatorze rodzica rekordu produktu pole, z CID rekordu kategorii docelowej Kod i odśwież elementy ListView.

Wybrana wartość klucza ListItem (PID wartość pola) została zapisana w strListItemKey Zmienna łańcuchowa.

Rzeczywisty CID rekordu kategorii wartość pola została wyodrębniona z węzła docelowego przez usunięcie wartości znaku prefiksu X i zapisana w zmiennej vCatID . To jest wartość, którą będziemy aktualizować w polu ParentID rekordu produktu, aby umieścić element ListItem w nowej kategorii.

Podobnie, wartość PID klucza produktu wybranego elementu listy wyodrębniona i zapisana w zmiennej lngPID . Zostało to użyte jako kryterium do filtrowania i wybierania tego konkretnego rekordu produktu do aktualizacji pola ParentID za pomocą vCatID .

AKTUALIZACJA Zapytanie SQL zostało utworzone w celu filtrowania rekordu przy użyciu lngPID Koduj jako kryteria, aby filtrować rekord produktu i aktualizować vCatID Wartość w P identyfikator użytkownika pole.

Wykonaj metoda bieżącej bazy danych został wywołany z SQL i aktualizuje zmianę.

Podświetlenie węzła zostało zresetowane do węzła źródłowego.

Następnie podprocedura TreeView0_NodeClick() została wywołana z tv_nodSource jako parametr odzwierciedlający zmianę w kontrolce ListView.

Zamknij Kliknięcie przycisku spowoduje zamknięcie formularza.

Pobierz bazę danych demonstracyjnych.

Możesz pobrać bazę danych Demo, przeprowadzić testy i przestudiować kod VBA.


Życzymy SZCZĘŚLIWEGO NOWEGO ROKU.

OBSŁUGA ZDARZEŃ MS-ACCESS

  1. Wyklucza moduł klasy MS-Access
  2. Wykluczenia i definiowanie własnych wydarzeń
  3. Zakładka pola tekstowego listy kombinacji zdarzeń
  4. Tabele kontroli formularzy dostępu i zdarzenia
  5. Tablice kontroli formularzy dostępu i zdarzenia-2
  6. Tablice kontroli formularzy dostępu i zdarzenia-3
  7. Wykluczenia w module klasy dla podformularza
  8. Zdarzenia w module klasy i danych
  9. Zgłoszenia zdarzeń i dostępu do zlewu zdarzeń
  10. Wypłaty i ukrywanie wierszy raportu
  11. Wykluczenia i podświetlanie wierszy raportu
  12. Zevents Texbox i przycisk poleceń
  13. Wyklucza przycisk polecenia pola tekstowego
  14. Wykluczenia i wszystkie typy kontroli formularzy



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy Twoja firma potrzebuje bazy danych HR?

  2. Jak wyświetlić zależności obiektów w programie Access 2016

  3. Jak naprawić nowy typ danych, który powoduje problemy w MS Access?

  4. Przejmij kontrolę nad swoimi danymi dzięki Microsoft Access

  5. Dlaczego kopie zapasowe danych są ważne dla Twojej organizacji