[...] Saisie predictive - données stoquées sur fichier CSV

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
JulienBoul
Niveau 4
Niveau 4
Messages : 82
Enregistré le : ven. 04 déc. 2015 13:55
Status : Hors ligne

[...] Saisie predictive - données stoquées sur fichier CSV

#1

Message par JulienBoul »

Bonjour,

Gros chantier en cours, attention les yeux (ça veut dire beaucoup de vues, peu de réponses ^^).

Mikell à aiguisé mes ambitions avec son code (cf http://www.autoitscript.fr/forum/viewto ... =3&t=14011 )
► Afficher le texte
Je me rend compte de la puissance d'Autoit, et me met à fantasmer... (Merci Mikell ^^)
Je reste frustré car je n'ai pas les moyens de mes ambitions. Je manque cruellement de connaissances, mais j'ai une idée de script qui en aiderai plus d'un (est il utile de le convertir en fonction?)

Il s'agit d'une saisie prédictive basée sur un tableau (csv).
Voici un exemple du fichier csv:
Parisot, Nombre d'habitants1, code postal1
Paris, Nombre d'habitants2, code postal2
Parennes, Nombre d'habitants3, code postal3

Il faudra que l'on puisse ajouter des lignes dans le fichier csv si on le souhaite sans devoir modifier le code (l'utilisateur peut mettre à jour sans dépendre du programmeur). Je pense ici à la longueur de la table qui doit être inscrite dans le code.

Dans une inputbox, l'utilisateur tape: "Par", la saisie prédictive lui suggère donc Parisot, Paris et Parennes.
L'utilisateur tape "Pari", on lui suggère "Paris" et "Parisot"
S'il tape Pariso, on lui suggère "Parisot"
Soyons exigeant.
L'utilisateur tape "isot", on lui suggère "Parisot"
Il tape "ris" on lui suggère "Paris" ou "Parisot"

Dernière chose, si l'utilisateur tape "a", ça serait bien de limiter la taille de la liste proposée ^^) <-- surtout si le Tableau comprend plusieurs centaines de lignes...

Par contre, je préfère rester modeste, je suis limite au niveau de la compréhension du code de Mikell (surtout sur la partie hors du code, concernant le fonctionnement des UDF), donc j'ai bien peur de ne savoir comprendre tout ce que vous proposerez :roll:
L'idéal serait de coder de façon à ce que ce soit utilisable par tout codeur afin de ne pas travailler uniquement pour un utilisateur (Moi 8) ) mais pour la communauté. Je suis d'ailleurs surpris que ça n'existe pas déjà, j'ai tapé "prédictive" en mot clé, et je n'ai pas trouvé une seule réponse concernant ce besoin.

D'avance Merci, ravi d'avoir occupé votre esprit quelques heures pour ceux qui relèveront le défi ^^.

A+
Julien.
Kuma
Niveau 1
Niveau 1
Messages : 3
Enregistré le : mar. 23 juin 2015 20:57
Status : Hors ligne

Re: [...] Saisie predictive - données stoquées sur fichier CSV

#2

Message par Kuma »

Salut,

Je pense qu'en utilisant GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") + stringinstr() tu peux actualiser un tableau à chaque frappes.

Tu peux ensuite mettre à jour ton combo avec ton tableau.
Avatar du membre
orax
Modérateur
Modérateur
Messages : 1479
Enregistré le : lun. 23 mars 2009 04:50
Localisation : ::1
Status : Hors ligne

Re: [...] Saisie predictive - données stoquées sur fichier CSV

#3

Message par orax »

JulienBoul a écrit :Je suis d'ailleurs surpris que ça n'existe pas déjà, j'ai tapé "prédictive" en mot clé, et je n'ai pas trouvé une seule réponse concernant ce besoin.
Recherche plutôt complétion ou autocomplétion.
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [...] Saisie predictive - données stoquées sur fichier CSV

#4

Message par mikell »

For ze fun voilà un exemple :mrgreen:
Le code (un peu bricolé) vient tout droit du forum US. C'est un peu tordu parce qu'il n'utilise pas une combo mais une gui popup avec une liste
[si la quantité de données est très importante il vaudrait probablement mieux passer par une base de données]

Code : Tout sélectionner

; http://www.autoitscript.com/forum/topic/158070-autocomplete-input-text/

#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <File.au3>
#include <Array.au3>

