[R] Delete item listview et sqlite & réindexation

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

[R] Delete item listview et sqlite & réindexation

#1

Message par aulus »

Bonjour,

Le premier champ de la base sqlite, nommé "id" numérote chaque ligne. Ce champ s'incrémentant à chaque création de ligne supplémentaire.
Le contenu de la base s'affiche dans un listview. Trois boutons permettent de modifier la base : Ajouter une ligne, Modifier et Supprimer la ligne sélectionnée. Jusque là tout va bien.

A la suite de la suppression de ligne, je souhaiterais que les lignes retrouvent une numérotation continue, aussi bien dans la base sqlite, que dans le listview :
Je ne parviens pas à faire cela.
J'imagine mettre à jour la base sqlite, dans une boucle pour décrémenter d'1 tous les enregistrements supérieurs au numéro de la ligne supprimée.
Mais là je suis perdu.

Code : Tout sélectionner

;suppression de la ligne sélectionnée :

Local $index = ControlListView("", "", $myList, "GetSelected")

$Base_SQLite = _SQLite_Open($sqlite)
_SQLite_Exec($Base_SQLite, "DELETE FROM liste WHERE id = '" & $index & "';")

;réindexation : là rien ne va plus
$nbre_lignes =  _SQLite_Query($Base_SQLite, "sqlite_num_rows(liste);")
For $i = $index + 1 To $nbre_lignes
$decr = $i - 1
_SQLite_Query($Base_SQLite, "UPDATE liste SET id = '" & $decr & "' WHERE ID = $i;")
Next

 
Je vous remercie de votre aide.
Modifié en dernier par aulus le dim. 11 mai 2014 09:25, modifié 1 fois.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] delete item listview et sqlite & réindexation

#2

Message par jchd »

Je te déconseille de bidouiller tes identificateurs pour en faire des numéros de "ligne". Si tu as _vraiment_ besoin de numéroter tes lignes dans ta listview, fais-le mais laisse cette numérotation indépendante de rowid.

Il n'est pas compliqué de faire ça :
_sqlite_gettable2d($hdb, "select 1, col1, col2, col3 from ... where ... order by ...", ...)
ensuite tu remplaces le 1 par un vrai numéro de ligne
for...
next
et tu as ce que tu souhaites, visuellement (tu n'es pas obligé d'afficher le rowid dans ta listview).

Il faut bien comprendre qu'il n'y a aucun ordre dans une table SQL et que, sauf lorsqu'une clause "order by" est spécifiée dans un select, l'ordre peut être quelconque et même varier entre deux invocations successives.

Ah oui, aussi une autre chose qui me chiffonne : je ne sais pas comment tu as défini ta table, mais mettre $index entre quotes en fait une chaîne et non un entier.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#3

Message par aulus »

Merci pour ces précisions. J'essaie de comprendre... ce qui n'est pas gagné ! :)
Mon $index est effectivement un entier de manière à obtenir un affichage correct (10 après le 9, et non après le 1)

Je me mets à la tâche...
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#4

Message par jchd »

L'intérêt de dissocier les données de la base et leur numéro d'ordre dans ta présentation est multiple :
o) pas de pollution de la base avec des valeurs n'ayant aucun rapport avec les données qu'elle contient
o) indépendance du numéro d'ordre avec l'ordre de tri et donc l'ordre de présentation dans la listview
o) nul besoin de gérer "à la main" les numéros d'ordre après mise à jour de la base
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#5

Message par aulus »

Bonjour,

