Introduktion.
Fortsat fra sidste uges ActiveX ListView Control Tutorial-01.
I denne session af selvstudiet lærer vi, hvordan du søger og finder de bestemte række- og kolonneværdier og viser dem på en etiketkontrol på formularen. Dette er meget nyttigt, når vi har en stor mængde data i ListView-kontrollen. Vi vil også lære brugen af nogle ListView-egenskabsindstillinger.
Først og fremmest vil vi se, hvor nemt det er at omarrangere kolonnerne, som vi gør med Access Datasheet View, som vi ønsker, at de skal være på ListView Control. Vi har tilføjet nogle TextBoxes, ComboBox, Command Buttons og Label for nemmere valg af søgeparametre og visning af søgeresultater.
Jeg har lavet nogle ændringer i sidste uges demodata. De første kolonneværdier har jeg taget fra Employees Table of Northwind.accdb eksempeldatabasen. Oprettede en forespørgsel for at forbinde efternavns- og fornavnsværdierne med feltnavnet Student og EmployeeID brugt som nøgle (X01, X02 ...).
Før vi går til søgeoperationerne, vil vi kontrollere, hvordan man omarrangerer kolonner ved hjælp af træk og slip-metoden.
Bemærk: Hvis du ikke har gennemgået den tidligere selvstudieside og gerne vil fortsætte med denne session, så gå til ListView Control Tutorial-01-siden og download demodatabasen fra bunden af den side.
Pak filen ud og åbn databasen. Demoformularen vil være i normal visning.
-
Åbn din database med den sidste sessions demoformular, eller den formular, du har oprettet, åbn den i normal visning.
Nu vil vi prøve at trække og flytte en kolonne fra midten af listen (f.eks. kolonnen Vægt) og slippe den til Alder kolonne og se, hvad der sker. Det, der forventes at ske, er, at kolonnen Alder skal skifte til højre og indsætte den indgående kolonne i stedet for.
-
Flyt musemarkøren på kolonneoverskriften med navnet Vægt klik og hold venstre museknap nede. Når du trykker på venstre museknap, flyttes kolonneoverskriften lidt ned.
-
Prøv nu at trække kolonnen til venstre og slip den på kolonnen Alder .
Der vil ikke ske noget, fordi vi ikke har aktiveret denne funktion i egenskabsarket, og det er den eneste indstilling, vi skal ændre for at denne funktion kan fungere.
-
Skift formularen i designvisning.
-
Højreklik på ListView Control og fremhæv muligheden ListViewCtrl Object og vælg Egenskaber.
-
Der er muligheden 'AllowColumnReorder ' på den højre side. Sæt et flueben for at vælge det, og klik derefter på Anvend knappen efterfulgt af OK knappen for at lukke ejendomsvisningen.
-
Prøv nu at gentage ovenstående trin 2 og 3 ovenfor og se, hvad der sker.
Det er den eneste indstilling, du behøver for at aktivere denne funktion på ListView Control. Måske tænker du måske, hvad med at omarrangere rækkerne?.
Denne funktion skal programmere nogle hændelsesprocedurer, som vi gjorde tidligere i TreeView Control Drag-Drop Events. Den del gør vi efter noget tid.
-
Du kan eksperimentere med en hvilken som helst kolonne for at flytte hvor som helst du vil, inklusive den første kolonne også.
Bemærk: Før du slipper kildekolonnen, skal du se, at målkolonnen er dækket af den indgående kolonneramme, før du forsøger at slippe. Ellers kan den indgående kolonne skifte til den næste kolonneposition på højre side.
Dernæst vil vi lære, hvordan man hurtigt finder nogle oplysninger fra ListView, forudsat at vi har en stor mængde data i den.
Vi har tilføjet en underrutine til Tutorial-01 Module for at indlæse kolonneoverskriftens navne i en kombinationsboks på formularen med den røde baggrundsfarve. Kolonnenavnet bruges til at finde kolonneværdien (Alder, Højde, Vægt eller Klasse) for en elev.
Ny VBA-kode tilføjet til Form Class Module.
Følgende nye VBA-procedure er tilføjet til sidste uges vejledningsformulars klassemodul:
txtColCombo opretter listen over kolonneoverskriftsetiketter (feltnavne) i ComboBox. En af disse detaljer om elevens alder, højde, vægt, eller Klasse kan findes sammen med elevens navn som en del af søg-og-find-operationen.
Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub
Combobox vil ikke blive indlæst med en standardværdi for kolonneoverskriftsnavn. Hvis den er valgt, vises denne kolonneværdi for eleven i den store etiket under elevens navn. Hvis det efterlades tomt, vil søgeoperationen kun finde elevens navn.
Søgeoperationsmetoden er meget fleksibel og hurtig. Vi har to metoder til at finde en post.
Find posten ved at angive søgeteksten. Søgeteksten kan være fra enhver af kolonnerne, enten teksten helt eller delvist få tegn fra venstre. Da vi har to kategorier af objektmedlemmer i træk i ListView-kontrollen:ListItem - den første kolonne og andre kolonner er ListSubItems. Tekstsøgningen på disse objekter udføres separat.
En indstillingsgruppe med to afkrydsningsfelter er tilvejebragt ved siden af søgetekstindtastningstekstboksen på formularen for at vælge søge-og-find-mulighederne. Den første mulighed er valgt som standard, og søgningen udføres i den første kolonne (ListItem ) for at lede efter den givne tekst.
Vælg den anden mulighed for at søge i teksten i ListSubItem kolonner.
Bemærk: Omarrangering af kolonnerne vil ikke ændre objekterne, men kun deres visningsposition. Træk et ListSubItem kolonne og bringe den i den første kolonne ændres ikke det til et ListItem objekt.
Hvis du ønsker at hente en ukendt værdi fra en bestemt kolonne, skal du vælge et kolonnenavn fra ComboBox givet under den første tekstboks på formularen til søgeteksten. For eksempel kender du ikke en elevs højdemåling og gerne vil finde ud af det, vælg kolonnenavnet Højde fra ComboBox.
Efter indstilling af ovenstående værdi(er), klik på Find element Kommandoknap for at gå til søgeoperationen. Hvis søgningen lykkedes, vil resultatet blive vist i den store etiketkontrol under kommandoknappen.
Klik på kommandoknappen [Find element].
Kalder SearchAndFind() Procedure.
Private Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lvwList.ListItems.Item(j).Selected = True lblMsg.caption = msgText End If End Sub
I begyndelsen af programmet er både Students navn og Kolonnenavn ( 0valgfrit), kopieres fra tekstboksene til variablerne strFind og strColName efter valideringstjek.
Bemærk: Kolonnenavnet Combo Box's Not-in-List-egenskab er indstillet til Ja. Du kan vælge en gyldig værdi fra listen eller indtaste den eller lade kombinationsboksen stå tom. Hvis du indtaster en anden værdi, som ikke er på listen, vil den ikke blive accepteret.
Baseret på den valgte søgemulighed (1 - ListItem eller 2 - ListSubItem) dirigeres scanningsmetoden til det eller de specificerede objekt(er).
Ved at bruge en af disse søgemetoder finder du ListItem Object eller række der indeholder søgeteksten. Indeksværdien for listeelementet gemmes i variabel J til senere brug i programmet.
Bemærk: Systemet opretter automatisk indeksnumrene på det tidspunkt, hvor ListView-kontrolelementer udfyldes.
ListItem.Text værdi hentes. Denne information er forenet med den første ColumnHeader. Tekst (som Elev:Robert King) og tilføjet i Msgtext-strengen for at blive vist i Label-kontrolelementet på formularen.
Hvis kolonnen Header Name er valgt i ComboBox, derefter GetColVal() Funktionen kaldes med ListItem Object og Column Header Text værdien som parametre. Denne mulighed er god til at hente ukendte oplysninger om en elev, f.eks. elevens højde, fra posten.
GetColVal()-funktionen VBA-kode.
Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function
Ovenstående funktion beder om to parametre. Den første parameter er ListItem, hvor elevens navn findes. Den anden parameter er kolonnenavnet. Den valgte elevs Alder, Højde, Vægt, Klasse værdier gemmes i ListItem.ListSubItems Objekter. Funktionen ser gennem lvwList.ColumnHeader værdier for at finde det matchende kolonnenavn, når det er fundet, at kolonneindeksnummeret bruges til at hente kolonneværdien fra ListSubItems-objektet og returnerer værdien til det kaldende program.
Kommandoknappen [Find efter tast] Klik på Hændelsesprocedure.
Vi har tilføjet en anden metode til at finde elevens navn ved hjælp af den unikke nøgleværdi for ListItem hvis det bruges under oprettelse af ListItem List. Selvom det er valgfrit, er det bedre at tilføje unik nøglestrengværdi (skal starte med et alfabet) i stedet for at ignorere det.
For eksempel, hvis vi skal finde en persons oplysninger ud fra deres identifikationsnummer som CPR-nummer, nationalt identitetskortnummer, pasnummer eller kørekortnummer og så videre, kan en af disse oplysninger bruges som nøgleværdien til ListItem. Det er meget nemt og hurtigere at finde en post med denne unikke værdi i stedet for ovenstående søg-på-tekst-metode.
CmdKey_Click()-hændelsesproceduren.
Calls FindByKey() Subroutine.
Private Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") If len(lvKeyVal) > 0 then On Error Resume Next Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!",vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Som du kan se i ovenstående underrutine, kunne vi direkte finde ListItem hvor elevens navn er, med brug af nøgleværdien, med en enkelt sætning:Sæt lvItem =lvwList.ListItems.Item(xKeyVal).
Den næste linje læser ListItem-teksten (eller navnet på eleven) i variablen txt . De næste to linjer opretter meddelelsesteksten med elevens navn i msgText-strengvariablen.
Den næste Hvis . . .Så sætning kontrollerer, om en kolonnenavnsværdi er indtastet i kombinationsboksens kontrolelement. Hvis den findes, kalder du GetColVal() Funktion med de nødvendige parametre for at finde kolonneværdien og hente den i varColVal Variabel og vender tilbage til det kaldende program. Kolonnenavnet og dets hentede værdi føjes til msgText-strengvariablen for at blive vist på Label-kontrolelementet på formularen.
Den næste sætning fremhæver elevens postrække som en visuel indikation af, at det søgte element er fundet i rækken. msgText-værdien vises i etikettens billedtekstegenskab på formularen.
Den fulde VBA-kode på formularmodulet.
Option Compare Database Option Explicit Dim lvwList As MSComctlLib.ListView 'ListView Control Dim lvwItem As MSComctlLib.ListItem ' Dim ObjImgList As MSComctlLib.ImageList Const prfx As String = "K" Private Sub Form_Load() Call LoadListView Call txtColCombo End Sub Private Function LoadListView() 'Populate the ListView control with Student Details Dim db As DAO.Database Dim rst As DAO.Recordset Dim intCounter As Integer Dim strKey As String 'Assign ListView Control on Form to lvwList Object Set lvwList = Me.ListView1.Object With lvwList .AllowColumnReorder = True .Enabled = True .Font = "Verdana" .Font.Bold = True .Font.Size = 9 .ForeColor = vbBlack .BackColor = vbWhite End With 'Create Column Headers for ListView With lvwList .ColumnHeaders.Clear 'initialize header area 'Syntax: .ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon .ColumnHeaders.Add , , "Student", 2500 .ColumnHeaders.Add , , "Age", 1200 .ColumnHeaders.Add , , "Height", 1200 .ColumnHeaders.Add , , "weight", 1200 .ColumnHeaders.Add , , "Class", 1200 End With 'Initialize ListView Control While lvwList.ListItems.Count > 0 lvwList.ListItems.Remove (1) Wend 'Student Names and Ids are taken from Employees Table 'through the StudentQ Query. Set db = CurrentDb Set rst = db.OpenRecordset("StudentQ", dbOpenDynaset) With lvwList Do While Not rst.EOF And Not rst.BOF intCounter = rst![EmployeeID] strKey = "X" & Format(intCounter, "00") 'Key Value sample: X01 'Syntax: .ListItems.Add(Index, Key, Text, Icon, SmallIcon) Set lvwItem = .ListItems.Add(, strKey, rst![Student]) With lvwItem 'Syntax: .Add Index,Key,Text,Report Icon,TooltipText .ListSubItems.Add , strKey & CStr(intCounter), CStr(5 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 1), CStr(135 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 2), CStr(40 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 3), ("Class:" & Format(intCounter, "00")) End With rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing Set lvwItem = Nothing End With lvwList.Refresh End Function Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub Private Sub cmdFind_Click() Call SearchAndFind End Sub Private Sub cmdKey_Click() Call FindByKey End Sub Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub Public Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found in the List!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lblMsg.caption = msgText lvwList.ListItems.Item(j).Selected = True End If End Sub Public Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") On Error Resume Next If Len(lvKeyVal) > 0 Then Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!", vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Download demodatabasen fra følgende link:
- Microsoft TreeView Control Tutorial
- Oprettelse af adgangsmenu med TreeView-kontrol
- Tildeling af billeder til TreeView-noder
- Tildeling af billeder til TreeView Nodes-2
- TreeView Control Checkmark Tilføj Slet
- TreeView ImageCombo Drop-down Adgang
- Omarranger TreeView-noder ved at trække og slippe
- ListView-kontrol med MS-Access TreeView
- ListView Control Træk-slip hændelser
- TreeView-kontrol med underformularer