R3dKap
Expert Power AppsRéponses céées sur le Forum
-
Ah ouais, c’est pas juste une p’tite appli pour une p’tite boîte… 😅
Vous voulez pas que je vous accompagne sur le projet ? Je suis dispo en ce moment… 😁 On pourrait le faire en mode “mentoring” : c’est toi qui fait l’application avec moi en background qui te fait monter en compétence… 😋
-
Quand tu vas sur make.powerapps.com qu’est ce que tu as dans la partie Console de l’outil de développement de Chrome (les 3 petits points en haut à droite du navigateur > Plus d’outils > Outils de développement > Onglet Console) ?
Ouvre d’abord la console avant d’aller sur l’url et mets-nous une capture ici… 😉
-
Bon oublions toutes les manips hormis celle d’accéder directement à make.powerapps.com : quand tu tapes ça dans ton navigateur tu devrais arriver sur la page d’accueil de Power Apps, tout simplement.
Si ça marche sur Edge et pas sur Chrome, alors peut-être qu’une de tes (nombreuses) extensions sur Chrome empêche le bon fonctionnement de cette page : essaie peut-être de toutes les désactiver et de retenter le coup…
Essaie aussi make.preview.powerapps.com.
-
C’est ouf comme on a tous le réflexe de vouloir décrire un problème en y intégrant directement la solution… (moi le premier) 😅
- Sans me parler de Power Apps, de listes, de QR code, de scanner, etc. raconte-moi une histoire : parle-moi de ces pièces de rechanges, comment elles arrivent là, comment elles sont stockées, comment elles sont réutilisées, qu’est-ce que ça veut dire un mouvement, où va la pièce, quels sont les différents acteurs qui manipulent les pièces, le magasinier, le manipulateur du transpalette, le client qui veut acheter la pièce, etc. -> ça c’est la description de l’existant (dans la vie réelle).
- Ensuite, explique-moi ce que tu veux faire : je veux une application qui permette de tracer et d’historiser les entrées et les sorties des pièces afin de…, qui va utiliser l’application, comment tu voudrais idéalement que ce traçage se fasse (là tu peux parler de scanner et de qr code), qui a le droit de faire quoi dans l’application (pour identifier les rôles), il faut qu’un administrateur puisse faire ça et ci et ça, etc. -> ça c’est la description du besoin
Une fois que ça c’est bien clair alors tu peux commencer à réfléchir à l’architecture de ta solution dans l’ordre suivant :
- Conception du modèle de données (imaginer les listes, les colonnes, les relations, etc.) pour que ça réponde à ton besoin
- Schématiser le parcours de l’utilisateur dans l’application en précisant ce qu’il est possible de faire :
- Il fait un choix entre la consultation de l’historique des mouvements, la création d’un mouvement ou la gestion des pièces
- S’il choisit l’historique d’un mouvement, il peut modifier un mouvement ou en créer un nouveau et revenir ensuite au départ
- S’il choisit la création d’un mouvement (à partir du départ ou à partir de l’historique) il arrive sur l’écran de création de mouvement
- S’il choisit la gestion des pièces, il arrive sur un écran dédié où il peut : éditer les pièces existantes, ajouter de nouvelles pièces
- Faire des maquettes de tes écrans (maquettes grossières tout d’abord)
- Présenter ta solution aux utilisateurs finaux pour avoir leur sentiment (hyper important de faire ça AVANT de créer ton application passke sinon tu va être confronté au problème de “l’effet tunnel” : tu fais tout dans ton coin et puis tu le files aux utilisateurs qui finissent par te dire que ton machin est pas pratique du tout et qu’ils rechignent à l’utiliser)
- Réajuster ta solution en fonction des retours des utilisateurs
- Dessiner tes écrans au propre (couleurs, positions, dimensions, etc.)
- ET LA TU PEUX COMMENCER A CODER 😅
Ca c’est l’idéal. Après, souvent on saute un peu des étapes pour aller plus vite (à ses risques et périls) mais globalement faut quand même respecter cette logique. Et surtout que procéder méthodiquement comme ça va au final te faire gagner du temps par rapport à : je me lance direct dans le codage et je réfléchis après -> ça ne marche que pour ceux qui ont déjà 20 ans d’expérience dans la création d’applications 😉.
Et autre point très important aussi : le choix des mots -> appelle un chat un chat. Retour sur tes captures d’écrans plus haut :
- Produit ou Pièce ? Si ton application gère des pièces de rechange alors c’est le mot “Pièce” qu’il faut voir partout
- Type de mouvement ou Mouvement ? C’est pas la même chose : le 1er est plutôt une caractéristique du 2è -> si ton application gère des mouvements alors ça s’appelle “Mouvement“
Ah et aussi : part d’une page blanche plutôt que d’un modèle d’application existant (beaucoup trop galère selon moi).
-
R3dKap
Membre16 octobre 2024 à 22h37 en réponse à: Filter délégable pour liste sharepoint (Microsoft List) – contourner le "in"Salut @Dany,
Tout dépend de ce que tu appelles les “derniers” enregistrements : quelle est l’élément qui permet de les classer et de les considérer comme premiers ou derniers ?
Parce-que la fonction Sort() est déléguable à SharePoint (du moment que tu ne tries pas sur une colonne complexe) : ce qui veut dire que si tu veux récupérer des lignes parmi les 2000 derniers enregistrements d’une liste qui en contient 1 000 000, tu fais d’abord un Sort() et ensuite tu filtres :
Filter(Sort(Ma_Liste_SharePoint; DateEnreg; SortOrder.Descending); varUserMail in emails_bo)
Bon, ça n’empêchera pas le “in” de ne pas être déléguable…
-
Salut @Lilian,
Essayons déjà de résoudre un problème majeur ici 😅 : je n’ai jamais entendu parler de DataEntity ni dans SharePoint, ni dans Power Apps.
Est-ce que tu peux nous mettre une capture d’écran qui nous montre ce que c’est que ce truc-là ?
🙏
-
Ah bin oui là avec cette url il va rien se passer.
Est-ce que tu peux nous décrire le plus précisément possible quelles manipulations tu fais pour arriver à cet écran vide ? Tu essaies de créer une nouvelle application ? Où cliques-tu ? Tu essaies de modifier une application existante ? Comment fais-tu ?
N’hésite pas à mettre des captures ou faire une p’tite vidéo pour nous montrer… 😉
-
R3dKap
Membre16 octobre 2024 à 22h22 en réponse à: Aide pour transférer des données d’une liste Microsoft dans une collectionAvec plaisir @Fiona… 😉
-
Ok, je vois ce que tu veux faire. Mais avant de te détailler mes suggestions de réalisations, quelques informations importantes sur la logique et l’architecture générale de ton application :
- un contrôle Formulaire (constitué de datacards, eux-même constitutés des 4 contrôles habituels : DataCardKey, DataCardValue, ErrorMessage, StarVisible) est un objet semi-automatisé qui permet de manipuler un enregistrement d’une source de données (liste SharePoint, table Dataverse, table SQL, …) -> un Formulaire ne peut pas travailler avec une collection
- lorsqu’un contrôle Formulaire est placé sur un écran, la bonne pratique veut que l’on fasse l’appel au SubmitForm() soit lors du clic sur un bouton, soit lorsque l’on quitte l’écran -> on ne fait pas de SubmitForm() sur un formulaire qui ne se trouve pas sur l’écran actif !
- donc concrètement :
- soit tu utilises des contrôles Formulaire qui sont branchés sur tes listes SharePoint et à chaque fois que tu quittes un écran ou lors d’un clic sur un bouton tu fais ton SubmitForm() (c’est ce que j’ai plus ou moins décris dans mon post précédent)
- soit tu gères tes enregistrements via une collection et à ce moment-là tu n’utilises pas le contrôle Formulaire, tu construis toi-même tes formulaires de saisies en plaçant des libellés et des listes déroulantes ou des zone de texte sur tes écrans, et tu enregistres les données de ta collection via la fonction Patch() (mais c’est fastidieux car faut tout gérer “manuellement” : les messages d’erreurs, les réinitialisations de chaque contrôle au changement d’enregistrement, etc.)
<hr>
Maintenant il faut qu’on parle de ta liste SharePoint : il faut la revoir car tu mélanges dedans 2 notions différentes :
- les données générales de l’audit (client, auditeur, processus, commentaires, date de l’audit)
- les données des étapes (étape, description, responsable, notes)
Le problème avec ta liste actuelle c’est que tu as mis tous ces champs dans la même liste -> comme tu as un enregistrement par étape, tu vas répéter les données générales autant de fois qu’il y a d’étapes dans l’audit. Tu me suis ?
Il faut donc séparer ces notions dans 2 listes distinctes de la manière suivante :
- Liste AUDITS
- Client
- Auditeur
- Processus
- Commentaires
- Date de l’audit
- Liste ETAPES
- Audit (colonne de recherche qui pointe vers la liste AUDITS)
- Etape
- Description
- Responsable (peut être différent de l’auditeur ? sinon inutile)
- Notes
Bien définir ton modèle de données est crucial pour te faciliter la vie ensuite dans la construction de l’application.
<hr>
Perso ce que j’aurais bien vu en terme d’architecture pour ton appli c’est les écrans suivants :
- ACCUEIL
- Affiche la liste des audits dans une galerie
- Quand on clique sur un audit on arrive sur l’écran DETAILS AUDIT
- Un bouton NOUVEL AUDIT qui amènerait l’utilisateur sur l’écran AUDIT en mode création
- DETAILS AUDIT
- Un encart avec un rappel des données générales de l’audit sélectionné
- Une galerie qui récapitule les étapes de l’audit cliqué
- Ici à toi de voir si tu autorises de modifier les données générales de l’audit (auquel cas il y aurait un bouton MODIFIER L’AUDIT et on se brancherait en modification sur l’écran AUDIT)
- A voir aussi si tu autorises de modifier les étapes de l’audit (auquel cas il y aurait un bouton MODIFIER LES ETAPES et on se brancherait en modification sur l’écran ETAPES)
- AUDIT
- Un formulaire branché sur ta liste AUDITS qui se positionne en mode création
- Ton bouton DEMARRER L’AUDIT qui effectue le SubmitForm() et qui amène l’utilisateur sur l’écran ETAPES en mode création (pour créer à minima la première étape)
- ETAPES
- Un formulaire branché sur ta liste ETAPES et qui fonctionne plus ou moins comme je l’ai décris dans mon post précédent.
- J’ajouterai un bouton SUPPRIMER ETAPE pour se débarrasser d’une étape si nécessaire et je séparerai la notion d’étape suivante de la notion de nouvelle étape : donc je ferais un bouton NOUVELLE ETAPE et le bouton ETAPE SUIVANTE serait grisé lorsque l’on est sur la dernière étape.
- Le bouton TERMINER AUDIT qui ramène soit à l’ACCUEIL soit sur l’écran DETAILS AUDIT
Tu vois que pour moi les données s’enregistrent au fur et à mesure qu’elles sont manipulées. Et ce que je ferais c’est que je mettrais en place dans la liste AUDITS une colonne STATUT qui me permette de savoir si un audit est en cours ou s’il est terminé et qu’on ne peut plus le modifier.
Le truc c’est que tout ça dépend de la manière dont les audits se passent dans la vie réelle et quelles sont les règles de gestion associées. Comme je ne sais pas comment ça se déroule, je fais des suppositions. Typiquement :
- Est-ce qu’un audit peut être interrompu et repris plus tard ? Ne faut-il donc pas un statut de l’audit ?
- Peut-on supprimer des étapes ? Que se passe-t-il pour la numérotation des étapes dans ce cas ?
- Jusqu’à quel point un audit peut-il être modifié/rectifié ?
- etc…
En tout cas, pour répondre à l’une de tes remarques, fonctionner comme ça te permettrait quoiqu’il arrive de pouvoir revenir en arrière sur une étape pour la corriger.
<hr>
Non, la collection n’est pas du tout un élément requis au fonctionnement d’une application Power Apps. Tu peux très bien développer une application Power Apps qui n’utilise aucune collection et qui se “branche” uniquement directement sur les sources de données.
-
Salut @CedZ,
Q1. Pourquoi utilises-tu une collection AuditData ? Pourquoi ne pas travailler directement avec la liste SharePoint ? Passer par une collection complexifie la mécanique (mais peut-être y a-t-il une bonne raison).
Q2. Est-ce que les numéros d’étapes se suivent parfaitement d’un enregistrement à l’autre (sans trous) ? Que se passe-t-il au niveau de la numérotation si on supprime une étape ?
Q3. Qu’as-tu mis pour l’instant dans la propriété Item de ton formulaire ?
Q4. Comment remplis-tu aujourd’hui ta collection AuditData ?
Q5. Qu’as-tu prévu si l’utilisateur a commencé à saisir des données sur l’enregistrement en cours et qu’il clique sur PRECEDENT ? Popup de confirmation ? Il perd ce qu’il a saisit ? Enregistrement automatique ? Et si des champs obligatoires sont vides ?
Q6. Est-ce que le numéro d’étape est automatique et verrouillé ou il est saisi par l’utilisateur ? Que se passe-t-il s’il saisit un numéro complètement décalé avec le n° précédent et le suivant ?
—————-
Par rapport à ton code…
PRECEDENT
Les lignes
Last(FirstN(...))
ne servent à rien ici puisque le résultat n’est renvoyé nulle part, ni dans une variable, ni placées dans une propriété d’un contrôle (ou peut-être ne l’as-tu pas précisé).SUIVANT
Dans ton Collect() tu alimentes des colonnes avec des datacards “complets” (c’est-à-dire avec tous les contrôles qu’il y a dedans). C’est pas comme ça qu’on fait. Il faut que tu utilises les DataCardValueXXX qui sont les contrôles qui portent les saisies de l’utilisateur (listes déroulantes, zone de texte, etc.).
Donc par exemple :Collect(
AuditData;
{
Etape: DataCardValue3.Text;
Responsable: DataCardValue4.Text;
Notes: DataCardValue5.Text
})
Le plus souvent les développeurs ne renomment pas les DataCardValueXXX donc là j’ai mis n’importe quel numéro. Faudra mettre les tiens… 😉
Mais concrètement, pour ce que tu cherches à faire je ferais comme ceci :
- Champs obligatoires : Etape, Description, Responsable
- Sur le OnVisible de l’écran :
UpdateContext({numEtape: 1});; Reset(Form1);;
(on démarre à l’étape 1 et on réinitialise le formulaire) - Sur le Item du formulaire :
Last(FirstN(Sort(TaListeSP; Etape); numEtape))
(il faut bien trier la liste sur les étapes avant d’accéder à l’élément en cours sinon on sera pas sur le bon enregistrement) - Sur le DefaultMode du formulaire :
If(numEtape > CountRows(TaListeSP); FormMode.New; FormMode.Edit)
(en gros si on est sur une étape au-delà des étapes existantes c’est qu’on a cliqué sur le bouton SUIVANT alors qu’on était déjà sur la dernière étape existante -> donc on crée une nouvelle étape) - Sur le OnSelect du bouton PRECEDENT :
UpdateContext({indexationEtape: -1});; SubmitForm(Form1);;
(la variable indexationEtape va être ajoutée à la variable numEtape pour avancer ou reculer dans les étapes selon le bouton cliqué) - Sur le OnSelect du bouton SUIVANT :
UpdateContext({indexationEtape: 1});; SubmitForm(Form1);;
- Sur le OnSuccess du formulaire :
UpdateContext({numEtape: numEtape + indexationEtape});; ResetForm(Form1);;
(le changement d’étape ne doit se faire que si le formulaire a bien été enregistré -> c’est à ça que sert l’événement OnSuccess du formulaire : ainsi, tant qu’il y aura des champs obligatoire non renseignés, l’utilisateur restera bloqué sur l’étape en cours) - Sur le DisplayMode du bouton PRECEDENT :
If(numEtape > 1; DisplayMode.Edit; DisplayMode.Disabled)
(ça c’est histoire de verrouiller le bouton PRECEDENT si on est sur la première étape)
Voilou… J’ai p’têt oublié des trucs… Et c’est en supposant que c’est bien la logique que tu voulais mettre en place… 😉
-
R3dKap
Membre15 octobre 2024 à 22h02 en réponse à: Aide pour transférer des données d’une liste Microsoft dans une collectionSalut @Fiona,
Tu dois écrire ta formule comme ceci :
ClearCollect(
colGriDataConv;
AddColumns(
RenameColumns(
ShowColumns(
ListeFormation;
IdBis;
Cursus;
CFR;
CFA;
DateDebut;
DateFin;
Statut
);
IdBis;
Identifiant;
DateDebut;
'Date de début';
DateFin;
'Date de fin'
);
Convocation;
""
)
)
J’ai fait ça de tête donc y’a p’têt une p’tite erreur mais l’idée est là…
-
Nickel… Alors quelques questions sur l’organisation de tes données d’abord…
Dans ta liste Produits tu as déjà des colonnes Ref interne, Ref fournisseur, Emplacement, etc. Alors pourquoi les répéter dans la table des Mouvements ? Normalement, une donnée ne dois figurer qu’à un seul endroit (sauf raison valable).
Donc dans ta liste Mouvements tu ne devrais avoir que la colonne de recherche Pièce/produit qui pointe vers ta liste Produits (et les autres colonnes propres au mouvement bien sûr). A toi dans l’application d’aller chercher des informations complémentaires au produit si nécessaire lorsque tu es sur un écran de mouvement (voir plus bas).
Du coup j’en viens à l’écran Saisie de mouvement : pourquoi saisir sur cet écran la Ref fournisseur puisqu’elle est censée être fixe et renseignée justement dans la table Produits ? Idem pour Ref obsolète (et peut-être d’autres que l’on ne voit pas sur ta capture).
Concrètement, tu devrais avoir :
- LISTES
- Produits
- Pièce
- Description
- Réf. interne
- Réf. fournisseur
- Fournisseur
- Emplacement
- Qté en stock
- Seuil d’alerte
- Réf. obsolète
- Image
- Date de mouvement (<– ça c’est pas normal : tu peux pas avoir une date de mouvement ici puisque c’est une caractéristique du mouvement et que tu l’as déjà prévu dans ta liste Mouvements)
- Catégorie
- etc.
- Mouvements
- Pièce (qui pointe vers la liste Produits)
- Type de mouvement
- Quantité
- Date de mouvement
- Utilisateur
- Commentaire
- Produits
- ECRANS
- Saisie de produit
- Tous les champs de ta liste Produits
- Saisie de mouvement
- Tous les champs de ta liste Mouvements
- Si dans ton formulaire tu veux afficher des informations de la pièce sélectionnée pour le mouvement en cours de création/modification, informations qui se trouvent dans la liste Produits, alors ajoute par ex. des libellés dans le datacard du champ Pièce/Produit et alimente-les avec un code du style :
LookUp(PRODUITS; ID = DataCardValuePièce.Selected.Id).<nom du champ de la liste PRODUITS que tu veux afficher>
Remplace Produits par le nom de ta liste et DataCardValuePièce par le nom de la liste déroulante Pièce.
- Saisie de produit
Voilà mes recos… 😉
- LISTES
-
Tu peux nous mettre une capture (ou coller) de ton url dans le navigateur quand t’es sur la page blanche ?