OVH Cloud OVH Cloud

Comment optimiser le code ci après ?

4 réponses
Avatar
TEV
Bonjour,

Je cherche à gagner du temps sur l'affichage de données provenant d'une base
Access dans un ListView. A l'heure actuelle cela prend beaucoup de temps en
moyenne 5 minutes, pour 15 000 enregistrements (eh oui, je suis dégoûté).

Les données à afficher peuvent être beaucoup plus volumineuses jusqu'à 50
000 fiches voir +.

Il y a une table principale et une table contenant les n° de téléphones (>1
et <4 un par fiche).
-Je sélectionne via une requête les fiches à afficher.
- J'ouvre la boucle jusqu'à EOF
-Je parcourre la requête pour prendre les infos nécessaire et retenir l'ID
de l'enregistrement.
-J'ouvre une seconde requête pour récupérer le / les n° de téléphones de
l'enregistrement grâce à l'ID retenu.
- Je boucle sur les enregistrements de n° téléphone trouvés, pour les
concaténer et les afficher dans un champ unique.
- J'affiche le résultat dans la ListView
-Je ferme la requête téléphone
- Je boucle

Voici le code:

' Définition de la requête de recherche
RqRecVF = "SELECT id, nomfiche,prenom,mailmarche " & _
"FROM renseignement WHERE date()-dtmodification >365 AND listenoire =
false;"
' Créé le recordset
Set RcVF = New adodb.Recordset
RcVF.CursorLocation = adUseClient
' Exécution de la requête
OpenDataBase
RcVF.Open RqRecVF, AdoConnexion, adOpenDynamic, adLockOptimistic,
adCmdText

' Inscription des données dans la liste view
I = 1
Do Until .EOF
DoEvents
idTel = .Fields(0)
' Création de la RQ de récupération des N° de telephone
Rqphone = "SELECT tel FROM telephone WHERE idrenstel = " & idTel
Set itListv = ListV.ListItems.Add(I, , .Fields(0))
itListv.SubItems(ListV.ColumnHeaders("Nom").SubItemIndex) =
.Fields(1)
itListv.SubItems(ListV.ColumnHeaders("Prenom").SubItemIndex) =
.Fields(2)
itListv.SubItems(ListV.ColumnHeaders("Mail").SubItemIndex) =
.Fields(3)
'Création du recordset de recherche du telephone
Set RcTel = New adodb.Recordset
RcTel.CursorLocation = adUseClient
' Exécution de la requête téléphone
RcTel.Open Rqphone, AdoConnexion, adOpenDynamic, adLockOptimistic,
adCmdText
For J = 1 To RcTel.RecordCount
DoEvents
numTel = RcTel.Fields(0)
If (RcTel.RecordCount) > 1 Then numTel = numTel & "-" & numTel
Next J
itListv.SubItems(ListV.ColumnHeaders("Téléphone").SubItemIndex) =
numTel
.MoveNext
I = I + 1
RcTel.Close
Set RcTel = Nothing
Loop

Christian.

4 réponses

Avatar
François Picalausa
Hello,

A l'heure actuelle cela prend
beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
(eh oui, je suis dégoûté).



15 000 enregistrements dans une liste c'est surtout pour dégouter
l'utilisateur, non?
Ne peux-tu pas proposer un tri par ordre alphabétique ou autre via des
tabstrip? Parce qu'un utilisateur ne s'y retrouvera pas dans une liste de
15000 items...
Sans compte la place en mémoire prise par les éléments de la lvw (Text, Tag,
Key, autre...)

Sinon, tu peux masquer le listview pendant l'ajout (visible = false) celà
accélère déjà pas mal l'ajout des items, mais regarde surtout à "splitter"
la liste si possible!

--
François Picalausa (MVP VB)
http://faq.vb.free.fr --- http://msdn.microsoft.com
http://apisvb.europe.webmatrixhosting.net

"TEV" a écrit dans le message de
news:40e14e81$0$24425$
Bonjour,

Je cherche à gagner du temps sur l'affichage de données provenant
d'une base Access dans un ListView. A l'heure actuelle cela prend
beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
(eh oui, je suis dégoûté).

