sql >> Database >  >> RDS >> Access

ListView-besturing Drag Drop Gebeurtenissenafhandeling

Inleiding.

We zijn bekend met de bewerkingen met slepen en neerzetten op TreeView Control, in Ms-Access dat knooppunten herschikt. Alle basisrecords voor de Treeview Control Nodes komen uit een enkele toegangstabel. We werken altijd de ParentID van de Source Node bij veldwaarde, met de ID-waarde van het doelknooppunt op hetzelfde tabelrecord, om de positie op het TreeView-besturingselement te wijzigen. De records worden nergens fysiek verplaatst.

Hier, met de toevoeging van ListView Control samen met TreeView Control, zijn we van plan om met twee verschillende toegangstabellen te werken.

  1. lvCategory – Categoriecode en beschrijving.
  2. lvProducts – Producten per categorie.

Op deze manier is het gemakkelijker om de relatie tussen beide tabellen te begrijpen. Welke wijzigingen we moeten aanbrengen en waar, wanneer een productitem (ListView-item) van de ene categorie naar de andere gaat in het TreeView-besturingselement.

De lvCategory Access Table heeft 20 records voor de TreeView Nodes en de lvProducts Tabel heeft 45 voor het ListView-besturingselement. Een of meer records in de tabel Producten zijn direct gerelateerd aan een productcategorie in de categorietabel. De relatie tussen beide is bijgewerkt met de veldwaarde Categorie-ID (CID) op de ParentID van de producttabel veld zodat de verandering van categorie van het product onmiddellijk wordt weergegeven in het ListView-besturingselement.

De tabel met demogegevens is afkomstig uit Microsoft Access Sample Database Northwind.accdb en is in twee delen gesplitst.

Op basis van de ParentID-veldwaarde van lvProduct-records, kunnen we alle gerelateerde productitems filteren en weergeven in het ListView-besturingselement, wanneer een categorieknooppunt wordt geselecteerd in het TreeView-besturingselement.

Onderwerpen die we tot nu toe hebben behandeld.

Hieronder volgen de belangrijkste onderwerpen over TreeView , ImageList , ImageCombo, en ListView Bedieningselementen die we tot nu toe hebben behandeld in MS-Access:

  1. Microsoft TreeView Control-zelfstudie
  2. Toegangsmenu maken met TreeView Control
  3. Afbeeldingen toewijzen aan TreeView-besturingselement
  4. Afbeeldingen toewijzen aan TreeView Control-2
  5. TreeView Control Vinkje Toevoegen Verwijder Nodes
  6. Vervolgkeuzelijst TreeView ImageCombo-toegang
  7. Herschik TreeView-knooppunten door middel van slepen en neerzetten
  8. ListView-besturing met MS-Access TreeView

De ListView Drag-Drop-taak.

Wat de Drag and Drop-bewerking van ListView betreft, is het een eenvoudige oefening om dezelfde methode alleen binnen de TreeView-besturing te vergelijken. Aangezien de actie Drag Drop zowel TreeView- als ListView-besturingselementen omvat, gebruiken we dezelfde TreeView0_OLEDragDrop()-gebeurtenisprocedure met een eenvoudige VBA-code.

De productitems die in het ListView-besturingselement worden vermeld, behoren tot het huidige categorie-item dat is geselecteerd in het TreeView-besturingselement.

De gebruiker selecteert een bepaald productitem uit het ListView-besturingselement, als hij/zij denkt dat het tot een ander categorie-item behoort, sleept en zet het dan neer op het doelcategorie-item op de TreeViewCcontrol.

Het verplaatste ListView-productitem wordt toegevoegd aan de lijst met items die tot de gewijzigde categorie behoren. De veldwaarde ParentID van de productrecord wordt bijgewerkt met de record-ID van de doelcategorie (CID-waarde).

Het is slechts een eenrichtingsactie, verplaats het ListView-item altijd van de ene categorie en zet het neer op een ander categorieknooppunt op het TreeView-besturingselement.

De ListView drag-drop demo Toegangsformulier frmListViewDrag' s proefdraaien Schermafbeelding wordt hieronder gegeven:

In de bovenstaande afbeelding, de Dranken Categorie op de TreeView is geselecteerd. De producten die behoren tot de categorie Dranken zijn vermeld in de ListView Control.

De ontwerpweergave van het bovenstaande formulier:

De lijst met besturingsnamen op het formulier is als volgt:

  1. TreeView-besturing:TreeView0
  2. ListView-besturingselement:ListView0
  3. ImageList-besturingselement:ImageList3
  4. Opdrachtknop:cmdClose

De VBA-code op de frmListViewDrag ’s Klasmodule:

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 bekende VBA-codesegmenten.

In de Form_Load() Gebeurtenisprocedure, initialiseren we de TreeVew-, ListView-, ImageList-besturingselementen. Het creëert de ColumnHeadings van het ListView-besturingselement, voordat u lijstitems in het ListView-besturingselement invult. Aan het einde van deze routine noemen we de LoadTreeView()-subroutine.

De LoadTreeView() subroutine vult de categorieknooppunten van de producten in het TreeView-besturingselement, met de records uit de lvCategory Tafel. Het laden van knooppunten op het TreeView-besturingselement is een proces in twee stappen. Waarom is het zo, in plaats van het in één keer te doen? Dit aspect is in detail uitgelegd op een eerdere pagina, de 7e link op de lijst met links hierboven als u er doorheen wilt gaan. Het is misschien niet gepast om ze hier allemaal te herhalen.