Je suis complètement perdu :( Je ne maîtrise pas suffisamment sqlite. Je vais sans doute succomber à la tentation de remplacer les bases sqlite que j'envisageais de créer par des fichiers textes que je sais manipuler.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#6

Message par jchd »

Je veux bien t'aider mais il faut poster ce qui cloche et expliciter ce que tu souhaites.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#7

Message par aulus »

Merci pour votre patience et vos encouragements.

Voici les extraits de mon code :

Ma ListView :

Code : Tout sélectionner

    $myList = GuiCtrlCreateListview("n°|mot latin|mot français|texte|oeuvre|auteur latin|manuel|page|auteur manuel|editeur", 10, 50, 1280, 480, -1, _
    BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $WS_EX_CLIENTEDGE))
    GUICtrlSendMsg(-1, 0x101E, 0, 40)      ; n°
    GUICtrlSendMsg(-1, 0x101E, 1, 100)     ; latin
    GUICtrlSendMsg(-1, 0x101E, 2, 100)     ; français
    GUICtrlSendMsg(-1, 0x101E, 3, 300)      ; texte
    GUICtrlSendMsg(-1, 0x101E, 4, 200)      ; oeuvre
    GUICtrlSendMsg(-1, 0x101E, 5, 100)     ;auteur du texte latin
    GUICtrlSendMsg(-1, 0x101E, 6, 200)      ; manuel
    GUICtrlSendMsg(-1, 0x101E, 7, 40)        ; page
    GUICtrlSendMsg(-1, 0x101E, 8, 100)       ; auteur du manuel
    GUICtrlSendMsg(-1, 0x101E, 9, 100)     ; editeur
 
Ma fonction "supprimer un enregistrement de la base sqlite et mise à jour de la listview (suppression de l'affichage de l'enregistrement supprimé et renumérotation)

Code : Tout sélectionner

Func Supprimer()
; suppression de l'enregistrement sqlite
Local $selected = ControlListView($maGui, "", $myList, "GetSelected")
Local $index = Int(ControlListView($maGui, "", $myList, "GetText", $selected, 0))
Local $sLocalSQLiteDll = @ScriptDir & "\sqlite3.dll"
_SQLite_Startup($sLocalSQLiteDll, False, 1)
If @error Then MsgBox($MB_SYSTEMMODAL, "Le fichier SQLite3.dll est introuvable")
$Base_SQLite = _SQLite_Open($sqlite)
_SQLite_Exec($Base_SQLite, "DELETE FROM liste WHERE numero = " & Number($index) & ";")