Les données à afficher peuvent être beaucoup plus volumineuses
jusqu'à 50 000 fiches voir +.

Il y a une table principale et une table contenant les n° de
téléphones (>1 et <4 un par fiche).
-Je sélectionne via une requête les fiches à afficher.
- J'ouvre la boucle jusqu'à EOF
-Je parcourre la requête pour prendre les infos nécessaire et retenir
l'ID de l'enregistrement.
-J'ouvre une seconde requête pour récupérer le / les n° de téléphones
de l'enregistrement grâce à l'ID retenu.
- Je boucle sur les enregistrements de n° téléphone trouvés, pour les
concaténer et les afficher dans un champ unique.
- J'affiche le résultat dans la ListView
-Je ferme la requête téléphone
- Je boucle

Voici le code:

' Définition de la requête de recherche
RqRecVF = "SELECT id, nomfiche,prenom,mailmarche " & _
"FROM renseignement WHERE date()-dtmodification >365 AND
listenoire = false;"
' Créé le recordset
Set RcVF = New adodb.Recordset
RcVF.CursorLocation = adUseClient
' Exécution de la requête
OpenDataBase
RcVF.Open RqRecVF, AdoConnexion, adOpenDynamic, adLockOptimistic,
adCmdText

' Inscription des données dans la liste view
I = 1
Do Until .EOF
DoEvents
idTel = .Fields(0)
' Création de la RQ de récupération des N° de telephone
Rqphone = "SELECT tel FROM telephone WHERE idrenstel = " &
idTel Set itListv = ListV.ListItems.Add(I, , .Fields(0))
itListv.SubItems(ListV.ColumnHeaders("Nom").SubItemIndex) > .Fields(1)
itListv.SubItems(ListV.ColumnHeaders("Prenom").SubItemIndex) > .Fields(2)
itListv.SubItems(ListV.ColumnHeaders("Mail").SubItemIndex) > .Fields(3)
'Création du recordset de recherche du telephone
Set RcTel = New adodb.Recordset
RcTel.CursorLocation = adUseClient
' Exécution de la requête téléphone
RcTel.Open Rqphone, AdoConnexion, adOpenDynamic,
adLockOptimistic, adCmdText
For J = 1 To RcTel.RecordCount
DoEvents
numTel = RcTel.Fields(0)
If (RcTel.RecordCount) > 1 Then numTel = numTel & "-" &
numTel Next J

itListv.SubItems(ListV.ColumnHeaders("Téléphone").SubItemIndex) > numTel .MoveNext
I = I + 1
RcTel.Close
Set RcTel = Nothing
Loop

Christian.


Avatar
TEV
Merci beaucoup pour la réponse.
Effectivement 15000 items, voir plus, est effroyable mais c'est ce que l'on
m'a demandé et même en l'état actuelle des choses cela convient. Donc je
cherches plus à gagner du temps d'affichage... D'autant que j'ai déjà essayé
de réduire le nombre d'enregistrement en ajoutant d'autres critères. Mais
aucun n'ont convenus.

Sinon, je vais essayer en rendant invisible le listView et j'ai trouvé une
autre façon de coder. Pour le moment seulement en algorithmie. On verra...

Christian.



"François Picalausa" a écrit dans le message de news:

Hello,

> A l'heure actuelle cela prend
> beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
> (eh oui, je suis dégoûté).

15 000 enregistrements dans une liste c'est surtout pour dégouter
l'utilisateur, non?
Ne peux-tu pas proposer un tri par ordre alphabétique ou autre via des
tabstrip? Parce qu'un utilisateur ne s'y retrouvera pas dans une liste de
15000 items...
Sans compte la place en mémoire prise par les éléments de la lvw (Text,


Tag,
Key, autre...)

Sinon, tu peux masquer le listview pendant l'ajout (visible = false) celà
accélère déjà pas mal l'ajout des items, mais regarde surtout à "splitter"
la liste si possible!

--
François Picalausa (MVP VB)
http://faq.vb.free.fr --- http://msdn.microsoft.com
http://apisvb.europe.webmatrixhosting.net