Aan het einde van de bovenstaande subroutine, de LoadListView() subroutine is aangeroepen met de CID-waarde van het eerste categorierecord 1 als de parameter.

De veldwaarde Productrecords met ParentID 1 zijn gefilterd en vermeld op de ListView Control. Deze procedure werd in detail uitgelegd in de post van vorige week, het 8e item, van de lijst met links hierboven.

De subroutines voor slepen en neerzetten.

De volgende subroutines die zijn gekoppeld aan de actie Slepen en neerzetten, worden automatisch uitgevoerd in de volgorde waarin ze hieronder worden weergegeven:

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

De eerste en laatste subroutines initialiseren respectievelijk de betrokken nodes en resetten hun status aan het einde.

De tweede, OLEDragOver() subroutine werkt als de MouseMove Event Procedure en volgt de beweging van de muis tijdens het slepen en neerzetten. Het markeert de NodeText wanneer de muis zich boven een Node bevindt en volgt het traject totdat de linkermuisknop wordt losgelaten.

Alleen de procedurecode TreeView0_OLEDragDrop() wordt hieronder vermeld.

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

De actie met slepen en neerzetten stap voor stap.

De TreeView0_OLEDragDrop()-procedure wordt onmiddellijk uitgevoerd nadat de linkermuisknop is losgelaten om de neerzetactie te voltooien. Aan het begin van de code zijn de actieve en de Target TreeView Node-referenties opgeslagen in tv_nodSource en tv_nodTarget objectvariabelen respectievelijk.

Vervolgens controleren we of het ListItem op een geldige TreeView Node is neergezet of niet. Als het op hetzelfde broncategorieknooppunt of op een leeg gebied op het TreeView-besturingselement wordt neergezet, zijn deze bewegingen niet geldig. Als het in een leeg gebied van het TreeView-besturingselement is neergezet, wordt de tv_nodTarget objectvariabele zal de waarde Niets bevatten. In dat geval is het geeft een bericht weer en verlaat het programma.

Vervolgens worden de TreeView-bron- en doelknooppuntsleutelwaarden opgeslagen in twee tekenreeksvariabelen. Als beide sleutels hetzelfde zijn, wordt het ListItem gesleept en neergezet op zijn eigen bovenliggende knooppunt (categorieknooppunt) op het TreeView-besturingselement. De uitvoering van het programma wordt afgebroken om verder te gaan.

Als beide sleutels verschillend zijn, is het tijd om de wijziging op de Ouder-ID van het productrecord bij te werken veld, met de CID . van het doelcategorierecord Codeer en ververs de ListView-items.

De geselecteerde sleutelwaarde van ListItem (PID veldwaarde) is opgeslagen in de strListItemKey Tekenreeksvariabele.

De werkelijke CID . van de categorierecord veldwaarde is geëxtraheerd uit het doelknooppunt door de prefix-tekenwaarde X te verwijderen en opgeslagen in variabele vCatID . Dit is de waarde die we zullen bijwerken in het veld ParentID van het productrecord, om het ListItem onder de nieuwe categorie te plaatsen.

Evenzo wordt de productsleutel-PID-waarde van het geselecteerde lijstitem geëxtraheerd en opgeslagen in variabele lngPID . Dit is gebruikt als criteria om dat specifieke productrecord te filteren en te kiezen voor het bijwerken van het ParentID-veld met vCatID .

Een UPDATE Query-SQL is gemaakt om het record te filteren, met behulp van de lngPID Codeer als criteria, om de productrecord te filteren en om de vCatID . bij te werken Waarde in de P arentID veld.

De Uitvoeren methode van de Currentdb is aangeroepen met de SQL en werkt de wijziging bij.

De Highlight van de Node is teruggezet naar de Source Node.

Vervolgens is de subroutine TreeView0_NodeClick() aangeroepen met de tv_nodSource als een parameter om de wijziging op het ListView-besturingselement weer te geven.

De Sluiten Button Click sluit het formulier.

Demodatabase downloaden.

U kunt de demo-database downloaden, proefdraaien en de VBA-code bestuderen.


WENST U EEN HEEL GELUKKIG NIEUWJAAR.

MS-ACCESS EVENT AFHANDELING

  1. Metevents MS-Access Class Module
  2. Met evenementen en je eigen evenementen definiëren
  3. Bijgebeurtenissen Combo Lijst Tekstvak Tab
  4. Toegangsformulierbeheerarrays en gebeurtenissen
  5. Access Form Control Arrays en Event-2
  6. Access Form Control Arrays en Event-3
  7. Met gebeurtenissen in klasmodule voor subformulier
  8. Met gebeurtenissen in klasmodule en gegevens
  9. Met gebeurtenissen en toegangsrapport Event Sink
  10. Met gebeurtenissen en rapportregel verbergen
  11. Met gebeurtenissen en markering van rapportregels
  12. Met gebeurtenissen Texbox en Command-knop
  13. Withevents Textbox Command Button
  14. Met gebeurtenissen en alle typen formulierbesturing



  1. To-do lijst applicatie met PHP en MySQL database

  2. Opgeslagen procedure oproepen met VBA

  3. Oplossing voor:Store update-, insert- of delete-instructie beïnvloedde een onverwacht aantal rijen (0)

  4. Een web-app vanaf nul maken met Python Flask en MySQL:deel 4