R3dKap
Expert Power AppsRéponses céées sur le Forum
-
R3dKap
Membre12 avril 2023 à 9h37 en réponse à: TRANSFORMATION TABLEAU EXCEL ET ENVOIS EN PJ OUTLOOKmaverick59264 pas simple ton besoin… 😅
Ce que j’imagine en terme d’algorithme :
-
Identifier la liste des destinataires (c’est-à-dire les adresses mails de la colonne N)
-
Pour chaque destinataire identifié :
-
Récupérer les lignes du fichier Excel d’origine où la colonne N contient le destinataire
-
Créer un fichier Excel temporaire sur OneDrive avec ces lignes
-
Envoyer le fichier Excel temporaire généré par mail en le mettant en attachement
-
Supprimer le fichier Excel temporaire
-
Donc, ta première étape c’est d’arriver à obtenir la liste des destinataires. As-tu déjà réussi à faire cette partie ?
Je vais essayer de trouver un peu de temps pour reproduire ton cas mais je garanti rien… 😉
CommentID=WNz6JPpR5hhNU8O, PostID=MNHItnp6XZGj0xH
-
-
Bonjour Oliviersg95,
Je suis pas encore un expert sur Dataverse mais voici les bases sur les relations…
Si tu veux créer une relation 1-1 entre 2 tables, il te suffit de créer une nouvelle colonne de type Rechercher et où tu choisis la table liée. Et c’est tout… Le système stockera dans ta colonne la PK de ta table liée. Pas besoin de choisir une colonne dans la table liée (comme dans SharePoint). Et ensuite tu peux accéder aux données de ta table cible simplement avec un
.<colonne>
après le nom de ta colonne de recherche dans ta table source.Ensuite, si tu veux créer des relations 1-N, N-1 ou N-N, là tu passes par l’onglet Relations de l’une de tes 2 tables et tu crées une nouvelle relation Une-à-plusieurs, Plusieurs-à-une ou Plusieurs-à-plusieurs.
Dans le cas de la relation 1-N, le système ajoutera une colonne Rechercher dans la table cible. Dans le cas de la relation N-1, le système ajoutera une colonne de recherche dans ta table source.
Et le cas de la relation N-N est particulier : le système crée une table masquée impossible à interroger comme une table classique autrement que par Power Automate (et encore c’est pas trivial). Du coup, pour les relations N-N je préfère créer moi-même ma propre table dans laquelle je mets les PK des chacune des 2 tables concernées.
Par exemple, pour créer une relation N-N entre Client et Parc, je créerai une table Location avec 2 colonnes :
-
une colonne de recherche Client qui pointe vers la table Client
-
une colonne de recherche Produit qui pointe vers la table Parc
Si tu optes pour la relation N-N “native”, il te faudra utiliser les fonctions Relate() et Unrelate() pour faire et défaire les liens entre tes clients et tes produits.
Si tu optes pour ta propre table Location, il te faudra gérer son contenu à l’aide des fonctions habituelles de gestion de source de données : Patch(), Remove(), …
Voilà, j’espère que je n’ai pas dis de bêtise. Je laisse DavidZed ou autre spécialiste Dataverse confirmer ou infirmer…
CommentID=DGPcfoXYdZMPB5l, PostID=yJBamrxKphKJa6Y
-
Oliviersg95 fait simple : pour créer une relation 1:N ou N:1 fais-le directement dans la table concernée en créant une nouvelle colonne de type Rechercher.
Par exemple, dans ton cas, un produit ne pouvant être en location que par un seul client à la fois à un instant T, il te suffit de créer dans ta table Parc une colonne de type Rechercher que tu peux appeler tout simplement Client, ou encore mieux Loué par (comme ça c’est bien parlant).
Lors de la création de cette colonne, après avoir choisi le type Rechercher, choisi simplement la table Parc comme Table associée. Donne ensuite un nom technique à ta colonne dans Nom du schéma puis à ta relation dans Nom de la relation.Et c’est tout… Est-ce que cela répond à ton besoin ? Sinon n’hésite pas à nous décrire ta cible en termes métier déjà pour commencer afin que l’on comprenne bien ce que tu veux faire au final… 😉
SubCommentID=gOkxzkxlGheLjRN, CommentID=DGPcfoXYdZMPB5l, PostID=yJBamrxKphKJa6Y
-
Oliviersg95 j’ai supprimé ma réponse précédente qui était aussi inexacte (le week-end Pascal est passé par là 😅) et j’ai rectifié mon post d’origine ci-dessus. Je t’invite à le relire attentivement pour bien saisir comment ça fonctionne.
Sinon, y’a toujours la doc officielle :
SubCommentID=IchEAomTXBS7AiK, CommentID=DGPcfoXYdZMPB5l, PostID=yJBamrxKphKJa6Y
-
-
Salut Willfrombadtown,
Pour planifier ton flux Power Automate Desktop depuis un flux Power Automate Cloud Flow, voici la procédure : https://learn.microsoft.com/en-us/power-automate/desktop-flows/trigger-desktop-flows#trigger-a-desktop-flow-from-a-cloud-flow
Pour ce qui est de déclencher un flux Power Automate Desktop Flow depuis un bouton sur ton desktop, là je sais pas trop. En dehors des triggers classiques de Power Automate Desktop, je vois pas. Ou alors faudrait ajouter un bout de code à ton bouton pour qu’il fasse un call API Graph pour déclencher ton flux Power Automate Desktop ou déclencher un cloud flow qui lui-même déclencherai ton desktop flow.
Clairement, pour faire du Desktop flow tu dois avoir la licence à 33,70. Pas le choix…
CommentID=JhcGHNFoArKyaaY, PostID=whiKcabDCw4ZaLK
-
Salut Willfrombadtown,
Je ne comprends pas bien tes phrases “Sur Desktop, j’aimerai avoir la possibilité de créer des boutons sur le bureau.“. Idem pour la suivante “Sur Desktop, j’aimerai avoir la possibilité de créer des boutons sur le bureau.“.
Attention, utilise bien le terme complet Power Automate Desktop pour désigner le service RPA de Power Automate. Parce-que le terme Desktop tout seul pourrait tout aussi bien désigner ton bureau une version de bureau d’une application… 😅
Si tu veux faire du RPA avec Power Automate Desktop, il te faut la licence à 33,70… malheureusement 😉
CommentID=eOh3z9L7cSvKMqr, PostID=whiKcabDCw4ZaLK
-
Voici la formule pour convertir les valeurs RGBA qui se trouvent dans 4 text input numériques txtRedValue, txtGreenValue, txtBlueValue (contenant des valeurs de 0 à 255) et txtAlphaValue (contenant une valeur décimale entre 0 et 1) en une chaîne de couleur hexa au format rrggbbaa :
With(n {AlphaNum: "0123456789ABCDEF"};n Mid(n AlphaNum;n 1 + (txtRedValue.Text - Mod(n txtRedValue.Text;n 16n )) / 16;n 1n ) & Mid(n AlphaNum;n 1 + Mod(n txtRedValue.Text;n 16n );n 1n ) & Mid(n AlphaNum;n 1 + (txtGreenValue.Text - Mod(n txtGreenValue.Text;n 16n )) / 16;n 1n ) & Mid(n AlphaNum;n 1 + Mod(n txtGreenValue.Text;n 16n );n 1n ) & Mid(n AlphaNum;n 1 + (txtBlueValue.Text - Mod(n txtBlueValue.Text;n 16n )) / 16;n 1n ) & Mid(n AlphaNum;n 1 + Mod(n txtBlueValue.Text;n 16n );n 1n ) & Mid(n AlphaNum;n 1 + (Round(n txtAlphaValue.Text * 255;n 0n ) - Mod(n Round(n txtAlphaValue.Text * 255;n 0n );n 16n )) / 16;n 1n ) & Mid(n AlphaNum;n 1 + Mod(n Round(n txtAlphaValue.Text * 255;n 0n );n 16n );n 1n )n)
Exemple, si :
-
txtRedValue = 252
-
txtRedValue = 192
-
txtRedValue = 28
-
txtAlphaValue = 0,71
Alors le résultat est : FCC01CB5.
C’est comme ça que j’ai géré la conversion dans mon composant UltimateColorPicker :
CommentID=T9rFhQGtdWBDofz, PostID=OLRuh9zj5RYJEoy
-
-
R3dKap
Membre14 mars 2023 à 14h41 en réponse à: [Bug] Déclaration de variables locales de type 'record'Sebastien Brandeis mon avis…
Je mettrais un p’tit toggle togIsError caché dans le datacard où il y a besoin d’un contrôle de validité des données.
Sur le Default de ce toggle je mettrais :
!IsBlank(DataCardValueXXX) && !IsMatch(...)
. Si le toggle bascule à True c’est que la saisie est invalide. Je me sers alors du toggle pour :-
afficher un message d’erreur adéquat dans le ErrorMessage.Text :
If(togIsError.Value; "Saisie invalide"; Parent.Error)
-
changer la couleur de bordure du champ si erreur, DataCardValueXXX.BorderColor :
If(IsBlank(Parent.Error) && !togIsError.Value; Parent.BorderColor; Color.Red)
Et je ferais ça sur chaque datacard où il y a besoin d’avoir une validation des données. Ca évite de devoir jouer avec des variables et des Patch()… Et pour le côté obligatoire des champs, j’utiliserai le Required natif sur le datacard.
Pour finir, je conditionnerais l’activation du bouton Sauvegarder avec :
Form1.Valid && !togIsError1 && !togIsError2 && ...
Tu vois ce que je veux dire ?
Et probablement que ça règlerait ton pb entre la version Studio et la version publiée de ton app.
CommentID=VjqTR6RvOeCtYJM, PostID=IcFS4j8K7dnDNDT
-
-
Merci. Alors en fait si j’ai bien compris tu voudrais que sur ton écran BrowseScreen1 il n’affiche pas à chaque fois le même nom de la personne sur chaque ligne.
Pour faire ça il va falloir en fait créer un autre écran “entre” ton écran d’accueil Screen1 et le BrowseScreen1. Ce nouvel écran va afficher la liste des personnes et quand on cliquera sur une personne on arrivera sur le BrowseScreen1 qui n’affichera que les lignes de la personne cliquée.
Pour la suite je vais considérer que tu n’utilises pas la colonne Title et je vais utiliser seulement la colonne Nom. Car je ne sais pas comment tu as géré ça. ATTENTION : j’ai l’impression que tu as un espace dans le nom de ta colonne Nom (au moins au niveau du libellé d’affichage). Ca va te poser des galères pour la suite. Je vais supposer que tu l’enlèves…
Commence par dupliquer ton écran BrowseScreen1 et appelle-le ListScreen1. Du coup dedans tu vas avoir ta galerie qui va s’appeler BrowseGallery1_1. Renomme-la en ListGallery1 pour plus de facilité pour la suite.
Dans ta galerie ListGallery1 enlève toutes les infos qui ne t’intéressent pas garde seulement le nom de la personne.
Ensuite, modifie la propriété Items de la galerie ListGallery1 pour mettre ceci :
Distinct(SortByColumns(Filter([@'PACT Suivi']; StartsWith(Nom; TextSearchBox1_1.Text)); "Nom"; If(SortDescending1; SortOrder.Descending; SortOrder.Ascending)); Title)
Sur la propriété OnSelect de cette même galerie mets ceci :
Navigate(BrowseScreen1; ScreenTransition.None)
Sur la galerie BrowseGallery1 de l’écran BrowseScreen1, mets ceci :
SortByColumns(Filter([@'PACT Suivi']; Title=ListGallery1.Selected.Value); "Nom"; If(SortDescending1; SortOrder.Descending; SortOrder.Ascending))
Ensuite, recopie le IconBackarrow1 de l’écran DetailScreen1 et colle-le sur l’écran BrowseScreen1. Place-le en haut à gauche de l’écran et modifie le code ainsi :
Navigate(ListScreen1; ScreenTransition.None)
Voilà l’idée générale. Y’aura encore quelques retouches à faire pour isoler les tris sur le nouvel écran par rapport à celui de BrowseScreen1, mais globalement ça devrait déjà fonctionner…
CommentID=KHny79yyKlM9NYM, PostID=8UTe1NnTtc7tfN3
-
Est-ce que tu peux me mettre une capture de ton écran Screen1 stp ? Merci 😉
CommentID=AZ9f7sDos2GALtE, PostID=8UTe1NnTtc7tfN3
-
R3dKap
Membre7 mars 2023 à 17h25 en réponse à: Colonne localisation sharepoint non visible dans powerAPPSSalut hary,
Malheureusement les colonnes de type Localisation ne sont pas (encore) supportées par Power Apps. Solution de contournement : créer une colonne de texte où stocker les coordonnées GPS.
CommentID=GteK29HAp7eWc8P, PostID=ZdiwrTGRNU9epkC
-
Julien je vois que tes écrans s’appellent BrowseScreen1, DetailScreen1 et EditScreen1. Ce qui laisse supposer que tu as générer cette application directement à partir de la liste SharePoint. Normalement cette application est déjà fonctionnelle et il n’y pas besoin de la modifier pour l’adapter à mes suggestions ci-dessus. Surtout que je vois ton EDIT ci-dessus où tu as commencé à retoucher ces 3 écrans alors que c’est pas nécessaire puisqu’ils fonctionnent déjà bien nativement. Ok pour toi ?
Par contre tu as rajouté un écran Screen1. Que veux tu mettre sur cet écran ?
REMARQUE IMPORTANTE : à un moment tu dis “…je voudrais si on edit un agent parties lieu et dates ca ajoute une colonne…“. Ce n’est pas possible : dans une source de données on ne peut ajouter de colonnes à partir de l’application ; on ne peut qu’ajouter des lignes. Et donc dans ton cas si tu veux un suivi temporel il te faudra créer une ligne pour chaque déplacement. Par exemple :
-
Jean-Michel MARTIN Equipe 1 Chartres 01/02/2023 15/02/2023
-
Jean-Michel MARTIN Equipe 1 Lyon 19/02/2023 21/02/2023
-
etc.
CommentID=sFwZuF3H1tK6MF5, PostID=8UTe1NnTtc7tfN3
-
-
R3dKap
Membre7 mars 2023 à 14h50 en réponse à: Power Apps – Soumission de formulaire et notification d'erreur ou de succèsDe mon côté, pour essayer de donner une certaine cohérence à l’expérience de l’utilisateur, pour les champs pour lesquels j’ai besoin de contrôles customs, je les définis directement sur chacun des contrôles ErrorMessage :
ErrorMessage12.Text =
If(DataCardValue12.SelectedDate < Today(); "La date de début doit être postérieure ou égale à la date du jour."; Parent.Error)
Et je modifie la couleur de la bordure du champ ainsi :
DataCardValue12.BorderColor =
If(IsBlank(ErrorMessage12.Text); Parent.BorderColor; Color.Red)
Et donc sur le bouton, ça oblige à vérifier ces conditions customs en plus :
SubmitButton.DisplayMode =
If(IsBlank(ErrorMessage12.Text) && IsBlank(Form.Error) && Form.Valid; DisplayMode.Edit; DisplayMode.Disabled)
CommentID=QAyczGOXrhnxZNX, PostID=7HE1YBPjiBVCLdV
-
Salut Julien,
Content que le forum te plaise… 😉
Alors en fait, il faut jouer avec la propriété DefaultMode du formulaire. Celui-ci permet de préciser si le SubmitForm() va créer une nouvelle ligne (
FormMode.New
) dans ta liste SharePoint ou en modifier une existante (FormMode.Edit
). Dans le cas de la modification, il faut alors renseigner la propriété Item du formulaire pour lui préciser la ligne concernée, par exemple avec quelque chose comme :LookUp(TaListe; ID = Gallery1.Selected.ID)
si tu as par exemple une galerie qui affiche les lignes de ta liste. Note : cette propriété Item est ignorée lorsque la propriété DefaultMode de ton formulaire est définie àFormMode.New
(pour de la création).Comment as-tu organisé tes écrans ? As-tu un premier écran avec une galerie qui liste les déplacements + un bouton pour créer un nouveau déplacement ? Puis un 2ème écran qui affiche le formulaire ? Ou tout sur le même écran ?
Une bonne pratique serait la suivante…
Ecran Liste déplacements
-
Une galerie galDéplacements où :
-
Items =
TaListeSharePoint
-
OnSelect =
Navigate('Edit déplacement'; ScreenTransition.Fade; {locFormMode: FormMode.Edit; locSelectedDéplacement: ThisItem})
-
-
Un bouton CREER où :
-
OnSelect =
Navigate('Edit déplacement'; ScreenTransition.Fade; {locFormMode: FormMode.New; locSelectedDéplacement: Blank()})
-
Ecran Edit déplacement
-
Un formulaire frmDéplacement où :
-
Datasource =
TaListeSharePoint
-
Item =
locSelectedDéplacement
-
DefaultMode =
locFormMode
-
OnSuccess =
Notify("Déplacement enregistré avec succès !"; NotificationType.Success);; Back()
-
Avec ça tu as le minimum requis pour faire fonctionner ton app… 😉
N’hésite pas si tu as encore besoin d’aide… 😊
Comme tu débutes, je te suggère de lire ce petit article qui propose une bonne nomenclature des contrôles dans tes applications Power Apps :
Et celui-ci que je viens de poster ce matin sur la bonne approche pour la gestion des erreurs/notifications avec les formulaires :
CommentID=oJ3A6vHjpoWAv4Z, PostID=8UTe1NnTtc7tfN3
-
-
Salut Lamya Boukhrissi,
Pour que ta capture puisse permettre à DavidZed de t’aider je te propose de regarder ce petit article qui explique comment faire de bonnes captures lorsqu’il y a des erreurs dans ton application 😉 :
SubCommentID=NRQUbodmwb85YO6, CommentID=aWYHFU1ygKlkX38, PostID=5TLnNhtkQ60dFMF