"TEV" a écrit dans le message de
news:40e14e81$0$24425$
> Bonjour,
>
> Je cherche à gagner du temps sur l'affichage de données provenant
> d'une base Access dans un ListView. A l'heure actuelle cela prend
> beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
> (eh oui, je suis dégoûté).
>
> Les données à afficher peuvent être beaucoup plus volumineuses
> jusqu'à 50 000 fiches voir +.
>
> Il y a une table principale et une table contenant les n° de
> téléphones (>1 et <4 un par fiche).
> -Je sélectionne via une requête les fiches à afficher.
> - J'ouvre la boucle jusqu'à EOF
> -Je parcourre la requête pour prendre les infos nécessaire et retenir
> l'ID de l'enregistrement.
> -J'ouvre une seconde requête pour récupérer le / les n° de téléphones
> de l'enregistrement grâce à l'ID retenu.
> - Je boucle sur les enregistrements de n° téléphone trouvés, pour les
> concaténer et les afficher dans un champ unique.
> - J'affiche le résultat dans la ListView
> -Je ferme la requête téléphone
> - Je boucle
>
> Voici le code:
>
> ' Définition de la requête de recherche
> RqRecVF = "SELECT id, nomfiche,prenom,mailmarche " & _
> "FROM renseignement WHERE date()-dtmodification >365 AND
> listenoire = false;"
> ' Créé le recordset
> Set RcVF = New adodb.Recordset
> RcVF.CursorLocation = adUseClient
> ' Exécution de la requête
> OpenDataBase
> RcVF.Open RqRecVF, AdoConnexion, adOpenDynamic, adLockOptimistic,
> adCmdText
>
> ' Inscription des données dans la liste view
> I = 1
> Do Until .EOF
> DoEvents
> idTel = .Fields(0)
> ' Création de la RQ de récupération des N° de telephone
> Rqphone = "SELECT tel FROM telephone WHERE idrenstel = " &
> idTel Set itListv = ListV.ListItems.Add(I, , .Fields(0))
> itListv.SubItems(ListV.ColumnHeaders("Nom").SubItemIndex) > > .Fields(1)
> itListv.SubItems(ListV.ColumnHeaders("Prenom").SubItemIndex) > > .Fields(2)
> itListv.SubItems(ListV.ColumnHeaders("Mail").SubItemIndex) > > .Fields(3)
> 'Création du recordset de recherche du telephone
> Set RcTel = New adodb.Recordset
> RcTel.CursorLocation = adUseClient
> ' Exécution de la requête téléphone
> RcTel.Open Rqphone, AdoConnexion, adOpenDynamic,
> adLockOptimistic, adCmdText
> For J = 1 To RcTel.RecordCount
> DoEvents
> numTel = RcTel.Fields(0)
> If (RcTel.RecordCount) > 1 Then numTel = numTel & "-" &
> numTel Next J
>
> itListv.SubItems(ListV.ColumnHeaders("Téléphone").SubItemIndex) > > numTel .MoveNext
> I = I + 1
> RcTel.Close
> Set RcTel = Nothing
> Loop
>
> Christian.




Avatar
Driss HANIB
bonjour

peut être ne charger qu'une fois tout dans un tableau puis n'afficher que
sur critères les enregistrements concernés.


"TEV" a écrit dans le message de
news:40e1d6cc$0$19682$
Merci beaucoup pour la réponse.
Effectivement 15000 items, voir plus, est effroyable mais c'est ce que


l'on
m'a demandé et même en l'état actuelle des choses cela convient. Donc je
cherches plus à gagner du temps d'affichage... D'autant que j'ai déjà


essayé
de réduire le nombre d'enregistrement en ajoutant d'autres critères. Mais
aucun n'ont convenus.

Sinon, je vais essayer en rendant invisible le listView et j'ai trouvé une
autre façon de coder. Pour le moment seulement en algorithmie. On verra...

Christian.



"François Picalausa" a écrit dans le message de


news:

> Hello,
>
> > A l'heure actuelle cela prend
> > beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
> > (eh oui, je suis dégoûté).
>
> 15 000 enregistrements dans une liste c'est surtout pour dégouter
> l'utilisateur, non?
> Ne peux-tu pas proposer un tri par ordre alphabétique ou autre via des
> tabstrip? Parce qu'un utilisateur ne s'y retrouvera pas dans une liste