; mise à jour du champ numero ($aRow[0]) dans la base :
$nb_lignes = ??? (je ne trouve pas la fonction retournant le nombre d'enregistrements contenus dans la base sqlite)
Local $hQuery, $aRow 
_SQLite_Query($Base_SQLite, "SELECT * FROM liste ORDER BY numero DESC", $hQuery)
For $i = $index TO $nb_lignes (ne trouvant pas la fonction retournant le nombre d'enregistrements de la base, j'ai testé avec 9)
    Local $indexCorr = $i - 1
    _SQLite_Exec($Base_SQLite, _
    "UPDATE liste SET " & _
                "numero = " & $indexCorr & _
            "WHERE " & _
                "numero = " & $i & ";")
Next

; mise à jour de la listview (suppression de l'affichage de la ligne supprimée et renumérotation)
_GUICtrlListView_DeleteAllItems($myList)
While (_SQLite_FetchData ($hQuery, $aRow) = $SQLITE_OK)
GUICtrlCreateListViewItem($aRow[0] & "|" & $aRow[1] & "|" & $aRow[2] & "|" & $aRow[3] & "|" & $aRow[4] & "|" & $aRow[5] & "|" & $aRow[6] & "|" & $aRow[7] & "|" & $aRow[8] & "|" & $aRow[9], $myList)
Wend
_SQLite_Close ()
_SQLite_Shutdown ()
EndFunc
 
2 problèmes :

1. l'enregistrement supprimé dans la base n'est pas celui que j'ai sélectionné mais l'enregistrement voisin.
2. la numérotation dans la listview n'est pas bonne au réaffichage (des numéros qui se répètent 2 fois)
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#8

Message par Hugues »

Salut,

Moi pour supprimer une entrée dans un ListView, je fais:
► Afficher le texte
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#9

Message par aulus »

Bonsoir,

Ce code supprimerait éventuellement un enregistrement dans la base sqlite, mais pas dans la listview.
Je l'ai testé, mais l'enregistrement n'est pas supprimé dans la base.
Modifié en dernier par aulus le ven. 09 mai 2014 19:48, modifié 1 fois.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#10

Message par Hugues »

Bin après tu fais un refresh de ta ListView...

Tu fais un

Code : Tout sélectionner

_GUICtrlListView_DeleteAllItems($hListView)
, ensuite tu refais une requête et tu réaffiches dans ta ListView...
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#11

Message par aulus »

Ah oui d'accord.
Toutefois ce code ne me supprime pas l'enregistrement dans la base.

Mon propre code supprime bien un enregistrement dans la base, mais pas le bon !!!
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#12

Message par Hugues »

Code : Tout sélectionner

_GUICtrlListView_DeleteAllItems($hListView)
supprime le contenu de la ListView, mais pas dans la base.

Le code

Code : Tout sélectionner

$IndexItemListView = _GUICtrlListView_GetNextItem($hListView)
$aItem = _GUICtrlListView_GetItemText($hListView, $IndexItemListView)

_SQlite_Query (-1, "SELECT * FROM " & $Table & " WHERE ID = " & $aItem & ";", $hQuery)
local $req =_SQLite_Exec (-1, "DELETE FROM " & $Table & " WHERE ID = " & $aItem & ";")
supprime dans la base SQLite.

Et pour retourner le nombre de lignes contenues dans ta base et remplir ta ListView:

Code : Tout sélectionner

$iRval = _SQLite_GetTable2d(-1, "SELECT * FROM " & $Table & ";", $aResult, $iRows, $iColumns) ;$iRows -> Nombre de lignes

If $iRval = $SQLITE_OK Then
        Dim $TempArray[$iRows][Ton nombre de colonnes]

        For $r = 1 To $iRows
            For $c = 0 To 9
                $TempArray[$r-1][$c] = $aResult[$r][$c]
                        Next
                Next
                EndIf

        _GUICtrlListView_AddArray($hListView, $TempArray)

 
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#13

Message par aulus »

Oui, j'ai bien noté.

EDIT : SI, votre code supprime bien la ligne sélectionnée dans le listview. Dans le message ci-dessus j'ai parlé trop vite. Je m'excuse.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#14

Message par Hugues »

:mrgreen: et ça supprime le bon enregistrement?
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#15

Message par aulus »

Une erreur bloque le programme :

(1545) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
$TempArray[$r-1][$c] = $aResult[$r][$c]
^ ERROR
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#16

Message par Hugues »

Il faut que tu adaptes à la taille de ta base.

Tu dimensionnes ton tableau : Dim $TempArray[$iRows][Ton nombre de colonnes] -> $iRows étant le nombre de lignes contenues dans ta base retournée par la requête:

Code : Tout sélectionner

$iRval = _SQLite_GetTable2d(-1, "SELECT * FROM " & $Table & ";", $aResult, $iRows, $iColumns)
ensuite tu fais une boucle pour récupérer les valeurs:

Code : Tout sélectionner

For $r = 1 To $iRows ; -> Boucle de lecture de la ligne 1 à la dernière
    For $c = 0 To 9; -> Boucle de la colonne 0 à la colonne 9 (à adapter selon tes besoins)
        $TempArray[$r-1][$c] = $aResult[$r][$c]
    Next
Next

 
puis tu remplis ta ListView:

Code : Tout sélectionner

_GUICtrlListView_AddArray($hListView, $TempArray)
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#17

Message par mikell »

aulus tu as vraiment besoin de ce champ 'numero' ?
Tu pourrais très bien faire le delete dans la base avec un WHERE *autre chose* et repeupler ensuite la listview avec un _SQLite_GetTable2d avec (ou non) un ORDER BY
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
GaRydelaMer
Niveau 7
Niveau 7
Messages : 450
Enregistré le : mer. 18 mars 2009 22:12
Localisation : Montpellier
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#18

Message par GaRydelaMer »

Bonjour

j'utilise tous les jours des bases et des listviews, et j'ai résolu ce genre de problème en détournant la fonctionnalité AutoIt des LV.
J'utilise aussi le mode événementiel et des objets que je créé avec AutoItObject, donc je vais pas te donner du code mais le principe, pour le code faut que je retrouve mes vieux projets.

Je m'explique:
J'utilise les listviews créé avec l'UDF Listview, car AutoIt utilise un paramètre invisible pour stocker les identifiants des items de la liste et utilise cet identifiant dans le mode événementiel. C'est pas le cas avec l'UDF, donc je vais utiliser pour moi cette zone pour stocker mon rowid sans gêner le mode événementiel.

Tu as donc ta requête qui te renvoie une liste d'enregistrement: $Datas (j'utilise pas SQLlite mais ADO, le principe est le même), $oConn la connection.
rowid, champ1, champ2 etc....
rowid et le champ de la table un entier autoincrément gérer par la base de donnée.

Cn boucle sur cette liste du début tant que je suis pas à la fin:

Code : Tout sélectionner

While Not $Datas.EOF ;

  $Datas.MoveNext
Wend
L'idée dans cette boucle de peuplé la liste en ajoutant des Items

Code : Tout sélectionner

$iItem = _GUICtrlListView_InsertItem($hLisvtView, $Datas.Fields("champ1").value) ; j'insère un item avec comme texte la valeur du Champ1
_GUICtrlListView_SetItemText($hLisvtView, $iItem, $Datas.Fields("champ2").value, 1) ; on ensuite mettre à jour les valeurs dans les colonnes
_GUICtrlListView_SetItemText($hLisvtView, $iItem, $Datas.Fields("champ2").value, 2)
etc...
_GUICtrlListView_SetItemParam($hLisvtView, $iItem, Int($Datas.Fields("rowid"). value)) ;; C'est ici que je stocke l'identifiant unique de l'enregistrement dans la table.
Ensuite tu peux lire très simplement la ligne dans la liste et la relier à la ligne dans ta base de plus tu peux faire une requête pour afficher la liste et aller modifier la ligne dans la table.
Ici on va retrouver la liste sous forme de tableau des index dans la liste des items sélectionnés

Code : Tout sélectionner

Local $aItems = _GUICtrlListView_GetSelectedIndices($hListView))
Pour supprimer dans la base et la liste