$csv = "Parisot,Nombre d'habitants1,code postal1" & @crlf & _
	"Paris,Nombre d'habitants2,code postal2" & @crlf & _
	"Parennes,Nombre d'habitants3,code postal3"
If not FileExists("test.csv") Then FileWrite("test.csv", $csv)

Global $array_csv
_FileReadToArray("test.csv", $array_csv, 0, ",")
;_ArrayDisplay($array_csv)

Global $villes[UBound($array_csv)] 
For $i = 0 to UBound($array_csv)-1
   $villes[$i] = $array_csv[$i][0]
Next
;_ArrayDisplay($villes)

Global $hList, $idCurInput, $sCurrInput = "", $hListGUI = -1

$hGUI = GUICreate("AutoComplete Input Text", 300, 150)
GUICtrlCreateLabel('ville', 10, 10, 280, 20)
$hInput = GUICtrlCreateInput("", 10, 30, 280, 20)
GUICtrlCreateLabel('informations', 10, 70, 280, 20)
$hInput2 = GUICtrlCreateInput("", 10, 90, 130, 20)
$hInput3 = GUICtrlCreateInput("", 150, 90, 130, 20)
GUISetState(@SW_SHOW, $hGUI)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
        ExitLoop
  EndSwitch
WEnd



Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
   #forceref $hWnd, $Msg, $lParam
    Local $IdFrom = BitAnd($wParam, 0x0000FFFF)
    Local $iCode = BitShift($wParam, 16)
    Switch $IdFrom
       Case $hInput
          Switch $iCode
            Case $EN_UPDATE
               $idCurInput = $IdFrom
                _Update($idCurInput)
          EndSwitch
       Case $hList
         _Update($idCurInput)
    EndSwitch
   Return $GUI_RUNDEFMSG
EndFunc


Func _Update($_input)
    If GUICtrlRead($_Input) <> $sCurrInput Then 
        $sCurrInput = GUICtrlRead($_Input)
        If $hListGUI <> -1 Then ; List is visible.
             GUIDelete($hListGUI)
             $hListGUI = -1
        EndIf
        If GUICtrlRead($hInput) = "" Then 
           GuiCtrlSetData($hInput2, "")
           GuiCtrlSetData($hInput3, "")
        EndIf
        $hList = _PopupSelector($hGUI, $hListGUI, $_Input, _CheckInputText($_Input, $villes)) 

; optionnel
        If $hList = -1 Then 
            GuiCtrlSetData($_Input, "")
            $sCurrInput = GUICtrlRead($_Input)
        EndIf
    EndIf
; ------

    Local $sChosen
    If $hList <> -1 Then $sChosen = GUICtrlRead($hList)
    If $sChosen <> "" Then
        GuiCtrlSetData($_Input, $sChosen)
        For $i = 0 to UBound($villes)-1
             If $sChosen = $villes[$i] Then 
                 GuiCtrlSetData($hInput2, $array_csv[$i][1])
                 GuiCtrlSetData($hInput3, $array_csv[$i][2])
             EndIf
        Next

        $sCurrInput = GUICtrlRead($_Input)
        GUIDelete($hListGUI)
        $hListGUI = -1
    EndIf
EndFunc  ;==>_Update


Func _PopupSelector($hMainGUI, ByRef $hListGUI, $_Input, $sCurr_List)
    Local $hList = -1
    If $sCurr_List = "" Then Return $hList

    Local $pos = ControlGetPos($hMainGUI, "", $_Input)
    $hListGUI = GUICreate("", 280, 160, $pos[0], $pos[1]+$pos[3], $WS_POPUP, _ 
		BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST, $WS_EX_MDICHILD), $hMainGUI)
    $hList = GUICtrlCreateList("", 0, 0, 280, 150, BitOR(0x00100000, 0x00200000))
    GUICtrlSetData($hList, $sCurr_List)

    StringReplace($sCurr_List, "|", "|")
    Local $iCurrHeight = @extended * GUICtrlSendMsg($hList, $LB_GETITEMHEIGHT, 0, 0) + 10
    WinMove($hListGUI, "", Default, Default, Default, $iCurrHeight)
    GUICtrlSetPos($hList, 0, 0, 150, $iCurrHeight)

    GUISetControlsVisible($hListGUI) ; To Make Control Visible And Window Invisible.
    GUISetState(@SW_SHOWNOACTIVATE, $hListGUI)
    Return $hList
EndFunc   ;==>_PopupSelector


