Répondre à: Comparaison de deux tables via champ lookup

  • R3dKap

    Membre
    9 mars 2022 à 9h30

    @Laurent CARRIERE et @Ludovic je vais essayer de vous amener à comprendre pourquoi vous n’y arrivez pas afin de vous donner l’autonomie de le faire par vous-même par la suite…

    En fait, il y a confusion dans les données que vous manipulez. Mais avant toute chose, il faudrait idéalement améliorer la nomenclature des objets et des variables parce-que là, même moi je m’y perds…
    Ce que je recommande c’est d’utiliser en tout temps la nomenclature suivante (j’aimerais tellement que TOUS les développeurs Power Apps du monde entier suivent la même nomenclature… ce serait tellement plus simple pour se parler et lire le code des p’tits copains… 😀) :

    • collection locale : colNomDeLaCollection (à définir avec les fonctions ClearCollect(), Collect(), Filter(), …)

    • variable globale : gloNomDeLaVariableGlobale (à définir avec la fonction Set())

    • variable locale : locNomDeLaVariableLocale (à définir avec la fonction UpdateContext())

    • colonne d’une liste SharePoint (nom interne) : scNomDeLaColonne (colonne à créer en 2 temps comme expliqué ici au paragraphe Création des colonnes)

    Vous noterez au passage le jeu de majusucules/minuscules A RESPECTER pour plus de lisibilité… 😉

    Pour en revenir à la formule qui ne fonctionne pas…

    Si j’ai bien compris la manière dont sont organisées les données :

    • une liste RESERVOIR avec une colonne IDRESERVOIR de type texte (en gros c’est le catalogue des réservoirs)

    • une liste NETTOYAGE avec une colonne IDRESERVOIR de type recherche qui pointe vers la liste RESERVOIR (sur le champ IDRESERVOIR je suppose)

    Là encore, déjà, aussi un petit souci de nomenclature :

    • la liste contenant TOUS les réservoirs devrait s’appeler RESERVOIRS au pluriel (c’est tout bête mais ça représente mieux la réalité et dans le code par la suite le fait de voir le pluriel me fait potentiellement comprendre plus facilement que c’est une liste) ; à la rigueur CatalogueReservoirs aurait même mieux… bref…

    • idem pour le nom de la liste NETTOYAGE qui serait mieux lotie avec un ‘S’

    • dans la liste NETTOYAGE, la colonne IDRESERVOIR est mal nommé car on ne nettoie pas un IDRESERVOIR mais un RESERVOIR -> donc autant l’appeler RESERVOIR tout simplement : en gros, le modèle de données, dans sa nomenclature, doit refléter la réalité (je nettoie quoi ? un réservoir -> j’appelle ma colonne RESERVOIR)

    Et là on en arrive au plus important : la structure de cette colonne de recherche IDRESERVOIR de la liste NETTOYAGE. Comme vous le savez sa structure est la suivante :

    {n    Id: ...;n    Value: ...n}

    La première colonne Id va contenir la valeur de la colonne ID (remarquez ici les majuscules) de l’élément dans la liste liée RESERVOIR. Et la colonne Value va contenir la valeur de la colonne liée (ici IDRESERVOIR) de l’élément dans la liste RESERVOIR.

    Voilà… Il faut bien avoir ça en tête au moment où on manipule les données.

    Maintenant, supposons que l’on veuille mettre en place le filtrage proposé par @Ludovic. Pour rappel, l’idée c’est de filtrer la liste RESERVOIR pour ne conserver que les réservoirs qui ne sont jamais utilisés dans la liste NETTOYAGE (colonne de recherche IDRESERVOIR).

    Donc, pour faire ça, on va donc écrire quelque chose qui ressemble à ça :

    Filter(RESERVOIR; <condition de filtrage>)

    La condition de filtrage va consister à regarder, pour le RESERVOIR en cours (en effet, n’oubliez pas que la fonction Filter() fonctionne comme une boucle où chaque élément de la collection en premier paramètre va être confronté à la condition spécifiée dans le 2è paramètre), s’il existe des lignes dans NETTOYAGE dont la colonne IDRESERVOIR pointe sur ce réservoir. S’il n’en existe aucune alors on “conserve” le réservoir en question et on sait qu’il n’a pas été nettoyé. On va utiliser la fonction CountIf() pour vérifier l’existence de ces lignes.

    La formule se complète donc ainsi :

    Filter(n    RESERVOIR; n    CountIf(NETTOYAGE; <condition de comptage>)=0n)

    Que veux-t-on faire dans la condition de comptage ? On veut rechercher des éléments de NETTOYAGE IDRESERVOIR pointe sur le réservoir en cours du Filter() (de la boucle). Or souvenez-vous, IDRESERVOIR dans NETTOYAGE c’est {Id: <ID dans RESERVOIR>; Value: <IDRESERVOIR dans RESERVOIR>}.

    Donc, ma condition va être la suivante :

    IDRESERVOIR.Id = ID (celui de RESERVOIR)

    Mais y’a un souci : il existe aussi une colonne ID dans NETTOYAGE. Comment Power Apps va savoir si ID c’est celui de RESERVOIR ou de NETTOYAGE dans notre formule ? Il y a ambiguïté… Pour résoudre ce problème, on a 2 solutions :

    • soit on utilise l’opérateur de désambiguïté : IDRESERVOIR.Id = RESERVOIR[@ID] (on précise que la colonne ID est celle de la liste RESERVOIR)

    • soit on nomme temporairement la liste RESERVOIR dans la fonction Filter() pour pouvoir y faire référence ailleurs dans la formule : Filter(RESERVOIR As ItemReservoir; ...) et la condition du CountIf() serait alors IDRESERVOIR.Id = ItemReservoir.ID

    Je préfère la 2è solution. Et notre formule finale est donc la suivante :

    Filter(n    RESERVOIR As ItemReservoir; n    CountIf(NETTOYAGE; IDRESERVOIR.Id = ItemReservoir.ID)=0n)

    Au passage, lorsque je tape mon code je procède par étapes : j’écris les fonctions en partant du niveau le plus haut et je rentre en profondeur au fur et à mesure. Ca m’évite des erreurs de parenthèses et des oublis de paramètres. Et donc, j’écris les choses ainsi :

    Filter(RESERVOIR As ItemReservoir; )

    Puis :

    Filter(RESERVOIR As ItemReservoir; CountIf()=0)

    Puis :

    Filter(RESERVOIR As ItemReservoir; CountIf(NETTOYAGE; IDRESERVOIR.Id = ItemReservoir.ID)=0)

    Voilou… En espérant que vous avez bien suivi la logique et vous saurez l’appliquer à d’autres cas de figure… 😉

    CommentID=sU0c4GHCY5Bgb5X, PostID=8LH1lVbKjN748zo