Introduktion.
Vi är bekanta med Dra och släpp-operationerna på TreeView Control, i Ms-Access som omarrangerar noder. Alla basposter för Treeview-kontrollnoderna kommer från en enda åtkomsttabell. Vi uppdaterar alltid källnodens förälder-ID fältvärde, med målnodens ID-värde på samma tabellpost, för att ändra positionen på TreeView-kontrollen. Posterna flyttas inte fysiskt någonstans.
Här, med tillägget av ListView Control tillsammans med TreeView Control, planerar vi att arbeta med två olika åtkomsttabeller.
- lvCategory – Kategorikod och beskrivning.
- lvProducts – Categorywise Products.
På så sätt är det lättare att förstå sambandet mellan de båda tabellerna. Vilka ändringar vi måste göra och var, när en produktartikel (ListView-objekt) flyttas från en kategori till en annan på TreeView-kontrollen.
lvCategory Access Table har 20 poster för TreeView-noderna och lvProducts Tabellen har 45 för ListView Control. En eller flera poster i tabellen Produkter är direkt relaterade till en produktkategori i kategoritabellen. Relationen mellan dem har uppdaterats med fältvärdet för kategori-ID (CID) på produkttabellens förälder-ID fältet så att ändringen av produktens kategori återspeglas omedelbart på ListView Control.
Demodatatabellen togs från Microsoft Access Sample Database Northwind.accdb och delades upp i två delar.
Baserat på ParentID Field Value, för lvProduct-poster, kan vi filtrera och lista alla relaterade produktartiklar i ListView-kontrollen när en kategorinod väljs i TreeView-kontrollen.
Ämnen vi har behandlat hittills.
Följande är huvudämnena i TreeView , Bildlista , ImageCombo, och ListView Kontroller, vi har täckt hittills i MS-Access:
- Microsoft TreeView Control Tutorial
- Skapa åtkomstmeny med TreeView-kontroll
- Tilldela bilder till TreeView-kontroll
- Tilldela bilder till TreeView Control-2
- TreeView Control Markera Lägg till Ta bort noder
- TreeView ImageCombo rullgardinsmeny
- Arrangera om TreeView-noder genom att dra och släppa
- ListView-kontroll med MS-Access TreeView
ListView Drag-Drop Task.
När det gäller ListViews Dra och släpp-operation är det en enkel övning som jämför samma metod enbart inom TreeView-kontrollen. Eftersom Drag Drop-åtgärden involverar både TreeView- och ListView-kontroller använder vi samma TreeView0_OLEDragDrop()-händelseprocedur med en enkel VBA-kod.
Produktobjekten som listas i ListView-kontrollen tillhör den aktuella kategoriposten som valts i TreeView-kontrollen.
Användaren väljer en specifik produktpost från ListView-kontrollen, om han/hon tror att den tillhör en annan kategoriartikel, dra och släpp den på målkategoriobjektet på TreeViewCcontrol.
Den flyttade ListView-produkten kommer att läggas till i listan över artiklar som tillhör den ändrade kategorin. Produktpostens ParentID-fältvärde uppdateras med målkategoripost-ID (CID-värde).
Det är bara en enkelriktad åtgärd, flytta alltid ListView-objektet från en kategori och släpp det på en annan kategorinod på TreeView-kontrollen.
ListView dra-släpp-demon Åtkomstformulär frmListViewDrag’ s testkörning Skärmbilden ges nedan:
På bilden ovan visas Drycker Kategori på trädvyn har valts. Produkterna som tillhör kategorin Drycker har listats i ListView Control.
Designvyn för ovanstående formulär:
Listan över kontrollnamn på formuläret är enligt nedan:
- TreeView-kontroll:TreeView0
- ListView Control:ListView0
- ImageList Control:ImageList3
- Kommandoknapp:cmdClose
VBA-koden på frmListViewDrag s klassmodul:
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
De välbekanta VBA-kodsegmenten.
I Form_Load() Händelseprocedur, vi initierar TreeVew, ListView, ImageList-kontrollerna. Det skapar kolumnrubriker av ListView Control, innan du fyller i listobjekt i Listview-kontrollen. I slutet av denna rutin anropar vi subrutinen LoadTreeView().
LoadTreeView() subrutinen fyller i produktens kategorinoder på TreeView-kontrollen, med posterna från lvCategory Tabell. Att ladda noder på TreeView-kontrollen är en process i två steg. Varför är det så, snarare än att göra det på en gång? Denna aspekt har förklarats i detalj på en tidigare sida, den 7:e länken på listan med länkar ge ovan om du vill gå igenom den. Att upprepa dem alla här kanske inte är lämpligt.
I slutet av ovanstående subrutin, LoadListView() subrutinen har anropats med den första kategoripostens CID-värde 1 som parameter.
Värdet 1 i fältet Product Records with ParentID har filtrerats och listats på ListView Control. Denna procedur förklarades i detalj i förra veckans inlägg, den 8:e punkten, bland listan över länkar ovan.
The Drag-Drop Action Subroutines.
Följande subrutiner kopplade till Dra och släpp-åtgärden kommer att köras automatiskt i den ordning de presenteras nedan:
- TreeView0_OLEStartDrag()
- TreeView0_OLEDragOver()
- TreeView0_OLEDragDrop()
- TreeView0_OLECompleteDrag()
De första och sista subrutinerna initierar de involverade noderna och återställer deras status i slutet respektive.
Den andra, OLEDragOver()-underrutinen fungerar som MouseMove Event Procedure och spårar musens rörelse under drag-släpp-operationen. Den markerar NodeTexten när musen är över en Nod och spårar dess bana tills vänster musknapp släpps.
Enbart Procedurkoden för TreeView0_OLEDragDrop() listas nedan.
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
Drag-släpp-åtgärden steg för steg.
TreeView0_OLEDragDrop()-proceduren körs omedelbart efter att vänster musknapp har släppts för att slutföra Drop-åtgärden. I början av koden har den aktiva och Target TreeView Nodes referenser sparats i tv_nodSource och tv_nodTarget objekt Variabler respektive.
Därefter utför vi en kontroll, om ListItem har släppts på en giltig TreeView-nod eller inte. Om det släpps på samma källkategorinod eller på ett tomt område på TreeView-kontrollen är dessa drag inte giltiga. Om den har släppts i ett tomt område i TreeView-kontrollen är tv_nodTarget objektvariabel kommer att innehålla värdet Ingenting. I så fall är det visar ett meddelande och avslutar programmet.
Därefter sparas nyckelvärdena för TreeView-källan och målnoden i två strängvariabler. Om båda nycklarna är desamma dras och släpps ListItem på sin egen överordnade nod (kategorinod) på TreeView-kontrollen. Programexekveringen avbryts från att fortsätta.
Om båda nycklarna är olika är det dags att uppdatera ändringen på produktpostens förälder-ID med målkategoripostens CID Koda och uppdatera ListView-objekten.
Det valda listobjektets nyckelvärde (PID fältvärde) har sparats i strListItemKey Strängvariabel.
Kategoripostens faktiska CID fältvärdet har extraherats från målnoden genom att ta bort prefixets teckenvärde X och sparats i variabeln vCatID . Detta är värdet som vi kommer att uppdatera i produktpostens ParentID-fält, för att placera ListItem under den nya kategorin.
På liknande sätt extraherades och sparades det valda listobjektets produkts nyckel-PID-värde i variabel lngPID . Detta har använts som kriterium för att filtrera och välja just den produktposten för uppdatering av ParentID-fältet med vCatID .
En UPPDATERING Query SQL har skapats för att filtrera posten med lngPID Koda som kriterier, för att filtrera produktposten och för att uppdatera vCatID Värde i P arentID fältet.
Execute metoden för Currentdb har anropats med SQL och uppdaterar ändringen.
Höjdpunkten för noden har återställts till källnoden.
Därefter har subrutinen TreeView0_NodeClick() anropats med tv_nodSource som en parameter för att återspegla ändringen på ListView Control.
Stäng Knappklick stänger formuläret.
Ladda ner demodatabas.
Du kan ladda ner demodatabasen, provköra och studera VBA-koden.
ÖNSKAR DIG ETT GOTT NYTT ÅR.
MS-ACCESS HANTERING AV HÄNDELSER
- Med Events MS-Access Class Module
- Med evenemang och definiera dina egna evenemang
- Textrutafliken Withevents Combo List
- Åtkomst till formulärkontrollarrayer och händelse
- Åtkomst till Form Control Arrays And Event-2
- Åtkomst till Form Control Arrays And Event-3
- Med händelser i klassmodul för underformulär
- Med händelser i klassmodul och data
- Med händelser och åtkomstrapport händelsesink
- Med händelser och rapportradsdöljning
- Med händelser och rapportlinjemarkering
- Med händelser Texbox och kommandoknapp
- Kommandoknapp för Withevents Textbox
- Med händelser och alla formulärkontrolltyper