de
> 15000 items...
> Sans compte la place en mémoire prise par les éléments de la lvw (Text,
Tag,
> Key, autre...)
>
> Sinon, tu peux masquer le listview pendant l'ajout (visible = false)


celà
> accélère déjà pas mal l'ajout des items, mais regarde surtout à


"splitter"
> la liste si possible!
>
> --
> François Picalausa (MVP VB)
> http://faq.vb.free.fr --- http://msdn.microsoft.com
> http://apisvb.europe.webmatrixhosting.net
>
> "TEV" a écrit dans le message de
> news:40e14e81$0$24425$
> > Bonjour,
> >
> > Je cherche à gagner du temps sur l'affichage de données provenant
> > d'une base Access dans un ListView. A l'heure actuelle cela prend
> > beaucoup de temps en moyenne 5 minutes, pour 15 000 enregistrements
> > (eh oui, je suis dégoûté).
> >
> > Les données à afficher peuvent être beaucoup plus volumineuses
> > jusqu'à 50 000 fiches voir +.
> >
> > Il y a une table principale et une table contenant les n° de
> > téléphones (>1 et <4 un par fiche).
> > -Je sélectionne via une requête les fiches à afficher.
> > - J'ouvre la boucle jusqu'à EOF
> > -Je parcourre la requête pour prendre les infos nécessaire et retenir
> > l'ID de l'enregistrement.
> > -J'ouvre une seconde requête pour récupérer le / les n° de téléphones
> > de l'enregistrement grâce à l'ID retenu.
> > - Je boucle sur les enregistrements de n° téléphone trouvés, pour les
> > concaténer et les afficher dans un champ unique.
> > - J'affiche le résultat dans la ListView
> > -Je ferme la requête téléphone
> > - Je boucle
> >
> > Voici le code:
> >
> > ' Définition de la requête de recherche
> > RqRecVF = "SELECT id, nomfiche,prenom,mailmarche " & _
> > "FROM renseignement WHERE date()-dtmodification >365 AND
> > listenoire = false;"
> > ' Créé le recordset
> > Set RcVF = New adodb.Recordset
> > RcVF.CursorLocation = adUseClient
> > ' Exécution de la requête
> > OpenDataBase
> > RcVF.Open RqRecVF, AdoConnexion, adOpenDynamic, adLockOptimistic,
> > adCmdText
> >
> > ' Inscription des données dans la liste view
> > I = 1
> > Do Until .EOF
> > DoEvents
> > idTel = .Fields(0)
> > ' Création de la RQ de récupération des N° de telephone
> > Rqphone = "SELECT tel FROM telephone WHERE idrenstel = " &
> > idTel Set itListv = ListV.ListItems.Add(I, , .Fields(0))
> > itListv.SubItems(ListV.ColumnHeaders("Nom").SubItemIndex) > > > .Fields(1)
> > itListv.SubItems(ListV.ColumnHeaders("Prenom").SubItemIndex) > > > .Fields(2)
> > itListv.SubItems(ListV.ColumnHeaders("Mail").SubItemIndex) > > > .Fields(3)
> > 'Création du recordset de recherche du telephone
> > Set RcTel = New adodb.Recordset
> > RcTel.CursorLocation = adUseClient
> > ' Exécution de la requête téléphone
> > RcTel.Open Rqphone, AdoConnexion, adOpenDynamic,
> > adLockOptimistic, adCmdText
> > For J = 1 To RcTel.RecordCount
> > DoEvents
> > numTel = RcTel.Fields(0)
> > If (RcTel.RecordCount) > 1 Then numTel = numTel & "-" &
> > numTel Next J
> >
> > itListv.SubItems(ListV.ColumnHeaders("Téléphone").SubItemIndex) > > > numTel .MoveNext
> > I = I + 1
> > RcTel.Close
> > Set RcTel = Nothing
> > Loop
> >
> > Christian.
>
>




Avatar
Pierre Moureaux
Salut,

