Code : Tout sélectionner
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>
Opt("GuiOnEventMode", 1)
; initialisation =============================
Global $lastclicked = 0, $var = 0, $base = @ScriptDir & "\genea2.sqlite"
Local $array, $iRows, $iColumns, $iRval, $hQuery
_SQLite_Startup ()
_SQLite_Open($base)
;==================== création de la base =====================
If FileRead($base) = "" Then
SplashTextOn ("", "Création de la base...", 280, 55, -1, -1, 49)
; ################ déclarer les types de données autant que possible
; ################ déclarer id comme "integer not null primary key autoincrement" ; id devient alors un alias de rowid
; ################ voir plus bas pourquoi ce schéma ne convient pas : papa & maman sont déjà dans la table, donc il ne faut pas
; ################ faire figurer leur nom, prénom, infos et autres en plusieurs endroits.
_SQLite_Exec (-1, "CREATE TABLE IF NOT EXISTS liste " & _
"(id , date, inc1, inc2, inc3, nom, prenom, sexe, inc4, " & _
"nompapa, prenompapa, infopapa, inc5, nommaman, prenommaman, " & _
"inc6, inc7, inc8, inc9, inc10, inc11, preinc, info1, info2, inc12, inc13);")
$file = FileOpen(@ScriptDir & "\genea.txt", 0) ; fichier texte
$i = 1
; ################ toujours grouper les modifications massives à l'intérieur d'une transaction
_SQLite_Exec(-1, "Begin;")
While 1
$line = FileReadLine($file)
If @error = -1 Then ExitLoop
$a = _TriLigne($line)
; ############### ne pas fournir de valeur pour id ; c'est un rowid dont la valeur est indifférente qui doit être géré par SQLite, c'est juste une
; ############### étiquette unique, une sorte de n° de série interne
; ############### il nous faut déterminer si la rangée n'a pas déjà été insérée dans la base : "insert or replace" après création d'un index unique
; ############### qui permettra d'éviter le clash sur personnes homonymes de la même époque
; ############### il faut que les FK papaid et mamanid sur id soient déclarées "cascade" (voir plus bas pour les FKs)
; ############### ici, du fait que $i part de 1 et si on fait tourner N fois le prog avec le même fichier d'entrée, on aura N-1 doublons
_SQLite_Exec(-1, "INSERT INTO liste VALUES ('" & $i & "', " & _
_SQLite_FastEscape($a[1]) & ", " & _
_SQLite_FastEscape($a[2]) & ", " & _
_SQLite_FastEscape($a[3]) & ", " & _
_SQLite_FastEscape($a[4]) & ", " & _
_SQLite_FastEscape($a[5]) & ", " & _
_SQLite_FastEscape($a[6]) & ", " & _
_SQLite_FastEscape($a[7]) & ", " & _
_SQLite_FastEscape($a[8]) & ", " & _
_SQLite_FastEscape($a[9]) & ", " & _
_SQLite_FastEscape($a[10]) & ", " & _
_SQLite_FastEscape($a[11]) & ", " & _
_SQLite_FastEscape($a[12]) & ", " & _
_SQLite_FastEscape($a[13]) & ", " & _
_SQLite_FastEscape($a[14]) & ", " & _
_SQLite_FastEscape($a[15]) & ", " & _
_SQLite_FastEscape($a[16]) & ", " & _
_SQLite_FastEscape($a[17]) & ", " & _
_SQLite_FastEscape($a[18]) & ", " & _
_SQLite_FastEscape($a[19]) & ", " & _
_SQLite_FastEscape($a[20]) & ", " & _
_SQLite_FastEscape($a[21]) & ", " & _
_SQLite_FastEscape($a[22]) & ", " & _
_SQLite_FastEscape($a[23]) & ", " & _
_SQLite_FastEscape($a[24]) & ", " & _
_SQLite_FastEscape($a[25]) & ");")
$i += 1
WEnd
; ############### fin de la transaction = une seule phase de MAJ massive de la bdd
_SQLite_Exec(-1, "Commit;")
FileClose($file)
SplashOff()
EndIf
;================ chargement ==============================
SplashTextOn ("", "Chargement ...", 280, 55, -1, -1, 49)
$gui = GuiCreate("genea", 600, 600)
GuiSetOnEvent(-3, "_Exit")
$listview = GuiCtrlCreateListview("n°|date|nom|papa|maman", 5, 5, 590, 550, -1, _
BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $WS_EX_CLIENTEDGE))
GUICtrlSendMsg($listview, $LVM_SETCOLUMNWIDTH, 0, 40)
; ############ faire effectuer le formattage du résultat par SQLite, plutôt que de refaire une boucle ensuite pour tout concaténer entre des '|'
; ############ sur le modèle : select colA || '|' || colB || '|' || colC .... SQLite possède plein de fonctions implémentées efficacement en C
; ############ et il est beaucoup plus rapide de confier ce boulot au moteur qui l'effectuera au vol pour chaque rangée du résultat
; ############ attention : ici id n'est pas forcément = rowid. Déclarer id en integer not null primary key (pas int, ce n'est pas pareil !)
; ############ ce schéma n'est pas bon car pas normalisé. Outre l'exigeance académique, le pb est que si un jour on s'aperçoit qu'en fait
; ############ tel ancêtre s'appelait Benoistre à l'époque et non pas Benoît comme on l'a enregistré, il faudra partir à la pêche pour corriger
; ############ dans sa descendance. Il faut ici utiliser des références au père et à la mère (leur propre id) en lieu et place d'une copie de leurs infos
; ############ Il faut donc déclarer des papaid et mamanid qui seront des FK (clés étrangères) à cette même table
; ############ du coup ce select deviendrait (juste un sketch)
; select id, date, nom, prenom, p.nom, p.prenom, m.nom, m.prenom from liste join liste as p on p.id = papaid join liste as m on m.id = mamanid;
_SQLite_GetTable2d (-1, "SELECT id, date, nom, prenom, nompapa, prenompapa, " & _
"nommaman, prenommaman FROM liste;", $array, $iRows, $iColumns)
For $i = 1 to UBound($array)-1
GUICtrlCreateListViewItem($array[$i][0] &"|"& $array[$i][1] &"|"& _
$array[$i][2] &" "& $array[$i][3] &"|"& $array[$i][4] &" "& _
$array[$i][5] &"|"& $array[$i][6] &" "& $array[$i][7] , $listview)
Next
SplashOff()
GuiSetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
While 1
Sleep(10)
Wend
;=====================================================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
$hListView = GuiCtrlGetHandle($listView)
Switch $hWndFrom
Case $hListView
Switch $iCode
Case $LVN_COLUMNCLICK
$tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)
$colonne = DllStructGetData($tInfo, "SubItem")
If $colonne = $lastclicked Then
$var = not $var
Else
$var = 0
EndIf
$lastclicked = $colonne
_LVSort($colonne, $var)
Case $NM_DBLCLK ; CLICK
Local $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
$item = DllStructGetData($tInfo, "Index")+1
Local $name = ControlListView($gui, "", $listview, "GetText", $item-1, 2)
_ShowData($item, $name)
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Func _LVSort($nColumn, $var)
Local $ar_tri, $iRows, $iColumns, $pattern
Switch $nColumn
Case 0
$pattern = "rowid "
Case 1
$pattern = "date "
Case 2
$pattern = "nom, prenom "
Case 3
$pattern = "nompapa, prenompapa "
Case 4
$pattern = "nommaman, prenommaman "
EndSwitch
Local $sort[2] = ["ASC", "DESC"]
Local $sens = $sort[$var]
SplashTextOn ("", "Chargement ...", 280, 55, -1, -1, 49)
Sleep(10)
; ############ faire effectuer le formattage du résultat par SQLite, plutôt que de refaire une boucle ensuite pour tout concaténer entre des '|'
; ############ genre : select colA || '|' || colB || '|' || colC .... SQLite possède plein de fonctions implémentées efficacement en C
; ############ et il est beaucoup plus rapide de confier ce boulot au moteur qui l'effectuera au vol pour chaque rangée du résultat
; ############ attention : ici id n'est pas forcément = rowid. Déclarer id en integer not null primary key (pas int, ce n'est pas pareil !)
; ############ ce schéma n'est pas bon car pas normalisé. Outre l'exigeance académique, le pb est que si un jour on s'aperçoit qu'en fait
; ############ tel ancêtre s'appelait Benoistre à l'époque et non pas Benoït comme on l'a enregistré, il faudra partir à la pêche pour corriger
; ############ sa descendance. Il faut ici utiliser des références au père et à la mère (leur id)
; ############ Il faut donc déclarer des papaid et mamanid qui seront des FK (clés étrangères) à cette même table
_SQLite_GetTable2d (-1, "SELECT id, date, nom, prenom, nompapa, prenompapa, " & _
"nommaman, prenommaman FROM liste " & _
"ORDER BY " & $pattern &" "& $sens & ";", $ar_tri, $iRows, $iColumns)
_GUICtrlListView_DeleteAllItems($listview)
For $i = 1 to UBound($ar_tri)-1
GUICtrlCreateListViewItem($ar_tri[$i][0] &"|"& $ar_tri[$i][1] &"|"& _
$ar_tri[$i][2] &" "& $ar_tri[$i][3] &"|"& $ar_tri[$i][4] &" "& _
$ar_tri[$i][5] &"|"& $ar_tri[$i][6] &" "& $ar_tri[$i][7] , $listview)
Next
SplashOff()
EndFunc
Func _ShowData($item, $name)
Local $aResult, $aNames, $hQuery
; ############ éviter select * ... car l'ordre des colonnes dépend de la base. si elle doit être réorganisée, ça foutra le souk
; ############ discossier le nom des colonnes des tables et le nom souhaité pour l'affichage d'une listview
; ############ combattre la flemme et coder select colA, colB, colC, ... Ainsi le résultat ne dépend plus de l'ordre des colonnes dans la table
; ############ faire effectuer le formattage du résultat par SQLite, plutôt que de refaire une boucle ensuite pour tout concaténer entre des '|'
; ############ genre : select colA || '|' || colB || '|' || colC .... SQLite possède plein de fonctions implémentées efficacement en C
; ############ et il est beaucoup plus rapide de confier ce boulot au moteur qui l'effectue au vol pour chaque rangée du résultat
; ############ ici, faire un _SQLite_GetTable
_SQlite_Query (-1, "SELECT * FROM liste WHERE rowid='" & $item &"';", $hQuery)
_SQLite_FetchNames($hQuery, $aNames)
_SQLite_FetchData ($hQuery, $aResult)
_SQLite_QueryFinalize($hQuery)
Local $details_gui = GuiCreate($name, 300, 300)
GuiSetOnEvent(-3, "_Close", $details_gui)
Local $details_LV = GuiCtrlCreateListview("col|details", 10, 10, 280, 280, -1, _
BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $WS_EX_CLIENTEDGE))
GUICtrlSendMsg($details_LV, $LVM_SETCOLUMNWIDTH, 0, 90)
GUICtrlSendMsg($details_LV, $LVM_SETCOLUMNWIDTH, 1, 160)
For $i = 1 to UBound($aResult)-1
GUICtrlCreateListViewItem($aNames[$i] &"|"& $aResult[$i], $details_LV)
Next
GuiSetState()
EndFunc
Func _TriLigne($ligne)
$ligne = StringRegExpReplace($ligne, "/{2,}", "/")
Local $split = StringSplit($ligne, "|")
Local $array_ligne[$split[0]+1]
Local $date = StringSplit($split[1], "/")
$array_ligne[0] = $split[0]
$array_ligne[1] = $date[3] & " (" & $date[2] & " " & $date[1] & ")" ; date2
For $i = 2 to $split[0]
$array_ligne[$i] = $split[$i]
Next
Return $array_ligne
EndFunc
Func _Exit()
_SQLite_Close ()
_SQLite_Shutdown ()
Exit
EndFunc
Func _Close()
GuiDelete(@GUI_WinHandle)
EndFunc