Hallo Zusammen,
ich bin auf der Suche nach einer Möglichkeit, die Liste eines ListViews zu filtern bzw. darin zu suchen.
Bisher bin ich mit meinem Lösungsansatz noch nicht ganz glücklich. Die gefundenen Zeilen sind nicht deutlich genug "markiert". Wie könnte ich das besser machen?
Oder gibt es eine Möglichkeit, die nicht benötigten Zeilen auszublenden, ähnlich wie man es mit _GUICtrlListView_HideColumn für Spalten machen könnte? Dann blieben nur noch die zutreffenden Reihen übrig.
Spoiler anzeigen
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GuiConstantsEx.au3>
#include <ButtonConstants.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
#include <array.au3>
#include <Date.au3>
Opt('MustDeclareVars', 1)
[/autoit] [autoit][/autoit] [autoit]$Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work
[/autoit] [autoit][/autoit] [autoit]#Region Vars-Declaration
Global $MyGui, $GuiListView, $GuiFilterInput, $GuiStatusLabel, $GuiButtonFiltern, $GuiButtonClear, $GuiButtonLast, $GuiButtonNext, $GuiMSG, $hImage
Global $GuiWidth = 700, $GuiHeight = 400 ; GUI-Größe
Global $MaxRows = 999, $MaxCol = 5 ; Reihen und Spalten
Global $FoundedArray, $FApos ; Hilfsarray für die gefundenen Elemente
Global $MyInitTimer
Global Const $ItemDistance = 10
Global $LastX
#EndRegion Vars-Declaration
#Region Gui-Creation
; -- GUI erzeugen --
$MyGui = GUICreate("Filter in ListView", $GuiWidth, $GuiHeight)
$LastX = $ItemDistance
GUICtrlCreateLabel("Filter:", $LastX, 20, 30, 20)
$LastX += 30 + $ItemDistance
$GuiFilterInput = GUICtrlCreateInput("99", $LastX, 20 - 3, 200)
$LastX += 200 + $ItemDistance
$GuiButtonFiltern = GUICtrlCreateButton("Filtern/Suchen", $LastX, 20 - 4, 90, 24, $BS_DEFPUSHBUTTON)
$LastX += 90 + $ItemDistance
$GuiButtonClear = GUICtrlCreateButton("Löschen", $LastX, 20 - 4, 90, 24)
$LastX += 90 + $ItemDistance
$GuiButtonLast = GUICtrlCreateButton("<<", $LastX, 20 - 4, 20, 24)
GUICtrlSetState(-1, $GUI_DISABLE)
$LastX += 20 + $ItemDistance
$GuiButtonNext = GUICtrlCreateButton(">>", $LastX, 20 - 4, 20, 24)
GUICtrlSetState(-1, $GUI_DISABLE)
; $GuiListView = GUICtrlCreateListView("", 10, 60, $GuiWidth - 20, 290, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER), $LVS_EX_FULLROWSELECT)
$GuiListView = GUICtrlCreateListView("", 10, 60, $GuiWidth - 20, 290, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_CHECKBOXES))
$GuiStatusLabel = GUICtrlCreateLabel("Gui erzeugen...", 10, $GuiHeight - 20, $GuiWidth - 20, 20)
GUISetState(@SW_SHOW, $MyGui)
#EndRegion Gui-Creation
#Region fill the listview
; -- Tabelle füllen --
$MyInitTimer = TimerInit()
_GUICtrlListView_BeginUpdate($GuiListView)
; Add columns
For $c = 1 To $MaxCol
_GUICtrlListView_InsertColumn($GuiListView, $c - 1, "Column " & $c, 100)
Next
; Add items
SetStatus("Erzeugen (" & $MaxRows & " x " & $MaxCol & ")...", 1)
For $r = 1 To $MaxRows
_GUICtrlListView_AddItem($GuiListView, "Row " & $r & ", Col 1, " & Random(0, 99999, 1), $r - 1)
For $c = 2 To $MaxCol
_GUICtrlListView_AddSubItem($GuiListView, $r - 1, "Row " & $r & ", Col " & $c & ", " & Random(0, 99999, 1), $c - 1)
Next
Next
_Debug("main", "Tabelle füllen", ru_TimerDiffNice($MyInitTimer))
; Spaltenbreite anpassen
$MyInitTimer = TimerInit()
For $c = 1 To $MaxCol
_GUICtrlListView_SetColumnWidth($GuiListView, $c - 1, $LVSCW_AUTOSIZE)
Next
_Debug("main", "Spaltenbreite anpassen", ru_TimerDiffNice($MyInitTimer))
_GUICtrlListView_EndUpdate($GuiListView)
#EndRegion fill the listview
#Region Main
; Mainloop
SetStatus("")
While 1
$GuiMSG = GUIGetMsg()
Switch $GuiMSG
Case $GUI_EVENT_CLOSE ; Window-Event-Close
GUISetState(@SW_HIDE, $MyGui)
GUIDelete($MyGui)
Exit
Case $GuiButtonFiltern ; Filtern/Suchen
Search(GUICtrlRead($GuiFilterInput))
Case $GuiButtonClear ; clear filter
GUICtrlSetData($GuiFilterInput, "")
Search("")
SetStatus("Filter gelöscht")
Case $GuiButtonLast ; last
JumpToFoundedItem(-1)
Case $GuiButtonNext ; next
JumpToFoundedItem(+1)
EndSwitch
WEnd
#EndRegion Main
#Region Funktionsdefinitionen
; Funktion, die im Listview nach dem Filter sucht und alle Zeilen markiert.
; Ebenfalls werden die gefundenen Rows im Array $FoundedArray aufgehoben, damit mit "last" und "next" umgeblättert werden kann
Func Search($myFilter)
Local $MyLocalInitTimer = TimerInit()
Local $FoundInRow, $LastRow, $CounterFounded
; Filter-Eingabe
; $myFilter = InputBox("Bitte Filter eingeben", "Z.B. 99", 99, "", 200, 120)
If $myFilter == "" Then
; Alle Selektionen entfernen
_GUICtrlListView_SetItemSelected($GuiListView, -1, False, False) ; Alle entfernen
; Butto deaktivieren
GUICtrlSetState($GuiButtonLast, $GUI_DISABLE)
GUICtrlSetState($GuiButtonNext, $GUI_DISABLE)
; FoundedArray löschen
$FoundedArray = "" ; Array
$FApos = 0 ; Position im Array für "last" und "next"
SetStatus("Alle anzeigen")
Return
EndIf
; Alle Selektionen entfernen
_GUICtrlListView_SetItemSelected($GuiListView, -1, False, False) ; Alle entfernen
; Parameter zurücksetzen
$FoundInRow = -1 ; start from the beginning
$LastRow = -2
$CounterFounded = 0
; Suchen
_GUICtrlListView_BeginUpdate($GuiListView)
SetStatus('Suchen nach "' & $myFilter & '"...', 1)
; Search for target item
While 1
$FoundInRow = _GUICtrlListView_FindInText($GuiListView, $myFilter, $FoundInRow)
If $FoundInRow < 0 Or $LastRow >= $FoundInRow Then ExitLoop 1
; "Last" aufheben, damit nicht unendlich immer wieder von vorne gesucht wird
$LastRow = $FoundInRow
$CounterFounded += 1
_GUICtrlListView_SetItemSelected($GuiListView, $FoundInRow, True, True) ; Nur den einen setzen
; _GUICtrlListView_SetItemState($GuiListView, $FoundInRow, $LVIS_SELECTED, $LVIS_SELECTED)
; _GUICtrlListView_EnsureVisible($GuiListView, $FoundInRow) ; Hinscrollen/Anzeigen
WEnd
_GUICtrlListView_EndUpdate($GuiListView)
; Ausgabe, diesmal mit _GUICtrlListView_GetSelectedCount
; SetStatus(_GUICtrlListView_GetSelectedCount($GuiListView) & ' Items mit "' & $myFilter & '" gefunden und markiert')
; Retrieve indices of selected item(s)
$FoundedArray = _GUICtrlListView_GetSelectedIndices($GuiListView, True)
; _ArrayDisplay($FoundedArray, "founded items")
$FApos = 0
JumpToFoundedItem(+1)
; Button frei geben
If IsArray($FoundedArray) And $FoundedArray[0] > 0 Then
GUICtrlSetState($GuiButtonLast, $GUI_ENABLE)
GUICtrlSetState($GuiButtonNext, $GUI_ENABLE)
EndIf
_Debug("Search", 'suchen nach "' & $myFilter & '"', ru_TimerDiffNice($MyLocalInitTimer))
[/autoit] [autoit][/autoit] [autoit]; Ausgabe in MsgBox
If $CounterFounded == 0 Then
MsgBox(0, "Suchergebnis", 'Es wurden keine Items mit "' & $myFilter & '" gefunden!')
Else
MsgBox(0, "Suchergebnis", $CounterFounded & ' Items mit "' & $myFilter & '" gefunden und markiert')
EndIf
EndFunc ;==>Search
; Funktion, die in dem $FoundedArray von der derzeitigen Position im Array $FApos vor +der zurückblättert und an
; die betreffende Reihe springt
; $ArrayPos ist normalerweise +1 oder -1
Func JumpToFoundedItem($ArrayPos = 0)
Local $MyLocalInitTimer = TimerInit()
Local $NewArrayPos = $FApos + $ArrayPos
Local $GoToRow
If (Not IsArray($FoundedArray)) Or $FoundedArray[0] == 0 Then
SetStatus("Kein Sucherergebnis vorhanden")
Return
EndIf
; letztes Element überschritten?
If $NewArrayPos > $FoundedArray[0] Then $NewArrayPos = 1
; erstes Element unterschritten
If $NewArrayPos < 1 Then $NewArrayPos = $FoundedArray[0]
; Reihe nochmal setzen und hinspringen
$GoToRow = $FoundedArray[$NewArrayPos]
_GUICtrlListView_SetItemSelected($GuiListView, $GoToRow, True, True) ; Nur den einen setzen
_GUICtrlListView_EnsureVisible($GuiListView, $GoToRow) ; Hinscrollen/Anzeigen
; Pointer umsetzen
$FApos = $NewArrayPos
SetStatus($NewArrayPos & " # " & $FoundedArray[0] & " gefundenen Items")
[/autoit] [autoit][/autoit] [autoit]_Debug("JumpToFoundedItem", 'jump to result ' & $NewArrayPos & " in row " & $GoToRow, ru_TimerDiffNice($MyLocalInitTimer))
EndFunc ;==>JumpToFoundedItem
; Funktion, die den Text um unteren Rand der Gui ausgibt und ggf. den WaitingCursor setzt
Func SetStatus($Text, $WaitingCursor = 0)
; Status ausgeben
GUICtrlSetData($GuiStatusLabel, $Text)
; Cursor umsetzen
If $WaitingCursor Then
GUISetCursor(15, 1, $MyGui) ; Waiting-Cursor
Else
GUISetCursor(-1, 0, $MyGui) ; Normal-Cursor
EndIf
EndFunc ;==>SetStatus
; Funktion, die Debug-Ausgaben macht
Func _Debug($VonFunc = "", $Text = "", $a = "", $b = "", $c = "", $d = "", $e = "", $f = "")
Local $Message = '>' & $VonFunc & '<: ' & $Text
If $a <> "" Then $Message &= ", " & $a
If $b <> "" Then $Message &= ", " & $b
If $c <> "" Then $Message &= ", " & $c
If $d <> "" Then $Message &= ", " & $d
If $e <> "" Then $Message &= ", " & $e
If $f <> "" Then $Message &= ", " & $f
ConsoleWrite($Message & @CRLF)
EndFunc ;==>_Debug
; Funktion, die einen TimerDiff "schöne" Zeitangaben umwandelt und zurückliefert
; $typ == "I", dann muß in $InitOrDiffZahl das Ergebnis von TimerInit stehen
; $typ == "D", dann muß in $InitOrDiffZahl das Ergebnis von TimerDiff stehen, also das ausgerechnete TimeDifferenz
Func ru_TimerDiffNice($InitOrDiffZahl, $typ = "I")
Local $hh, $mm, $ss, $ret
Local $TimerDiffZahl
If $InitOrDiffZahl <= 0 Then Return ""
[/autoit] [autoit][/autoit] [autoit]; Schauen, was übergeben wurde
If $typ == "I" Then
; Ist InitTimer-Zahl, daher Diff berechnen
$TimerDiffZahl = TimerDiff($InitOrDiffZahl)
ElseIf $typ == "D" Then
; TimerDiff-Zahl direkt übernehmen
$TimerDiffZahl = $InitOrDiffZahl
Else
; Falscher Typ, einfach nichts zurückgeben
Return ""
EndIf
; Integer daraus machen
$TimerDiffZahl = Int($TimerDiffZahl)
; hh, mm, ss füllen
_TicksToTime($TimerDiffZahl, $hh, $mm, $ss)
If $hh > 0 Then $ret &= StringFormat("%02ih ", $hh)
If $mm > 0 Then $ret &= StringFormat("%02im ", $mm)
If $ss > 0 Then $ret &= StringFormat("%02is ", $ss)
If $ss < 1 Then
$ret &= $TimerDiffZahl & " ticks"
Else
$ret &= "(" & $TimerDiffZahl & " ticks)"
EndIf
Return $ret
EndFunc ;==>ru_TimerDiffNice
#EndRegion Funktionsdefinitionen
Probiert hatte ich auch schon von BugFix das "ListView - SubItem einzeln färben/formatieren ", aber das ist bei großen Tabellen leider zu langsam.
Besten Dank schon mal für jede Idee!
R@iner