2.4Parcours d'enregistrements & tables fichier
Après avoir manipulé UN enregistrement, apprenons à traiter des ENSEMBLES d'enregistrements — c'est le quotidien d'une application de gestion. Le PARCOURS consiste à passer en revue les enregistrements d'un fichier ou d'une requête. Le WLangage propose deux approches. (1) La boucle POUR TOUT : la forme moderne et recommandée, concise et lisible — elle parcourt automatiquement tous les enregistrements et gère la fin du parcours. (2) La boucle manuelle avec HLitPremier puis HLitSuivant, en testant HEnDehors pour savoir quand s'arrêter. Elle est plus verbeuse mais indispensable à comprendre, car elle montre ce qui se passe réellement (et reste utile dans les cas particuliers). Dans les deux cas, on peut parcourir selon un ORDRE (une clé/index précise) et avec un FILTRE.
Côté interface, le champ TABLE est le compagnon naturel du parcours : il affiche plusieurs enregistrements en lignes et colonnes. Deux modes essentiels à distinguer. (1) La table FICHIER (ou « table sur fichier/requête ») : elle est LIÉE directement à une source de données et se remplit AUTOMATIQUEMENT — WinDev ne charge que les lignes nécessaires à l'affichage, ce qui la rend performante même sur de très gros volumes. C'est le mode à privilégier en gestion. (2) La table MÉMOIRE : on la remplit soi-même par code (TableAjouteLigne), ce qui donne une liberté totale mais impose de gérer le chargement — à réserver aux données construites ou de volume maîtrisé. Points de vigilance : sur de gros volumes, NE CHARGEZ PAS TOUT en mémoire (préférez la table fichier avec un filtre) ; et pour les traitements de masse, privilégiez les REQUÊTES ou les fonctions ensemblistes plutôt qu'une boucle qui traite un million d'enregistrements un par un.
Vocabulaire de la section
- Parcours
- Passer en revue les enregistrements d'un fichier ou d'une requête, éventuellement selon un ORDRE (une clé) et avec un FILTRE. Le quotidien d'une application de gestion.
- POUR TOUT
- La forme moderne et recommandée de parcours : concise, lisible, elle gère automatiquement la progression et la fin du parcours.
- Parcours manuel
- La forme classique : HLitPremier puis HLitSuivant, en testant HEnDehors pour détecter la fin. Plus verbeuse, mais indispensable à comprendre et utile dans les cas particuliers.
- Table FICHIER
- Champ table LIÉ directement à un fichier ou une requête : remplissage AUTOMATIQUE, WinDev ne charge que les lignes affichées — performant même sur de gros volumes. À privilégier.
- Table MÉMOIRE
- Champ table rempli par CODE (TableAjouteLigne) : liberté totale mais chargement à gérer soi-même. À réserver aux données construites ou de volume maîtrisé.
Quelle différence entre une table FICHIER et une table MÉMOIRE ?
En pratique — Parcourir et afficher des enregistrements
- Écrivez un parcours avec POUR TOUT (forme recommandée) pour traiter tous les enregistrements d'un fichier ou d'une requête.
- Écrivez le même parcours en version manuelle (HLitPremier / HLitSuivant + test HEnDehors) pour bien comprendre le mécanisme sous-jacent.
- Pour l'affichage, utilisez de préférence une table FICHIER liée à un fichier ou une requête : elle se remplit automatiquement et reste performante sur gros volumes.
- Réservez la table MÉMOIRE (TableAjouteLigne) aux données construites par code, et sur les gros volumes filtrez plutôt que de tout charger.
Points clés à retenir
- Deux formes de PARCOURS : la boucle POUR TOUT (moderne, concise, recommandée — elle gère automatiquement la progression et la fin) et le parcours MANUEL (HLitPremier / HLitSuivant + test HEnDehors), plus verbeux mais essentiel à comprendre. On peut parcourir selon un ORDRE (clé) et avec un FILTRE.
- Le champ TABLE affiche plusieurs enregistrements en lignes/colonnes. La table FICHIER (liée à un fichier ou une requête) se remplit AUTOMATIQUEMENT et ne charge que les lignes affichées — performante même sur de très gros volumes : c'est le mode à privilégier en gestion.
- La table MÉMOIRE se remplit par CODE (TableAjouteLigne) : liberté totale mais gestion du chargement à votre charge. À réserver aux données construites ou de volume maîtrisé.
- ⚠️ VIGILANCE PERFORMANCE : ne chargez PAS tout en mémoire sur de gros volumes (préférez une table fichier avec filtre) ; et pour les traitements de masse, privilégiez les REQUÊTES ou opérations ensemblistes plutôt qu'une boucle traitant un million d'enregistrements un par un.
Questions fréquentes
Quelle différence entre une table fichier et une table mémoire, et laquelle choisir ?
La table FICHIER est LIÉE à une source de données et se remplit automatiquement en ne chargeant que les lignes affichées (performante sur gros volumes) ; la table MÉMOIRE est remplie par votre code (liberté totale, mais tout est chargé). En gestion, privilégiez la table FICHIER dès que les données viennent de la base. La table FICHIER : (1) Principe : on lie le champ table à un fichier de l'analyse ou à une REQUÊTE. WinDev se charge du remplissage. (2) Performance : c'est l'argument décisif — WinDev ne lit QUE les enregistrements nécessaires à l'affichage courant, et charge la suite au fur et à mesure du défilement. Une table sur un million d'enregistrements s'affiche donc instantanément. (3) Simplicité : très peu de code, tout est déclaratif. (4) Fonctions intégrées : tri par clic sur les en-têtes, recherche, filtres, positionnement — largement automatiques. (5) Cohérence : les données affichées correspondent à la base. (6) Limite : moins de liberté quand l'affichage doit être très éloigné de la structure des données. La table MÉMOIRE : (1) Principe : la table est vide au départ ; votre code y ajoute des lignes (TableAjouteLigne) avec les valeurs de votre choix. (2) Liberté totale : vous affichez ce que vous voulez, d'où vous voulez — données calculées, agrégées, provenant de plusieurs sources, résultats de traitements, données externes (fichier importé, service web). (3) Inconvénient majeur : TOUT est chargé en mémoire. Sur un gros volume, cela consomme de la mémoire et le remplissage prend du temps — l'utilisateur attend. (4) Vous devez gérer vous-même le remplissage, la mise à jour, le tri éventuel. (5) Utile aussi pour des listes courtes construites par code (paramètres, choix, synthèses). Comment choisir : (1) Données venant directement de la base, volume potentiellement important → table FICHIER. C'est le cas le plus fréquent en gestion (liste de clients, de commandes, d'articles) et le bon réflexe par défaut. (2) Besoin de filtrer ou de trier → table fichier sur une REQUÊTE (paramétrée si besoin) : vous gardez la performance tout en maîtrisant le contenu. (3) Données CALCULÉES, agrégées, ou issues de sources multiples/externes → table MÉMOIRE, en veillant à limiter le volume. (4) Petites listes construites par code → table mémoire, sans souci. (5) Cas hybride : préparez les données dans une REQUÊTE (jointures, calculs, filtres, agrégats) et affichez-la en table fichier — vous combinez souplesse et performance. C'est souvent la meilleure solution. Les pièges à éviter : (1) Remplir une table mémoire en parcourant un gros fichier : c'est l'erreur classique, qui donne une application qui « rame » et se fige au chargement. Si les données viennent de la base, utilisez une table fichier. (2) Tester uniquement sur un petit jeu de données : le problème n'apparaît qu'en production. (3) Afficher des dizaines de milliers de lignes sans filtre : aucun utilisateur ne les parcourt — proposez plutôt une recherche. En résumé : la table FICHIER est liée à un fichier ou une REQUÊTE et se remplit automatiquement, en ne chargeant QUE les lignes nécessaires à l'affichage — elle reste donc instantanée même sur des volumes très importants, demande peu de code et offre nativement tri, recherche et positionnement. La table MÉMOIRE est remplie par votre code (TableAjouteLigne) : elle autorise n'importe quel contenu (données calculées, agrégées, multi-sources, externes) mais charge TOUT en mémoire, ce qui la rend inadaptée aux gros volumes. Le choix est donc simple : dès que les données proviennent de la base, utilisez une table FICHIER — c'est le réflexe par défaut en gestion — en la basant sur une REQUÊTE (éventuellement paramétrée) lorsque vous devez filtrer, joindre ou calculer, ce qui combine maîtrise du contenu et performance. Réservez la table mémoire aux données construites par code ou aux listes courtes. Le piège classique à éviter absolument : remplir une table mémoire en parcourant un gros fichier — l'application se fige au chargement, et le défaut ne se voit qu'en production, jamais sur le petit jeu de test du développeur.
Comment traiter efficacement un grand nombre d'enregistrements ?
En faisant faire le maximum de travail par la BASE (requêtes, filtres, opérations ensemblistes) plutôt que par une boucle WLangage qui traite les enregistrements un par un, en limitant les données chargées, et en soignant les index — la différence de performance peut être considérable. Les principes fondamentaux : (1) FILTREZ à la source. Ne parcourez jamais tout un fichier pour ne garder que quelques enregistrements : posez la condition dans la requête ou le filtre HFSQL. Le moteur utilisera ses INDEX. (2) Ne lisez que les RUBRIQUES utiles, surtout si les enregistrements contiennent des mémos ou des images volumineuses. (3) Déléguez les CALCULS d'ensemble (somme, moyenne, comptage) à la base via GROUP BY : demander un total au moteur est infiniment plus rapide que d'additionner ligne par ligne en WLangage. (4) Utilisez les opérations ENSEMBLISTES quand c'est possible : une requête de mise à jour agissant sur un ensemble d'enregistrements bat très largement une boucle qui les modifie un par un. (5) Vérifiez les INDEX sur les rubriques de filtre, de tri et de jointure : c'est la première cause de lenteur. Pour l'interface : (1) Table FICHIER plutôt que table mémoire (chargement à la demande). (2) Ne montrez pas des dizaines de milliers de lignes : proposez une RECHERCHE ou des filtres pour que l'utilisateur cible ce qu'il veut. Personne ne fait défiler cinquante mille lignes. (3) Évitez les traitements lourds dans les événements déclenchés à chaque ligne affichée. Pour les traitements par LOT (imports, recalculs) : (1) TRANSACTIONS : regrouper les écritures dans une transaction accélère souvent le traitement ET garantit la cohérence (tout ou rien). (2) Désactivez temporairement ce qui n'est pas nécessaire pendant un import massif (rafraîchissements d'écran, traitements accessoires) — mais avec prudence et en connaissance de cause. (3) Informez l'utilisateur : barre de progression, message. Un traitement long sans retour visuel donne l'impression que l'application est plantée. (4) Traitez par LOTS plutôt que tout d'un bloc si le volume est énorme. (5) Prévoyez la REPRISE en cas d'interruption sur les très gros traitements. La méthode de travail : (1) MESUREZ avant d'optimiser : identifiez ce qui est réellement lent (le débogueur et les traces aident) plutôt que d'optimiser au hasard. (2) TESTEZ avec des volumes RÉALISTES — c'est le point le plus important. Un traitement instantané sur mille enregistrements peut être inutilisable sur un million. Les problèmes de performance ne se découvrent pas sur un jeu de test miniature. (3) Optimisez d'abord ce qui a le plus d'impact (souvent : un filtre manquant ou un index absent). (4) Restez LISIBLE : n'optimisez pas au prix d'un code incompréhensible si le gain est marginal. En résumé : traitez efficacement de gros volumes en confiant le maximum de travail au MOTEUR de base de données plutôt qu'à une boucle WLangage — filtrez à la source (le moteur exploite ses index), ne lisez que les rubriques utiles, déléguez les calculs d'ensemble via GROUP BY et privilégiez les opérations ENSEMBLISTES (une requête de mise à jour globale bat toujours une boucle qui modifie les enregistrements un par un). Vérifiez systématiquement les INDEX sur les rubriques filtrées, triées et jointes : leur absence est la première cause de lenteur. Côté interface, utilisez une table FICHIER (chargement à la demande) et ne cherchez pas à afficher des dizaines de milliers de lignes : offrez plutôt une recherche. Pour les traitements par lot, exploitez les TRANSACTIONS (rapidité et cohérence tout-ou-rien), traitez par lots si le volume est énorme et affichez impérativement une PROGRESSION, faute de quoi l'utilisateur croira à un plantage. Enfin, la règle de méthode : MESUREZ avant d'optimiser, et surtout TESTEZ AVEC DES VOLUMES RÉALISTES — un traitement instantané sur mille enregistrements peut être inutilisable sur un million, et ce type de défaut ne se découvre jamais sur un petit jeu de test.