Func _CheckInputText($_Input, $array)
   Local $sPartialData = ""
   Local $aSelected = _GetSelectionPointers($_Input)
    If (IsArray($aSelected)) And ($aSelected[0] <= $aSelected[1]) Then
        $sCurrInput = GUICtrlRead($_Input)
        Local $aSplit = StringSplit(StringLeft($sCurrInput, $aSelected[0]), " ")
        $aSelected[0] -= StringLen($aSplit[$aSplit[0]])
        If $aSplit[$aSplit[0]] <> "" Then
            For $A = 0 To UBound($array)-1
                If StringLeft($array[$A], StringLen($aSplit[$aSplit[0]])) = $aSplit[$aSplit[0]] _ 
				And $array[$A] <> $aSplit[$aSplit[0]] Then
                    $sPartialData &= $array[$A] & "|"
                EndIf
            Next
        EndIf
    EndIf
    Return $sPartialData
EndFunc   ;==>_CheckInputText


Func _GetSelectionPointers($hEdit)
    Local $aReturn[2] = [0, 0]
    Local $aSelected = GUICtrlRecvMsg($hEdit, 0x00B0) ; $EM_GETSEL.
    If IsArray($aSelected) Then
        $aReturn[0] = $aSelected[0]
        $aReturn[1] = $aSelected[1]
    EndIf
    Return $aReturn
EndFunc   ;==>_GetSelectionPointers


Func GUISetControlsVisible($hWnd) ; By Melba23.
    Local $aControlGetPos = 0, $hCreateRect = 0, $hRectRgn = _WinAPI_CreateRectRgn(0, 0, 0, 0)
    Local $iLastControlID = _WinAPI_GetDlgCtrlID(GUICtrlGetHandle(-1))
    For $i = 3 To $iLastControlID
        $aControlGetPos = ControlGetPos($hWnd, '', $i)
        If IsArray($aControlGetPos) = 0 Then ContinueLoop
        $hCreateRect = _WinAPI_CreateRectRgn($aControlGetPos[0], $aControlGetPos[1], _ 
			$aControlGetPos[0] + $aControlGetPos[2], $aControlGetPos[1] + $aControlGetPos[3])
        _WinAPI_CombineRgn($hRectRgn, $hCreateRect, $hRectRgn, 2)
        _WinAPI_DeleteObject($hCreateRect)
    Next
    _WinAPI_SetWindowRgn($hWnd, $hRectRgn, True)
    _WinAPI_DeleteObject($hRectRgn)
EndFunc   ;==>GUISetControlsVisible

" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2282
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [...] Saisie predictive - données stoquées sur fichier CSV

#5

Message par jchd »

SQLite est parfait pour faire ça en réel, à cause du volume et du besoin de désaccentuation ou de recherche floue, par exemple. Le côté GUI étant cosmétique, ce qui importe en premier c'est souvent la puissance et la souplesse du moteur sous-jacent. On peut toujours rajouter une couche de maquillage quand les fondations sont solides.

Je n'ai pas l'information "population" dans ma table de codes postaux, mais voici deux exemples de requêtes : la première sur préfixe et la seconde floue. Les critères cedex et autres filtrent les codes usuels. Chaque requête prend grosso modo 500 ms sur mon vieux clou à partir d'une bonne grosse base stockée sur disque, la table ayant circa 75400 rangs.
SELECT ville, code FROM codespostaux WHERE paysiso = 'FR' AND ville LIKE 'monch%' AND NOT (cedex OR special OR cityssimo OR armee OR air) ORDER BY ville, code;
renvoie ceci :
Ville Code
MONCHAUX SORENG   76340
MONCHAUX SUR ECAILLON   59224
MONCHEAUX   59283
MONCHEAUX LES FREVENT   62270
MONCHECOURT 59234
MONCHEL SUR CANCHE   62270
MONCHEUX 57420
MONCHIET 62123
MONCHY AU BOIS 62111
MONCHY BRETON  62127
MONCHY CAYEUX  62134
MONCHY HUMIERES   60113
MONCHY LAGACHE 80200
MONCHY LE PREUX   62118
MONCHY ST ELOI 60290
MONCHY SUR EU  76260
SELECT ville, code FROM codespostaux WHERE paysiso = 'FR' AND typos(ville, 'minchic%') < 3 AND NOT (cedex OR special OR cityssimo OR armee OR air) ORDER BY ville, code;
renvoie ceci :
Ville Code
MANCHECOURT 45300
MONCHECOURT 59234
MONCHIET 62123
RANCHICOURT 62150
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Répondre