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.
- lvCategory – Kod i opis kategorii.
- 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:
- Samouczek sterowania Microsoft TreeView
- Tworzenie menu dostępu za pomocą TreeView Control
- Przypisywanie obrazów do kontrolki TreeView
- Przypisywanie obrazów do TreeView Control-2
- Kontrola TreeView Zaznacz opcję Dodaj usuń węzły
- Rozwijane menu dostępu TreeView ImageCombo
- Ponownie rozmieszczaj węzły TreeView przez przeciąganie i upuszczanie
- 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:
- Kontrola TreeView:TreeView0
- Kontrola ListView:ListView0
- Kontrola ImageList:ImageList3
- 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:
- TreeView0_OLEStartDrag()
- TreeView0_OLEDragOver()
- TreeView0_OLEDragDrop()
- 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
- Wyklucza moduł klasy MS-Access
- Wykluczenia i definiowanie własnych wydarzeń
- Zakładka pola tekstowego listy kombinacji zdarzeń
- Tabele kontroli formularzy dostępu i zdarzenia
- Tablice kontroli formularzy dostępu i zdarzenia-2
- Tablice kontroli formularzy dostępu i zdarzenia-3
- Wykluczenia w module klasy dla podformularza
- Zdarzenia w module klasy i danych
- Zgłoszenia zdarzeń i dostępu do zlewu zdarzeń
- Wypłaty i ukrywanie wierszy raportu
- Wykluczenia i podświetlanie wierszy raportu
- Zevents Texbox i przycisk poleceń
- Wyklucza przycisk polecenia pola tekstowego
- Wykluczenia i wszystkie typy kontroli formularzy