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