Pourquoi placer 15000 lignes dans un Listview alors que l'on ne peut en voir
que quelques 10 aines en même temps !?

Il faut modifier le listview à la demande, utiliser un Virtual Listview !

Je te conseille d'étudier l'exemple à l'adresse suivante :

http://www.mvps.org/vbvision/grouped_demos.htm (virtual listview
demo.zip)

C'est assez compliqué car fait appel au subclassing mais je l'ai utilisé
pour une application analogue à la tienne et ça donne de très bons résultats
! Epatant n'est-ce pas, 1 000 000 de lignes dans un listview !

Bon courage ....

Pierre.

Une piste plus simple mais que j'ai déjà vu suggérée : un listview d'un
nombre de ligne fixé, par exemple 30 plus un contrôle Vscroll de 15000
"unités de hauteur" et dont le déplacement se charge de charger les éléments
à partir de la base de donnée et de la mise à jour de l'affichage du
listview. Tu pourrais aussi prévoir une mémoire tampon qui te permettrait d'
éviter d'accéder chaque fois à la base de donnée pour chaque déplacement de
1 unité.

Un conseil : travailler avec des "pages", le contrôle ADO le permet.




"TEV" a écrit dans le message de
news:40e14e81$0$24425$
Bonjour,

Je cherche à gagner du temps sur l'affichage de données provenant d'une


base
Access dans un ListView. A l'heure actuelle cela prend beaucoup de temps


en
moyenne 5 minutes, pour 15 000 enregistrements (eh oui, je suis dégoûté).

Les données à afficher peuvent être beaucoup plus volumineuses jusqu'à 50
000 fiches voir +.

Il y a une table principale et une table contenant les n° de téléphones


(>1
et <4 un par fiche).
-Je sélectionne via une requête les fiches à afficher.
- J'ouvre la boucle jusqu'à EOF
-Je parcourre la requête pour prendre les infos nécessaire et retenir l'ID
de l'enregistrement.
-J'ouvre une seconde requête pour récupérer le / les n° de téléphones de
l'enregistrement grâce à l'ID retenu.
- Je boucle sur les enregistrements de n° téléphone trouvés, pour les
concaténer et les afficher dans un champ unique.
- J'affiche le résultat dans la ListView
-Je ferme la requête téléphone
- Je boucle

Voici le code:

' Définition de la requête de recherche
RqRecVF = "SELECT id, nomfiche,prenom,mailmarche " & _
"FROM renseignement WHERE date()-dtmodification >365 AND listenoire > false;"
' Créé le recordset
Set RcVF = New adodb.Recordset
RcVF.CursorLocation = adUseClient
' Exécution de la requête
OpenDataBase
RcVF.Open RqRecVF, AdoConnexion, adOpenDynamic, adLockOptimistic,
adCmdText

' Inscription des données dans la liste view
I = 1
Do Until .EOF
DoEvents
idTel = .Fields(0)
' Création de la RQ de récupération des N° de telephone
Rqphone = "SELECT tel FROM telephone WHERE idrenstel = " & idTel
Set itListv = ListV.ListItems.Add(I, , .Fields(0))
itListv.SubItems(ListV.ColumnHeaders("Nom").SubItemIndex) > .Fields(1)
itListv.SubItems(ListV.ColumnHeaders("Prenom").SubItemIndex) > .Fields(2)
itListv.SubItems(ListV.ColumnHeaders("Mail").SubItemIndex) > .Fields(3)
'Création du recordset de recherche du telephone
Set RcTel = New adodb.Recordset
RcTel.CursorLocation = adUseClient
' Exécution de la requête téléphone
RcTel.Open Rqphone, AdoConnexion, adOpenDynamic, adLockOptimistic,
adCmdText
For J = 1 To RcTel.RecordCount
DoEvents
numTel = RcTel.Fields(0)
If (RcTel.RecordCount) > 1 Then numTel = numTel & "-" & numTel
Next J
itListv.SubItems(ListV.ColumnHeaders("Téléphone").SubItemIndex) > numTel
.MoveNext
I = I + 1
RcTel.Close
Set RcTel = Nothing
Loop

Christian.