Page 1 sur 1

Alimenter TreeView depuis une base de données

Publié : dim. 12/avr./2020 17:58
par pls
Bonjour,

Nouveau sur le forum et débutant en PUREBASIC, j'aurai besoin de vos conseils.

J'ai une BDD Oracle avec 2 tables.

Table1 : liste des applications
Table2 : liste des tables de l'application qui référence la table 1 par un code.

Je souhaite créer un treeview qui me permette d'avoir la liste des applis que je peux déplier pour avoir la liste des tables que contient l'application.

app1
table1
table1
app2
table1
table2
table3

Pas de soucis pour me connecter à Oracle avec ODBC par contre je bute sur la mise en œuvre.
J'ai fait quelques essais et j'arrive bien a alimenter le 1er niveau du treeview je ne vois pas comment ajouter le second (je ne peux pas utiliser le même DBID).
De plus, j'aimerai quand le clique sur une appli ou une table dans le treeview, afficher le reste des information des applis ou table.

Merci de vos précieux conseils.

Code : Tout sélectionner

UseODBCDatabase()

#DBID = 0
#TREE1 = 1

If Not OpenDatabase(#DBID, "DW_CARTO", "XJKDSJDQMFK", "XJKDSJDQMFK")
  MessageRequester("BDD","PB COnnexion " + DatabaseError(),#PB_MessageRequester_Warning)
EndIf

reqApp.s = "Select code_app, lib_app from carto_application"
reqEnt.s = "Select code_entite, nom_entite from carto_entite"+
           " where fk_code_app = "+codeApp

If Not DatabaseQuery(#DBID, reqApp)
  MessageRequester("Sql Error",reqApp+Chr(10)+DatabaseError(),#PB_MessageRequester_Error)
EndIf

If OpenWindow(0, 0, 0, 800, 600, "Carto", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(#TREE1, 10, 10, 300, 580) 
  If DatabaseQuery(#DBID, reqApp)
    While NextDatabaseRow(#DBID)
      AddGadgetItem(#TREE1, -1, GetDatabaseString(#DBID,DatabaseColumnIndex(#DBID,"LIB_APP")),0,0)
    Wend
  EndIf
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Debug #DBID

CloseDatabase(#DBID)

Re: Alimenter TreeView depuis une base de données

Publié : dim. 12/avr./2020 19:52
par Marc56
Bonjour,

Pour décaler donc créer une branche il faut mettre en cinquième paramètre de getgadgetitem un numéro supérieur à celui de la ligne précèdente

Pour récupérer le numéro de l'element sélectionné il faut utiliser Getgadgetstate

:wink:

Re: Alimenter TreeView depuis une base de données

Publié : dim. 12/avr./2020 21:06
par pls
Bonjour,

Merci pour ta réponse rapide.
Top pour le Getgadgetstate, ça va bien m'aider et le positionnement dans le treeview, ça marche impeccable :)

J'ai quand même un truc qui me fait bizarre, j'ai du ouvrir 2 fois ma DBB car comme je lance 2 requêtes différentes, j'adresse 2 curseurs différents.
Ça vous parait normal ? Il y a peut être un moyen moins biscornu ? Une requête unique sur les 2 tables ?

Merci,
Philippe.

Code : Tout sélectionner

reqApp.s = "Select code_app, lib_app from carto_application order by lib_app"

If Not DatabaseQuery(#DBID, reqApp)
  MessageRequester("Sql Error",reqApp+Chr(10)+DatabaseError(),#PB_MessageRequester_Error)
EndIf

If OpenWindow(0, 0, 0, 1024, 780, "Carto", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(#TREE1, 10, 10, 300, 760) 
  If DatabaseQuery(#DBID, reqApp)
    While NextDatabaseRow(#DBID)
      codeApp = GetDatabaseLong(#DBID,DatabaseColumnIndex(#DBID,"CODE_APP"))
      AddGadgetItem(#TREE1, -1, GetDatabaseString(#DBID,DatabaseColumnIndex(#DBID,"LIB_APP")),0,0)
      OpenDatabase(#DBID1, "DW_CARTO", "DW", "DW")
      If DatabaseQuery(#DBID1, "Select code_entite, nom_entite from carto_entite where fk_code_app = "+codeApp+
                               " order by nom_entite")
        While NextDatabaseRow(#DBID1)
          AddGadgetItem(#TREE1, -1, GetDatabaseString(#DBID1,DatabaseColumnIndex(#DBID1,"NOM_ENTITE")),0,1)
        Wend
      EndIf 
      CloseDatabase(#DBID1)
    Wend
  EndIf
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

CloseDatabase(#DBID)

Re: Alimenter TreeView depuis une base de données

Publié : lun. 13/avr./2020 7:48
par Marc56
Bonjour,
J'ai quand même un truc qui me fait bizarre, j'ai du ouvrir 2 fois ma DBB car comme je lance 2 requêtes différentes, j'adresse 2 curseurs différents.
Ça vous parait normal ? Il y a peut être un moyen moins biscornu ? Une requête unique sur les 2 tables ?
Oui, pourquoi ne pas faire une jointure ?

Car en plus, tel que tu l'as écrit, tu ré-ouvres et referme la connexion à chaque ligne.
Un appel à FinishDatabaseQuery() après lecture de la dernière ligne (NextDatabaseRow) permet de libérer la ressource et exécuter une autre requête donc remet le curseur au début.

Code : Tout sélectionner

[...]    
While NextDatabaseRow(#DBID)
[...]
      OpenDatabase(#DBID1, "DW_CARTO", "DW", "DW")
[...]
:wink:

Re: Alimenter TreeView depuis une base de données

Publié : lun. 13/avr./2020 8:35
par pls
Merci beaucoup pour tes précieux conseils.

Re: Alimenter TreeView depuis une base de données

Publié : lun. 13/avr./2020 9:35
par Marc56
Je n'ai que des connaissances de base en SQL et pas du tout en Oracle, mais je suppose que quelque chose comme ceci devrait te permettre d'interroger les deux tables en une seule.
(Pas sûr pour la syntaxe alias de tables)

À faire vérifier par un spécialiste...

Code : Tout sélectionner

Code$ = GetGadgetText(...)

; Select code_app, lib_app from carto_application order by lib_app
; Select code_entite, nom_entite from carto_entite where nom_entite = "+codeApp+" order by nom_entite"

SQL$ = "SELECT                     " +
       "    A.code_app,            " +
       "    A.lib_app,             " +
       "    E.code_entite,         " +
       "    E.nom_entite           " +
       "FROM                       " +
       "    carto_application A,   " +
       "    carto_entite E         " +
       "WHERE                      " +
       "    E.nom_entite =       A." +
       Code$                         +
       "ORDER BY                   " +
       "    A.lib_app,             " +
       "    E.nom_entite           "

Debug SQL$
Note au passage, comment PB te permet de formater le code bien lisiblement (Il n'existe pas de caractère de rupture de ligne, mais on peut couper après un + ou une , (sauf dans les chaines de caractères))
CTRL+A suivi de CTRL+I reformate tout le code automatiquement.

:wink:

Re: Alimenter TreeView depuis une base de données

Publié : lun. 13/avr./2020 11:02
par pls
Effectivement, la requête est OK

Code : Tout sélectionner

reqSql = " Select app.code_app, app.lib_app, ent.code_entite, ent.nom_entite"+
         " From carto_entite ent, carto_application app"+
         " where app.code_app = ent.fk_code_app (+)"
Et me donne le bon résultat :

Code : Tout sélectionner

CODE_APP  LIB_APP	CODE_ENT	LIB_ENT
29			APP1		939			T1
299			APP1		940			T2
299			APP1		941			T3
39			APP2		1296			T1
39			APP2		1297			T2
39			APP2		1298			T3
C'est plutôt dans l'alimentation du treeview que ca coince ;)

Petit complément, j'ai récupéré le code de FALSAM (sqlLite Explorer) et après quelques adaptations, ça fonctionne.

Code : Tout sélectionner

;Affichage de la liste des Application et de leurs entités
Procedure DataBaseListTable()
  Protected ReqSql.s, Appli.s, Buffer.s , Dim Applis.s(0), n
  ;Extraction de la liste des Applications
  ReqSql="Select * From carto_application order by lib_app"
  If DatabaseQuery(#Database, ReqSQL) 
    While NextDatabaseRow(#Database)
      If Len(GetDatabaseString(#Database,0)) > 0
        Applis(n) = GetDatabaseString(#Database,1)
        n+1 : ReDim Applis(n)
      EndIf 
    Wend
    For n = 0 To ArraySize(Applis()) -1
      AddGadgetItem(#ListApplis, -1, Applis(n))
      ReqSql = " Select * From carto_entite, carto_application "+
               " where carto_entite.fk_code_app = carto_application.code_app "+
               " and carto_application.lib_app = '"+Applis(n)+"' order by nom_entite;"
      If DatabaseQuery(#Database, ReqSql)
        While NextDatabaseRow(#Database)
          AddGadgetItem(#ListApplis, -1, GetDatabaseString(#Database,2), 0, 1)
        Wend
      EndIf
    Next
  EndIf
EndProcedure