Code : Tout sélectionner

For $i = $aItems[0] to 1 Step -1 ; je boucle à l'envers si tu as plusieurs items sélectionnés pour pas que la LV ré-indexe les Items du tableau $aItems
    $iItem = $aItems[$i] ; je prend l'index de l'item dans le tableau
    $iRowID = _GUICtrlListView_GetItemParam($hLisvtView, $iItem) ; je récupère ici la valeur du paramètre caché de la LV qui contient mon identifiant unique dans la base.
   _GUICtrlListView_DeleteItem($hLisvtView, $iItem) ; Je supprime l'item dans la listview
    $oConn.Execute("DELETE FROM la_Table WHERE rowid = " & $iRowID) ; ici tu vas le supprimé dans la base et le tour est joué
Next
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#19

Message par jchd »

Exactement cela.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
aulus
Niveau 7
Niveau 7
Messages : 424
Enregistré le : lun. 25 mars 2013 19:38
Status : Hors ligne

Re: [..] Delete item listview et sqlite & réindexation

#20

Message par aulus »

Hugues a écrit ::mrgreen: et ça supprime le bon enregistrement?
Non !
Hugues a écrit :Il faut que tu adaptes à la taille de ta base
Tu dimensionnes ton tableau : Dim $TempArray[$iRows][Ton nombre de colonnes]
Maintenant c'est bon : ce "détail" m'avait échappé à la lecture du code.
mikell a écrit :aulus tu as vraiment besoin de ce champ 'numero' ?
Tu pourrais très bien faire le delete dans la base avec un WHERE *autre chose* et repeupler ensuite la listview avec un _SQLite_GetTable2d avec (ou non) un ORDER BY
Le problème est que je ne peux pas faire un WHERE sur un autre champ, car tous les champs peuvent se répéter :

VALUES (1,'cum','quand','Comment on devient serf','Liber de servis','Marmoutiers','Moyen âge','14','Delannoy','OCDL');")
VALUES (2,'cum','comme','Comment on devient serf','Liber de servis','Marmoutiers','Moyen âge','14','Delannoy','OCDL');")
VALUES (3,sicut','comme','Comment on devient serf','Liber de servis','Marmoutiers','Moyen âge','14','Delannoy','OCDL');")
GaRydelaMer a écrit :Bonjour
j'utilise tous les jours des bases et des listviews, et j'ai résolu ce genre de problème en détournant la fonctionnalité AutoIt des LV.
J'utilise aussi le mode événementiel et des objets que je créé avec AutoItObject, donc je vais pas te donner du code mais le principe, pour le code faut que je retrouve mes vieux projets... ...
Merci pour tout ce code qu'il me faut étudier.

=================================================

Grand merci à tous ! Je poursuis mes essais et vous informe de l'évolution...
Répondre