Tutoriel PowerApps - Développement from scratch d'une application de logistique

Thierry Couairon

Le but de ce tutoriel est de vous faire développer, from scratch, une application simple. L'idée n'est pas de faire un focus sur un point particulier, mais de voir, au fur et à mesure de l'avancée, comment se servir de l'outil. Ce tutoriel est de niveau DÉBUTANT et explore uniquement le côté Développement (Application Canvas), c'est-à-dire « From Scratch ». De plus il nécessite Sql Server ou, à défaut, Excel et OneDrive.

Commentez

- Titre : Tutoriel PowerApps - Développement from scratch d'une application de logistique

- Auteur : Thierry Couairon

- Parution : 20 septembre 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2020 Thierry Couairon. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.

Sommaire

- I. Avant-propos

- II. Pour commencer

- III. Présentation de l'application

- IV. Création des tables

- IV-A. Sql Server

- IV-B. Excel

- IV-C. Connexion à la source de données

- V. Développement

- V-A. Quelques règles

- V-B. Propriétés, contrôles et fonctions utilisés

- V-C. La création des écrans

- V-D. Le login - Autoriser l'accès à l'application

- V-D-1. Écran de login

- V-D-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-D-3. Règles de gestion

- V-D-4. Code

- V-D-4-a. En clair

- V-D-4-b. PowerApps

- V-D-4-c. Nota Bene

- V-D-4-d. Test

- V-E. Le menu - Portail de l'application

- V-E-1. Écran de menu

- V-E-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-E-3. Règles de gestion

- V-E-4. Code

- V-E-4-a. En clair

- V-E-4-b. PowerApps

- V-E-4-c. Nota Bene

- V-E-4-d. Test

- V-F. La gestion des utilisateurs

- V-F-1. Écran

- V-F-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-F-3. Règles de gestion

- V-F-4. Code

- V-F-4-a. En clair

- V-F-4-b. PowerApps

- V-F-4-c. Nota Bene

- V-F-4-d. Test

- V-G. Visu des tables

- V-G-1. Écran

- V-G-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-G-3. Règles de gestion

- V-G-4. Code

- V-G-4-a. En clair

- V-G-4-b. PowerApps

- V-G-4-c. Test

- V-H. Entrée, Sortie et Inventaire

- V-H-1. Écran

- V-H-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-H-3. Règles de gestion

- V-H-4. Code

- V-H-4-a. En clair

- V-H-4-b. PowerApps

- V-H-4-c. Nota Bene

- V-H-4-d. Test

- V-I. La mise à jour

- V-I-1. Écran

- V-I-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-I-3. Règles de gestion

- V-I-4. Code

- V-I-4-a. En clair

- V-I-4-b. PowerApps

- V-I-4-c. Test

- V-J. La recherche dans le stock

- V-J-1. Écran – Estock

- V-J-2. Contrôles à insérer (Icône + sur le côté gauche)

- V-J-3. Règles de gestion

- V-J-4. Code

- V-J-4-a. En clair

- V-J-4-b. Powerapps

- V-J-4-c. Nota Bene

- V-J-4-d. Test

- V-K. Visualisation des logs

- V-K-1. Écran ELog

- V-K-2. Contrôles à insérer

- V-K-3. Règles de gestion

- V-K-4. Code

- V-K-4-a. En clair

- V-K-4-b. Powerapps

- V-K-4-c. Nota Bene

- V-K-4-d. Test

- VI. Pièges à éviter pour développer avec PowerApps

- VII. En guise de conclusion

- VIII. Et la suite ?

- IX. Remerciements

I - Avant-propos

POWERAPPS est un outil proche de Ms Access quant à son fonctionnement (génération des écrans, paramétrage des composants, utilisation des sources de données, langage like VBA), mais s'en écarte par son orientation WEB/Mobile, des fonctions et des paramètres moins nombreux.
Il couvre le même spectre que son illustre ancêtre, c'est-à-dire, d'une part, les utilisateurs non informaticiens qui pourront développer rapidement une application métier en se basant sur des modèles et macros (Flow) existants (un grand nombre sont fournis de base), et, d'autre part, le développeur qui partira « From Scratch ».
Ce tuto est fait à partir de la documentation Microsoft que je vous invite à parcourir.

II - Pour commencer

Connectez-vous à POWERAPPS, puis cliquez sur le bouton « Démarrer gratuitement », entrez votre compte Microsoft puis cliquez sur « S'inscrire ». Si vous avez déjà une licence, vous arriverez directement à la page d'accueil de PowerApps, sinon il faudra vous inscrire et profiter ainsi d'un essai de 30 jours. Cependant cette licence ne vous donnera pas accès au connecteur SLQ Server qui nécessite une « Licence Premium ». Vous devrez alors suivre ce tuto en utilisant Excel et OneDrive.
Cliquez sur « Application Canevas à partir de rien », donnez un nom à votre appli et choisissez Tablette comme cible.
Ignorez la popup qui s'affiche.
L'éditeur est divisé en trois zones. À gauche, les actions possibles (connexion, insertion…), au centre la zone de dessin et à droite les propriétés de l'objet sélectionné .En haut de ces zones, on trouvera le menu (Fichier, Accueil…), et, sous ce ruban, les actions contextuelles liées au menu choisi (ici Accueil).
Il est important de savoir que l’éditeur va exécuter certains évènements comme OnVisible ou OnHidden lorsque vous arriverez sur un écran ou que vous le quitterez.Ce comportement pouvant provoquer des problèmes importants, nous verrons comment y faire face avec l'écran EIOIMaj.
Je n'irai pas plus loin dans la présentation, car nous en ferons une utilisation basique.

III - Présentation de l'application

L'application est une appli logistique simple comportant les fonctions suivantes :

- Login ;

- Administration User ;

- Anomalies ;

- Menu ;

- Entrée Équipement ;

- Sortie Équipement ;

- Inventaire ;

- Recherche sur stock.

Cette simplicité permettra de ne pas se concentrer sur l'algorithme, mais sur l'outil.

IV - Création des tables

IV-A - Sql Server

Ce chapitre est exclusivement réservé aux utilisateurs possédant une Licence Premium, un accès à une base LOCALE Sql Server et des autorisations permettant la création de tables. Les ordres SQL nécessaires se trouvent ici Sql pour la création et l'initialisation des tables. (Remplacez schéma par votre propre schéma.)

IV-B - Excel

Si vous souhaitez utiliser Excel ou si vous n'avez pas la Licence Premium, de base ou d'autorisations, c'est ici.
Ouvrez un nouveau classeur et créez quatre feuilles. Créez ensuite un tableau par feuille que vous renommerez du nom d'une des tables. (La 1re ligne de ces tableaux comportera le nom des colonnes). Initialisez les tables. Les noms des tables et colonnes se trouvent ici.
Une fois le fichier constitué, transférez-le dans OneDrive.
Il vous faudra modifier le code en retirant '[schema].' dans les fonctions SQL.

IV-C - Connexion à la source de données

Cliquez sur Connexions (Icône en forme de cylindre sous +) puis développez connecteur et choisissez votre connexion (Sql Server ou OneDrive).
Ajoutez une connexion et renseignez les paramètres (Compte One Drive ou paramètres SQL).
Apparaît alors la liste des tables de la base (SQL) ou le fichier Excel. (OneDrive. Dans ce cas, sélectionnez celui-ci.) Cochez les quatre tables créées ci-dessus. Celles-ci apparaîtront à gauche, indiquant ainsi le succès de la connexion.
Ce qui suit est valide pour SQL
Création et installation d'une passerelle. C'est impératif pour pouvoir utiliser une base SQL localement, ce qui est notre cas.
Paramètres d'une connexion SQL

- Type d'authentification : Sql Server.

- Connectez-vous à l'aide de la passerelle locale.

- Nom du serveur SQL : (c'est l'instance qui est demandée et non l'URL).

- Nom de la base.

- Login.

- Password.

- Choisissez une passerelle.

V - Développement

V-A - Quelques règles

Règles

- Sauvegardez souvent.

- Faites une copie localement de votre projet à chaque point de synchro.

- Donnez des noms à vos contrôles.

- La zone de codage est vite confuse si votre code est important. N'hésitez pas à écrire celui-ci dans le bloc-note, puis copiez-le dans powerapps. Corrigez les anomalies.

- La syntaxe est de type Excel, c'est-à-dire : le If THEN ELSE se traduit par If (condition;alors;sinon). Quand n instructions se suivent, séparez-les par ;;

V-B - Propriétés, contrôles et fonctions utilisés

Les propriétés ci-dessous sont celles que nous utiliserons.

Propriétés remarquables

Niveau

Quoi

Utilisation

Application

OnStart

Préprocess comme l'initialisation de variables globales, la navigation vers le 1er écran de l'appli

Écran

OnVisible

Préprocess comme l'initialisation de variables temporaires. Focus sur un contrôle particulier

Saisie Utilisateur

OnChange

Déclenché APRÈS la saisie, à la perte du focus

Bouton

OnSelect

Déclenché au clic (et non au select)

Les contrôles ci-dessous sont ceux que nous utiliserons.

Contrôles utilisés

Fonction

Documentation

Utilisation

Propriété importante

Bouton

Button

Déclencher une action

OnSelect

Étiquette

Label

Affichage d'un texte non modifiable

Text

Galerie verticale

Galerie

Affichage d'une collection suivant un gabarit prédéfini

Items

Icône

Icon

Déclencher une action

OnSelect

Saisie utilisateur

Text-Input

Saisie

OnChange

Liste déroulante

Drop Down

Choix unique

OnChange

Table de données

DataTable

Liste des éléments d'une collection

Items

Les fonctions ci-dessous sont celles que nous utiliserons.

Fonctions utilisées

Documentation

Utilisation

AddColumns

Ajouter une colonne à une collection

As

Donner un alias à une table

Back

Revenir en arrière dans la navigation

Collect, Clear, ClearCollect

Insérer des lignes (Collect), vider une collection (Clear), Vider la collection avant d'insérez les nouvelles lignes (ClearCollect)

CountRows

Compter le nombre de lignes d'une table

DateDiff

Différence entre deux dates

Filter

Rendre toutes les lignes (max 500) répondant aux conditions

First, FirstN, Last

Obtenir la 1re ligne (First), la ligne N (FirstN ou LastN), la dernière ligne (Last) d'une collection

ForAll

Boucler sur toutes les lignes d'une collection

IsBlank

Tester si la donnée est à blanc ou null

IsNumeric

Tester si un champ est numérique

IsToday

Vérifier si une date/time est dans la date du jour

Len

Longueur d'un texte, nombre de lignes d'un tableau

LookUp

Rendre la 1re ligne répondant aux conditions

Navigate

Naviguer vers

Notify

Afficher un message

Patch

Mettre à jour des lignes

Reset

Réinitialiser un contrôle

Remove

Supprimer des lignes

Select

Simuler un clic sur un contrôle

SetFocus

Donner le focus

Sort, SortByColumns

Trier (Sort), Trier en utilisant le nom de la colonne (SortByColumns)

Switch

Tests multiples

Text

Transformer numérique ou date vers texte

UpdateContext

Initialiser des variables temporaires

Upper

Mettre un texte en majuscules

Value

Transformer texte vers numérique

Lors de la création des écrans, j'indiquerai les contrôles et fonctions utilisés. Référez-vous à ces tableaux pour la documentation.
Le plus simple est d'ouvrir, dans un deuxième onglet, cette partie et la conserver

V-C - La création des écrans

Renommez screen1 en ETest (cet écran servira au débogage).
Créer huit écrans vierges (Nouvel Écran puis vierge) et renommez-les (les … en face du nom de l'écran) comme ceci :

- ELogin

- EMenu

- EUsers

- ELog

- EStock

- EInOutInv

- EIOIMaj

- EVisu

Il faut dire à l'application quel est l'écran qui sera appelé initialement. Ceci est fait par la propriété OnStart de l'application.

OnStart Application

Navigate(EMenu)

V-D - Le login - Autoriser l'accès à l'application

V-D-1 - Écran de login

Ecran ELogin

V-D-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Étiquette

Affichage LOGIN

Text

LOGIN

Input-Text

Saisie du matricule

MaxLength

8

(1)

Bouton

Validation

Text

VALIDEZ

Étiquette

Affichage texte durant l'accès en base

Text
Fill
Visible

Patientez
Aqua
vVisible

(2)

1. Renommez ce contrôle en Matricule et effacez le texte par défaut.

2. Donnez une taille importante à ce contrôle et passez la police à 30.
On affiche ce texte AVANT la recherche et on le rend invisible APRÈS. Il faut donc modifier la propriété Visible Dynamiquement.

Il est impossible de modifier dynamiquement une propriété fixée. Ainsi l'instruction Etiquette.visible=true sur un contrôle Etiquette dont la propriété visible est fixée à false ne fonctionnera pas. Ce comportement implique que toute propriété qui doit être dynamiquement modifiée ne peut être fixée, mais doit être liée à une variable ou au résultat d'une instruction.

V-D-3 - Règles de gestion

Règles du Login

Règle

Message

Matricule obligatoire

Matricule obligatoire

Matricule doit exister en table P8_Login

Matricule n'existe pas

Ces règles s’appliquent lorsque l’utilisateur appuie sur le bouton VALIDEZ. C’est alors la propriété OnSelect de celui-ci qui est déclenchée. Le code doit donc se trouver sur cette propriété.
Comme expliqué précédemment, l'initialisation des variables et le focus initial se font dans la propriété OnVisible l'écran.

V-D-4 - Code

V-D-4-a - En clair

Propriété OnVisible de l'écran

Initialiser vVisible
Mettre le focus sur le matricule

Propriété OnSelect du bouton

SI (MATRICULE = Space)
ALORS Afficher("Matricule Obligatoire")
SINON
Rechercher flag admin dans P8_Login avec Login=Matricule
SI absent ALORS
Afficher ("Matricule n'existe pas")
SINON
Aller vers EMenu(admin)
FSI
FSI

V-D-4-b - PowerApps

Propriété OnVisible de l'écran

UpdateContext({vVisible:Blank()});;SetFocus(MATRICULE)

Propriété OnSelect du bouton

If (IsBlank(Matricule.Text);Notify("Matricule obligatoire";Error);;SetFocus(MATRICULE);
UpdateContext({vVisible: true});;
UpdateContext({vAdmin: LookUp( '[schema].[P8_login]';Upper(Login) = Upper(Matricule.Text);admin)});;
UpdateContext({vVisible: false});;
If (IsBlank(vAdmin);Notify("Matricule inconnu";Error);;SetFocus(MATRICULE);Navigate(EMenu;Fade;{rAdmin:vAdmin})))

V-D-4-c - Nota Bene

Notify affiche des messages (en haut de l'écran) en y ajoutant une petite icône en fonction du type de message (Warning, Error…). Il y a un cast implicite vers du texte si l'un des composants du message est un texte. Ainsi Notify(100) provoquera une erreur alors que Notify(100 & " ") fonctionnera. Autre particularité, Notfiy("A");;Notify("B") n'affichera que Notify("B")
LookUp recherche, dans une collection, le 1er élément correspondant au test et renvoie la colonne demandée (3e argument) ou la ligne complète si cet argument est absent. Ici c'est le flag admin qui est renvoyé (n'oubliez pas de modifier le nom du schéma ou de l'enlever suivant que vous êtes en SQL ou en Excel).
UpdateContext permet d'initialiser une variable TEMPORAIRE, variable qui n'est visible que de l'écran à l'inverse de la variable GLOBALE qui est initialisée par l'instruction Set et est visible de toute l'application. Les deux étant persistantes, une bonne méthode consiste à initialiser les globales dans la propriété OnStart de l'application et les privées dans la propriété OnVisible de l'écran.
Navigate permet d'aller vers l'écran cité dans le navigate en lui passant, si nécessaire, des paramètres (ce qui est le cas ici). Les paramètres doivent être déclarés dans la fonction Navigate et sont de type temporaire. Ils ne sont utilisables que dans l'écran appelé.[Ici, on déclare un paramètre rAdmin initialisé avec la valeur vAdmin et qui ne pourra être utilisé que dans Emenu.]

V-D-4-d - Test

Test

Résultat

Valider sans saisie

Matricule obligatoire

Saisir XXX et valider

Matricule inconnu

Saisir un logon correct et valider

EMenu

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

V-E - Le menu - Portail de l'application

V-E-1 - Écran de menu

Ecran EMenu

Comme on peut le voir, il y a deux menus possibles en fonction du profil. Si c'est un profil ADMIN, alors c'est le 1er menu qui sera affiché, sinon ce sera le second.
Le flag admin a été récupéré lors du login et passé en paramètre à cet écran sous le nom de rAdmin.

V-E-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Bouton

Menu EUsers

Text
visible

Administrateur
rAdmin

Renommer en BUsers
(1)

Bouton

Menu ELog

Text
visible

Visualisation des Logs
rAdmin

Renommer en BLog
(1)

Bouton

Menu EStock

Text

Interrogation Stock

Renommer en BStock

Bouton

Menu EInOutInv

Text

Entrée Stock

Renommer en BEntree
(2)

Bouton

Menu EInOutInv

Text

Sortie Stock

Renommer en BSortie
(2)

Bouton

Menu EInOutInv

Text

Inventaire

Renommer en BInventaire
(2)

Bouton

Menu EVisu

Text

Visu tables (Test)

Renommer en BVisu
(3)

Étiquette

Affichage Menu Administrateur

Text
Visible

Menu Administrateur
rAdmin

(1)

Étiquette

Affichage Menu

Text
Visible

Menu
Not rAdmin

Même position que le bouton « Visualisation des logs »
(4)

1. La propriété visible est dépendante de la valeur de rAdmin. Si celle-ci vaut true, le bouton sera visible, sinon ce ne sera pas le cas.

2. C'est le même écran qui sera appelé par Entrée, Sortie ou Inventaire, car c'est le même dessin et quasiment les mêmes règles de gestion.

3. Cette fonction ne sert qu'au développeur pour lui permettre de visualiser les tables (P8_…) et la collection Errors.

4. Cet élément ne sera visible que si rAdmin est à false. D'autre part, sa position sera la même que celle du bouton « Visualisation de Logs ». Ceci n'a pas d'importance, le recouvrement n'ayant aucune incidence sur le comportement du contrôle.

Lorsque vous allez inscrire rAdmin dans la propriété visible, le contrôle pourrait disparaitre. Ceci est dû au fait que, n'étant pas passé par le login, rAdmin est à false.
Si c'est votre cas, exécutez le login et donnez un login administrateur. Votre menu reviendra.

V-E-3 - Règles de gestion

Règles du menu

Règle

Message

Afficher Menu 1 ou 2 en fonction du profil

Aller à la fonction choisie

La 1re règle va s'appliquer automatiquement, car la propriété visible des deux étiquettes et des deux boutons concernés est dépendante de ce flag.
La 2e règle s'applique lors du clic sur le bouton, c'est donc la propriété OnSelect qui est concernée.

V-E-4 - Code

V-E-4-a - En clair

Propriété OnSelect des boutons

Aller vers Exxxx()

V-E-4-b - PowerApps

Propriété OnSelect des boutons

Navigate(Exxxxx)

V-E-4-c - Nota Bene

Nous ne précisons pas Fade dans le Navigate, car c'est le défaut.

V-E-4-d - Test

Test

Résultat

Se connecter avec un profil administrateur (Login ADMIN)

Le menu 1 doit apparaître

Se connecter avec un profil non administrateur (Login AGENT)

Le menu 2 doit apparaître

Cliquer sur le bouton

Navigation vers le bon écran

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

V-F - La gestion des utilisateurs

V-F-1 - Écran

Dessin de l'écran Administrateur

V-F-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Icône Flèche gauche

Retour vers Menu

(1)

Étiquette

Affichage Titre

Text

Gestion des utilisateurs

Text-input

Saisie matricule

Text d'information
MaxLength

Matricule
8

Renommer en ILoginAgent

Text-Input

Saisie nom

Text d'information
MaxLength

Nom
50

Renommer en INomAgent

Liste déroulante

Choix Admin ou pas

Par défaut
items

NO
[« YES »;« No »]

Renommer en IAdmin
(2)

Bouton

Ajouter

Text

Ajouter

Étiquette

Afficher texte Login

Text
Fill

Login
BlueViolet

Étiquette

Afficher texte Nom

Text
Fill

Nom
BlueViolet

Étiquette

Afficher texte Admin

Text
Fill

Admin
BlueViolet

Galerie Verticale

Affichage de la table P8_Login

Items
Disposition

P8_Login
Titre, Sous-titre et corps

(3)
(4)

Colonne Admin (Ne pas ajouter, mais sélectionner)

Affichage flag admin

Text
Fill

Instruction
Instruction

(5)
(5)

Étiquette

Affichage Patientez

Text
Fill
Visible

Patientez.. Maj en cours
Aqua
vVisible

(6)

Comme vu précédemment, on doit forcer le focus sur le 1er contrôle de saisie (ici IloginAgent). C'est la propriété OnVisible de l'écran qui sera chargée de le faire.
Ajoutez, donc, à cette propriété, le code SetFocus(IloginAgent).

1. Utilisez le menu Insérer , sous-menu Icône du bandeau et non le menu Formes du volet gauche.

2. Une liste déroulante attend une collection. Celle-ci peut être une table, mais aussi un tableau. Dans ce cas la syntaxe est [el1;el2;…;eln]. C’est le cas ici où la collection est un tableau de deux postes [“YES”;”NO”].

3. Une galerie affiche une collection selon une disposition définie par le modèle choisi ou par l'utilisateur. Cette disposition est valable pour toutes les lignes et toute modification de celle-ci se répercute sur l’ensemble de la collection. Il en est de même pour les propriétés. Ainsi, le remplacement de l’icône > par l’icône poubelle doit se faire uniquement sur la 1re ligne, la modification étant répercutée sur l’ensemble du composant.

4. Les colonnes retenues de la table P8_Login sont Login (Titre), Nom (Sous-Titre) et Admin (Corps).
Renommez les colonnes , dans le contrôle Galerie par Login, Nom et Admin
Remplacez l’icône > par l’icône poubelle.

5. Voir règles de gestion concernant ce contrôle quant aux instructions.

6. Faire la même chose que lors de la recherche du Login.

V-F-3 - Règles de gestion

Règles de l'écran gestion des Utilisateurs

Règle

Message

Icône fait revenir au menu

Ajout Utilisateur

Début

Login obligatoire

Le login est obligatoire

Nom obligatoire

Le nom est obligatoire

Existence utilisateur

L'utilisateur existe déjà

Ajout Utilisateur

Fin

Flag Admin

Début

Admin : Rouge; Non Admin : Vert

Cliquer sur le flag fait changer la valeur en son contraire

Flag Admin

Fin

Suppression

Début

Clic sur l'icône poubelle

Doit rester un agent

Il doit rester un utilisateur au moins

Suppression

Fin

Ces règles vont s'appliquer sur la propriété OnSelect des contrôles activables (Icône, Bouton Ajouter, Flag Admin, icône poubelle).

V-F-4 - Code

V-F-4-a - En clair

Propriété OnSelect de l'icône flèche

Reset des contrôles et Retour arrière d'un écran

Propriété OnSelect du bouton Ajouter

SI (ILoginAgent = Blanc ALORS Afficher("Le Login est obligatoire")
SINON
SI (INomAgent = Blanc ALORS Afficher("Le nom est obligatoire"")
SINON
Rechercher dans P8_Login ILoginAgent
SI existe ALORS Afficher("Cet utilisateur existe déjà")
SINON créer Utilisateur)))

Propriété Test de la colonne admin

SI (item.admin = TRUE ALORS YES SINON NO)

Propriété Fill de la colonne admin

SI (item.admin = TRUE ALORS Vert SINON Rouge)

Propriété OnSelect la colonne admin

SI (item.admin = TRUE ALORS Modifier Table P8 (admin=false) ET Afficher NO ROUGE
SINON Modifier Table P8 (admin=true) ET Afficher YES VERT)

Propriété OnSelect l'icône poubelle

Compter le nombre lignes P8_Login
SI (compte=1 ALORS Afficher("Il doit rester un utilisateur au moins"")
SINON Supprimer la ligne de P8_Login)

V-F-4-b - PowerApps

Propriété OnSelect de l'icône flèche

Reset(IloginAgent);;Reset(INomAgent);;Reset(IAdmin);;Back()

Propriété OnSelect du bouton Ajouter

If(IsBlank(ILoginAgent.Text);Notify("Le Login est obligatoire";Error);;SetFocus(IloginAgent);
If(IsBlank(INomAgent.Text);Notify("Le nom est obligatoire";Error);;SetFocus(INomAgent);
If (IsBlank(LookUp('[schema].[P8_Login]';Upper(Login)=Upper(ILoginAgent.Text);Login));UpdateContext({vVisible:true});;Collect('[schema].[P8_Login]';{Login:Upper(ILoginAgent.Text);nom:INomAgent.Text;admin:If(IAdmin.SelectedText.Value="YES";true;false)});;UpdateContext({vVisible:false});
Notify("Cet utilisateur existe déjà");SetFocus(IloginAgent))))

Propriété Text de la colonne admin

If (ThisItem.admin;"YES";"NO")

Propriété Fill de la colonne admin

If (ThisItem.admin;Green;Red)

Propriété OnSelect la colonne admin

UpdateContext({vVisible:true});;Patch('[schema].[P8_login]';ThisItem;{admin:If (ThisItem.admin;false;true)});;UpdateContext({vVisible:false})

Propriété OnSelect l'icône poubelle

If (CountRows('[schema].[P8_login]') < 2;Notify("Il doit rester un utilisateur au moins";Error);;SetFocus(IloginAgent);
UpdateContext({vVisible:true});;Remove('[schema].[P8_login]';ThisItem);;UpdateContext({vVisible:false}))

V-F-4-c - Nota Bene

Remarquez l'utilisation de tests directement dans les fonctions. Cette façon de faire, si elle est maîtrisée, permet de rendre le code moins verbeux.
Remarquez aussi que l'on n'écrit pas, par exemple, If (ThisItem.admin;ThisItem.admin=false;ThisItem.admin=true). Cette syntaxe est incorrecte, car nous sommes déjà dans la partie valeur du couple nom:valeur.
Remarquez l'utilisation de ThisItem. Cette syntaxe correspond à Collection.SelectedItem. En effet, l'appui sur l'une des colonnes (icône) d'une ligne sélectionne celle-ci automatiquement.

V-F-4-d - Test

Test

Résultat

Ajouter un utilisateur sans rien renseigner

Message Login Obligatoire

Renseigner le login, pas le nom puis ajouter

Message Nom Obligatoire

Renseigner login et nom avec un login existant

Message Utilisateur existe déjà

Renseigner login et nom avec un login non existant

Celui-ci apparaît dans la liste

Cliquer sur le flag admin

Changement de texte et de couleur (YES ver NO et inv., Vert vers Rouge et inv.)

Cliquer sur l'icône poubelle

Si plus d'un agent, suppression de celui-ci sinon Message Il doit rester un utilisateur au moins

Cliquer sur l'icône flèche

Retour au menu

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.
Si vous ne voyez pas votre ajout, vérifiez que celui-ci n'est pas sous la fenêtre de la galerie.

Lorsque vous reviendrez au menu, vous constaterez que le menu est conservé alors que l'on ne relit pas le flag admin. Ceci démontre la persistance des données dans les écrans, persistance qu'il faudra gérer si besoin.

V-G - Visu des tables

V-G-1 - Écran

Dessin de l'écran Visu des tables

Cet écran ne sert que lors des tests pour vérifier les mises à jour des tables P8_Equipement, P8_Mouvement et P8_Stock. On y ajoute aussi la collection ERRORS que l'on fait pointer sur P8_Stock.

V-G-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Icône Flèche gauche

Retour vers Menu

DataTable

Liste P8_Mouvement

Items

P8_mouvement

(1)

DataTable

Liste P8_Stock

Items

P8_stock

(1)

DataTable

Liste P8_Equipement

Items

P8_equipement

(1)

Errors

Erreurs éventuelles

(1)(2)

1. Suivant votre version de PowerApps, le contrôle à insérer peut être nommé « Table de données »
Dans le 1er volet, cliquez sur modifier champs puis, dans la popup qui apparaît sur ajouter champs et ajouter l'ensemble des champs de la table. (L'ordre dans lequel vous sélectionnez les champs donne l'ordre d'affichage.)

2. Errors est une collection prédéfinie qui contient les erreurs éventuelles liées aux ordres SQL comme Patch,Update,Collect… Il y a une collection par table.

V-G-3 - Règles de gestion

Règles de l'écran Visu

Règle

Message

Icône fait revenir au menu

Ces règles vont s'appliquer sur la propriété OnSelect de l'Icône.

V-G-4 - Code

V-G-4-a - En clair

Propriété OnSelect de l'icône flèche

Naviguer vers le menu

V-G-4-b - PowerApps

Propriété OnSelect de l'icône flèche

Navigate(EMenu)

V-G-4-c - Test

Test

Résultat

Cliquer sur l'icône flèche

Retour au menu

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.
Si vous ne voyez pas vos données, vérifiez que celles-ci ne sont pas cachées (Slider).

V-H - Entrée, Sortie et Inventaire

V-H-1 - Écran

Dessin de l'écran du Scan

Cet écran ne possède qu'une seule zone Input alors que nous allons avoir à saisir Casier, Équipement et Quantité. Ce choix est lié au fait que l'agent peut commencer indifféremment par le casier ou l'équipement.

V-H-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Icône Flèche gauche

Retour vers Menu

(1)

Text-Input

Interdiction de maj

Text
Visible

vEIOI
false

(2)

Étiquette

Affichage de l'étape

Text

vLabel

(3)

Text-Input

Saisie agent

Étiquette

Affichage Casier

Text

Casier : vCasier

(4)

Étiquette

Affichage Équipement

Text

Équipement : vDes

(4)

Étiquette

Affichage Quantité

Text

Quantité : vQte

(4)

DataTable

Liste P8_Mouvement

Items

P8_mouvement

(4)

1. On choisit Navigate plutôt que Back, car la mise à jour se fera dans EIOIMaj. Back ferait alors revenir à l'écran EIOIMaj et non au menu.

2. Cet Input-text va servir de flag pour la maj dans l’écran EOIMaj. (Voir Ecran EIOIMaj.)

3. vLabel vaudra « Équipement ou Rangement » ou « Quantité » suivant l'étape.

4. Comme nous n'avons qu'une seule zone d'input, celle-ci ne peut conserver les données entrées. Cette fonction est dévolue à ces Étiquettes.

5. Liste des mouvements saisis dans la journée et triés par date de maj Décroissante.
On ne peut ici se contenter de donner juste la table. Il faut aussi que la liste réponde aux critères souhaités. Pour obtenir la liste des mouvements du jour, on utilisera Filter qui renvoie un ensemble de lignes et Sort pour trier celui-ci.

V-H-3 - Règles de gestion

Règles de l'écran InOutInv

Règle

Message

Si appelé par menu, l'ensemble des zones doit être initialisé.
Si retour de la mise à jour, le casier doit rester présent.
On peut commencer indifféremment par le casier ou l'équipement.
On ne saisit la quantité que lorsque le casier et l'équipement sont renseignés.
La saisie de la quantité déclenche la mise à jour SAUF si celle-ci vaut zéro (provoque le retour à la saisie de l'équipement).

Icône fait revenir au menu

Si saisie 5 caractères non numériques => Casier

Si saisie numérique et équipement ou casier non encore saisi => Équipement

Équipement n'existe pas

Si saisie numérique et équipement et casier saisis => Quantité

Quantité non numérique

La 1re règle est appliquée AVANT l'affichage de l'écran, donc avec l'évènement OnVisible. Pour éviter que le casier soit écrasé d'où que l'on vienne, celui-ci sera initialisé au retour vers le menu.
La règle liée à l'élément cliquable (la flèche gauche) est supportée, comme déjà vu, par OnSelect.
Les règles qui régissent les contrôles doivent être exécutées lorsque la saisie est terminée.
C'est l'évènement OnChange qui est concerné. Celui-ci est déclenché à la perte du focus, c'est-à-dire quand la saisie est terminée.

V-H-4 - Code

V-H-4-a - En clair

Propriété Items de la liste

Rechercher la liste de P8_Mouvements tels que la date de maj soit dans la date du jour.
Trier celle-ci par date décroissante

Propriété OnVisble de l'écran

Reset des variables (hors casier) et du IScan
Afficher "Equipement ou Rangement"
Donner le focus à IScan

Propriété OnSelect de l'icône flèche

Reset du casier
Naviguer vers le menu

Propriété OnChange de IScan

SI (casier=blanc ou équipement=blanc ALORS
SI (IScan n'est pas numérique ALORS
SI (Longueur de IScan = 5 ALORS
casier = IScan
SINON
Afficher ("Scan invalide (Casier ?)"
FSI
SINON
Recherche équipement dans P8_Equipement avec P8.equipement = ISCAN
SI (Non trouvé ALORS
Afficher ("Scan invalide (Equipement ?)")
SINON
équipement = IScan
FSI
FSI
SI (casier <> blanc ET équipement <> blanc ALORS Label = "Quantité"    FSI
SINON
SI (IScan = "0" ALORS
Equipement = blanc
Label = "Equipement ou Rangement"
SINON
SI (IScan non numérique ALORS
Afficher("Quantité non numérique")
SINON
Aller vers EIOIMaj (casier,équipement,quantité,type traitement)
FSI
FSI
FSI

V-H-4-b - PowerApps

Propriété Items de la liste

Sort(Filter('[schema].[P8_mouvement]';IsToday(DateMaj));DateMaj;SortOrder.Descending)

Propriété OnVisble de l'écran

UpdateContext({vLabel:"Equipement ou Rangement"});;
UpdateContext({vEqpt:Blank()});;
UpdateContext({vQte:Blank()});;
UpdateContext({vDes:Blank()});;
UpdateContext({vEIOI:Blank()});;
Reset(IScan);;
SetFocus(IScan)

Propriété OnSelect de l'icône flèche

UpdateContext({vCasier:Blank()});;
Navigate(EMenu)

Propriété OnChange de IScan

If (IsBlank(vCasier) Or IsBlank(vEqpt);
If (Not IsNumeric(IScan.Text);
If (Len(IScan.Text) = 5;UpdateContext({vCasier:IScan.Text});Notify("Scan invalide (Casier   ?)";Error));
UpdateContext({vDes:LookUp('[schema].[P8_equipement]';Equipement=Value(IScan.Text);Designation)});;
If (IsBlank(vDes);Notify("Scan invalide (Equipement ?)";Error);
UpdateContext({vEqpt:IScan.Text})));;
If (Not IsBlank(vEqpt) And Not IsBlank(vCasier);UpdateContext({vLabel:"Quantité"}));
If (IScan.Text = "0";UpdateContext({vEqpt:Blank()});;UpdateContext({vDes:Blank()});;UpdateContext({vLabel:"Equipement ou Rangement"});
If (Not IsNumeric(IScan.Text);Notify("Quantité non numérique";Error);
UpdateContext({vEIOI:"X"});;
Navigate(EIOIMaj;Fade;{rCasier:vCasier;rEqpt:vEqpt;rQte:IScan.Text;rType:typeTrt}))));;Reset(IScan);;SetFocus(IScan)

V-H-4-c - Nota Bene

Noter la valeur de vEIOI qui est blanc au départ et devient X juste avant le Navigate. C'est ce flag qui autorisera ou non la maj et règle ainsi le déclenchement intempestif du OnVisible de l'écran de EIOIMaj
Avant de tester cet écran , il faut d'abord modifier le menu afin de lui passer le type (Entrée, Sortie ou Inventaire). Le code est Navigate(EInOutInv;Fade;{typeTrt:« E »}) pour l'entrée, O pour la sortie et I pour l'inventaire.

V-H-4-d - Test

Test

Résultat

Initialisation

Toutes les variables sont à blanc
Le focus est sur le champ IScan

Cliquer sur l'icône flèche

Retour au menu

Entrer 3 car non numériques

Scan invalide (Casier ?)

Entrer 5 car non numériques

Texte Casier : valeur casier

Entrer 8 car numériques ne correspondant pas à un équipement

Scan invalide (Équipement ?)

Entrer 8 car numériques correspondant à un équipement

Texte Équipement : désignation équipement
Label « Quantité »

Entrer n car non numériques

Quantité non numérique

Entrer 0

Seul le casier doit rester présent
Label « Équipement ou Rangement »

Revenir à la quantité et entrer n car numériques

Appel de EIOIMaj

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

V-I - La mise à jour

V-I-1 - Écran

Dessin de l'écran de maj

Nous sommes ici dans le cas d'une fonction déportée, c'est-à-dire d'une fonction qui aurait dû être placée ailleurs (ici dans le onChange du contrôle IScan de l'écran EInOutInv). Il peut y avoir de bonnes raisons à faire ceci (lisibilité, complexité, réutilisation…), mais en général, on préférera les Flow qui se comportent comme des macros plutôt que d'utiliser un écran. (Dans ce tuto, la raison est de montrer l'utilisation d'un écran comme une fonction déportée, cet écran n'existant pas dans l'appli originelle.)

V-I-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Étiquette

Affichage de l'étape

Text
Fill

vLabel
Aqua

(1)

Bouton

Retour vers EInOutInv

Visible

false

(2)

1. Affichera le texte Patientez et l'étape de mise à jour. Celle-ci devra être importante, taille police 30.

2. Renommez-le en BRetour. Ce bouton servira à faire le retour à EinOutInv lorsqu'il sera sollicité par l'instruction Select. Un écran ne peut pas faire un Back dans OnVisible. Ceci provoque une erreur de syntaxe. On peut contourner cette limitation grâce à un contrôle que l'on déclenche à distance par l'instruction Select(nom du contrôle).

V-I-3 - Règles de gestion

Règles de l'écran EIOIMaj

Règle

Message

Ne s'exécuter que si le contrôle EIOI vaut X

Créer un mouvement
Créer un stock si n'existe pas ou mettre à jour le stock existant
Mettre à jour l'équipement

Si type=E alors stock = stock + Qte, Equipement = Equipement + Qte
Si type=S alors stock = stock - Qte, Equipement = Equipement - Qte
Si type=I alors Stock=Qte, Equipement=Equipement - ancien qte de stock + Qte

La 1re règle est impérative compte tenu du fonctionnement de l'éditeur.
Comme dit au début de ce tuto, OnVisible (resp OnHidden) est exécuté LORSQU'ON ENTRE (resp. SORT), que ce soit par l'application (Navigate, Back) ou par sélection de l'écran dans l'éditeur. Si, associé à cet évènement, on y a codé une mise à jour de base, par exemple, celle-ci SERA EXÉCUTÉE même si l'intention première était de modifier l'écran.
Faites ce test : Créez deux écrans, l'un que vous nommerez E1 et l'autre E2. Dans E1, ajoutez un bouton qui aura comme code Navigate(E2) puis sélectionnez E2. Ajoutez-y un bouton que vous renommerez B1, dans lequel, vous coderez, à son évènement OnSelect Navigate(E1), puis dans l'évènement OnVisible de l'écran E2, codez Select(B1).
Sauvez le tout, puis retournez sur E1 et cliquez sur le bouton. Vous allez voir E2 apparaître brièvement puis vous reviendrez sur E1, ce comportement est normal.
Maintenant, toujours dans l'éditeur, sélectionnez E2. Vous revenez à E1 et E2 n'est plus accessible.
Ce test démontre que l’évènement OnVisible a été déclenché. Il est donc souhaitable de ne pas coder de procédures critiques comme des mises à jour de base ici (la seule option qu'il vous reste est de renommer E1 afin de provoquer une erreur dans E2).

V-I-4 - Code

V-I-4-a - En clair

OnVisible

SI (EIOI = "X" ALORS
vLabel = "Maj Mouvement"
Créer un enregistrement dans P8_mouvement
vLabel = "Maj Stock"
Rechercher Stock avec Equipement et Casier
SI (stock n'existe pas ALORS
Créer Stock
oldStock = rQte
SINON
oldStock = stock.stock
Mettre à jour stock.stock
FSI
vLabel = "Maj Equipement"
Rechercher Equipement
Mettre à jour equipement.qteStock
Reset EIOI
Déclencher BRetour

Propriété OnSelect de BRetour

Retourner à EInOutInv

V-I-4-b - PowerApps

Propriété OnVisible de EIOIMaj

UpdateContext({vLabel:""});;
If(EIOI.Text="X";UpdateContext({vLabel:"Maj Mouvement"});;
Collect('[schema].[P8_mouvement]';{Equipement:Value(rEqpt);Designation:LookUp('[schema].[P8_equipement]';Equipement= Value(rEqpt);Designation);Qte:Value(rQte);Casier:rCasier;Type:rType;Agent:Matricule.Text;DateMaj:Now()});;
UpdateContext({vLabel:"Maj Stock"});;
UpdateContext({stock:LookUp('[schema].[P8_stock]';Equipement=Value(rEqpt) And Casier=rCasier)});;
If (IsBlank(stock);Collect('[schema].[P8_stock]';{Equipement:Value(rEqpt);Casier:rCasier;Stock:Switch(rType;"E";Value(rQte);"S";Value(rQte)*-1;"I";Value(rQte))});;                                           UpdateContext({oldQte:Value(rQte)});
UpdateContext({oldQte:stock.Stock});;
Patch('[schema].[P8_stock]';stock;{Stock:Switch(rType;"E";stock.Stock+Value(rQte);"S";stock.Stock-Value(rQte);"I";Value(rQte))}));;
UpdateContext({vLabel:"Maj Equipement"});;
UpdateContext({tabEqpt:LookUp('[schema].[P8_equipement]';Equipement=Value(rEqpt))});;
Patch('[schema].[P8_equipement]';tabEqpt; {QteStock:Switch(rType;"E";tabEqpt.QteStock+Value(rQte);"S";tabEqpt.QteStock-Value(rQte);"I";tabEqpt.QteStock-oldQte + Value(rQte));QteRecue:If(rType="E";tabEqpt.QteRecue+Value(rQte);tabEqpt.QteRecue)});;
Reset(EIOI);;
Select(BRetour))

Propriété OnSelect de BRetour

Back()

V-I-4-c - Test

Test

Résultat

Sélectionner EMenu puis revenir dans cet écran

Constater qu'aucune mise à jour n'est faite

Retour à Elogin puis dérouler l'application et faire quelques entrées

Vérifier que vous avez bien tous vos mouvements dans EInOutInv et vérifier, dans EVisu que les tables Stock et Equipement sont à jour

Retour à EMenu puis dérouler l'application et faire quelques sorties

Vérifier que vous avez bien tous vos mouvements dans EInOutInv et vérifier, dans EVisu que les tables Stock et Equipement sont à jour

Retour à EMenu puis dérouler l'application et faire quelques inventaires

Vérifier que vous avez bien tous vos mouvements dans EInOutInv et vérifier, dans EVisu que les tables Stock et Equipement sont à jour

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

V-J - La recherche dans le stock

V-J-1 - Écran – Estock

Dessin de l'écran EStock

V-J-2 - Contrôles à insérer (Icône + sur le côté gauche)

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Icone Left Arrow

Return EMenu

Étiquette

Recherche dans le stock

Text

Recherche dans le stock

Input-Text

Saisie de l'équipement

(1)

Galerie verticale

Affichage des stocks répondant au critère

Items
Disposition

liste
Titre, sous-titre et corps

(2)
(3)

Étiquette

Affichage texte durant l'accès en base

Text
Fill
Visible

Patientez…Recherche en stock
AquaMarine
vVisible

(4)

Étiquette

Affichage popup Équipement

Text
Fill
Visible

(5)
AntiqueWhite
vPlus

(6)

Icône X

Fermeture popup

Fill
Visible

AntiqueWhite
vPlus

1. Renommez ce contrôle en IStock et effacez le texte par défaut.

2. Renommez ce contrôle en Gliste.

3. Le Texte du titre doit comporter, non pas le N° d'équipement, mais la désignation. On obtient celle-ci par un LookUp sur l'équipement.
La propriété sera donc "Désignation : " + LookUp('[schema].[P8_equipement]';Equipement=ThisItem.Equipement;Designation)
Il est de très loin préférable d'utiliser une vue dans ce cas. En effet, le LookUp est effectué sur chaque ligne, ce qui pourrait potentiellement donner des temps de réponse exécrables.

4. Donnez une taille importante à ce contrôle et passez la police à trente Gras.

5. Text : "Équipement " + vEqpt.Equipement + Char(13) + "Total : " + vEqpt.QteStock

6. Renommez ce contrôle en popEqpt.

La popup est une fenêtre apparaissant au milieu de l'écran. Ce ne peut être un écran comme on en a généré jusqu'ici, car le Navigate écrase l'écran original.
On utilise ici une astuce qui se base sur deux contrôles. Un Text qui affichera les données et une icône X pour fermer notre popup. L’astuce réside en des positions contiguës, une couleur de fond identique et une variable de visibilité identique (ainsi les deux sont visibles ou invisibles en même temps).
Il existe d'autres façons de faire bien sûr, mais je trouve celle-ci simple et déclinable à l'infini.

V-J-3 - Règles de gestion

Règles de l'écran EStock

Règle

Message

Rechercher les stocks de l'équipement demandé

Trier par Équipement Casier

L'appui sur la flèche droite affiche le n° d'équipement et le stock total dans une popup

La recherche sera lancée à la fin de la saisie , donc, quand l'évènement OnChange sera déclenché.
La règle portant sur les données supplémentaires sera déclenchée au OnSelect de l’icône activée.

V-J-4 - Code

V-J-4-a - En clair

OnVisible

vVisible=false
vPlus=false
Donner le focus à IStock

OnSelect de la flèche gauche

Effacer IStock
Effacer la liste
Retourner à menu

OnChange de IStock

vVisible = true ' Rend visible la fenêtre "patientez..."
liste = Rechercher les stocks dont l'équipement correspond au N° d'équipement demandé et trier celle-ci par équipement, casier
vVisible = false ' Rend invisible la fenêtre "Patientez...."

OnSelect d'un item de Gliste

vEqpt = Rechercher l'équipement correspondant au N° de l'équipement de la ligne de Gliste sélectionnée
vPlus= true ' Rend visible la popup

OnSelect de l'icone X de la popup

vPlus = false ' Rend invisible la popup
SetFocus(IStock)

V-J-4-b - Powerapps

OnVisible

UpdateContext({vVisible:false});;
UpdateContext({vPlus:false});;
SetFocus(IStock)

OnSelect de la flèche gauche

Reset(IStock);;
Clear(liste);;
Navigate(EMenu)

OnChange de IStock

UpdateContext({vVisible:true});;
ClearCollect(liste;SortByColumns(Filter('[Power].[P8_stock]';Equipement=Value(IStock.Text));"Equipement";Ascending;"Casier";Ascending));;UpdateContext({vVisible:false})

OnSelect d'un item de Gliste

UpdateContext({vEqpt:LookUp('[Power].[P8_equipement]';Equipement=ThisItem.Equipement)});;
UpdateContext({vPlus:true})

OnSelect de l’icône X de la popup

UpdateContext({vPlus:false});;
SetFocus(IStock)

V-J-4-c - Nota Bene

Clear vide une collection de tous ses objets. À ne pas confondre avec Remove ou RemoveIf qui supprime des lignes d'une table.
ClearCollect vide une collection (Clear) avant de la recharger (Collect). Si on n'efface pas une collection, la nouvelle liste est ajoutée à la collection existante (Merge).
SortByColumns trie les lignes d’une collection. Il se diffère de Sort par la possibilité de faire du multicritère et par l’utilisation, pour définir un critère, du nom de la colonne.

V-J-4-d - Test

Test

Résultat

Entrez un équipement existant

Liste des casiers dans Gliste

Sélectionner la flèche droite

La popup apparaît

Fermer la popup

Celle-ci disparait et le focus est rendu au text-input

Retour à EMenu

Affichage EMenu

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

V-K - Visualisation des logs

V-K-1 - Écran ELog

Dessin de l'écran ELog

Cet écran ne correspond pas à ce qui a été réellement développé, mais va nous permettre d'aborder les jointures et la problématique des icônes dans les DataTables.

V-K-2 - Contrôles à insérer

Contrôles utilisés

Contrôle

Utilisation ici

Propriété

Valeur

Remarques

Icône Left Arrow

Return EMenu

Input-Text

Interdiction de maj et de recherche

visible

false

(1);

Étiquette

Libellé

Text

Visualisation des Mouvements

Étiquette

Libellé

Text
Fill

Date début (Gras)
BlueViolet

Étiquette

Libellé

Text
Fill

Date fin (Gras)
BlueViolet

Étiquette

Libellé

Text
Fill

Stock Négatif (Gras)
BlueViolet

Input-Text

Saisie de l'équipement

DisplayMode

vDisabled

(2);

Input-Text

Saisie du casier

DisplayMode

vDisabled

(3)

Sélecteur de date

Saisie date début

Default Date
InputTextPlaceHolder
DisplayMode

(4)
(4)
vDisabled

(4)

Sélecteur de date

Saisie date fin

Default Date
InputTextPlaceHolder
DisplayMode

(5)
(5)
vDisabled

(5)

Liste déroulante

Choix stock négatif

items
Default
DisplayMode

[« Oui »;« Non »]
« Non »
vDisabled

(6)

Étiquette

Libellé

Text
Fill

Trié par (Gras)
BlueViolet

ComboBox

Choix des critères

Items
No Selection text
Select Multiple
DisplayMode

[« Équipement »;« Casier »;« Date de Mouvement »]
Choisir un ou plusieurs critères
true
vDisabled

(7)

Button

Exécution

(8)

DataTable

Liste des mouvements

Items
Champs

(9)
(9)

(9)

Étiquette

Détail équipement

Text
Fill
visible

(10)
AntiqueWhite
vDetail

Icône X

Fermeture popup

Fill
Visible

AntiqueWhite
vDetail

(11)

Rectangle

Modification Stock

Fill
visible

AntiqueWhite
vEdit

(12)

Étiquette

Correction du Stock

visible

vEdit

(13)

Input-Text

Saisie Modification Stock

Hint text
visible

Nouveau stock
vEdit

(13)

Button

Confirmation stock

visible

vEdit

(13)

Icône X

Fermeture popup

Visible

vEdit

(13)

Étiquette

Libellé

Text
visible
Fill

Patientez…Recherche en cours
vVisible
AquaMarine

1. Renommez ce contrôle en ILog et effacez le texte par défaut.

2. Renommez ce contrôle en ILogEqpt et effacez le texte par défaut.

3. Renommez ce contrôle en ILogCasier et effacez le texte par défaut.

4. Renommez ce contrôle en ILogDebut,
DefaultDate = ToDay()-30,
InputTextPlaceHolder = If(IsBlank(Self.SelectedDate); Text(Today() - 30; Self.Format; Self.Language))
Self veut dire que l'action est sur le contrôle lui-même. C'est l'équivalent de this en Java, par exemple.
Le cast en texte de ToDay.. est nécessaire, car seul le texte est accepté.

5. Renommez ce contrôle en ILogFin,
DefaultDate = ToDay(),
InputTextPlaceHolder = If(IsBlank(Self.SelectedDate); Text(Today()); Self.Format; Self.Language))

6. Renommez ce contrôle en IlogStock.

7. Renommez ce contrôle en ILogTri.
PowerApps ne fait pas de distinction entre Value et Texte comme le fait la tag option en html.
Ce qui est affiché est renvoyé au programme. Ce comportement est gênant quand on désire afficher un texte à l'utilisateur et recevoir une autre valeur (ce qui est le cas ici avec la date de mouvement).

8. Renommez ce contrôle en Bliste.

9. Renommez ce contrôle en DListe
Les champs à insérer sont : DateMaj, Type, Equipement, Casier, Qte, MvtStock, MvtEqpt, Détail, Correction. Les quatre derniers champs ont été ajoutés par l'instruction AddColumns (voir le code correspondant).

10. Renommez ce contrôle en LDetail.
Text : "Equipement " + vEquipement.Equipement + Char(13) + "Designation " + vEquipement.Designation + Char(13) "Stock : " + vEquipement.QteStock.
Avec le contrôle ICloseDet, nous reprenons le principe de la popup vu dans l'écran précédent.

11. Renommez ce contrôle en IcloseDet.

12. Ce contrôle sert à donner un fond à la popup de correction.

13. Tous ces éléments appartiennent à la même popup. Ils ont donc la même visibilité.

V-K-3 - Règles de gestion

Règles de l'écran ELog

Règle

Message

Si stock négatif, l'équipement et le casier ne doivent pas être renseignés

Interdit avec Stock négatif

Récupérer la liste des mouvements triée suivant les critères choisis.
Cette liste comportera deux colonnes supplémentaires : Détail (Icône loupe) et Correction (Icône crayon).

L'appui sur la loupe affichera le détail de l'équipement

L'appui sur le crayon affichera la popup permettant la correction du stock

Popup de correction : la quantité doit être numérique

Quantité non numérique

Comme d'habitude, ces règles s'appliquent au OnSelect pour les boutons, items pour les liste et OnVisible pour l'écran.
Nous avons vu et revu ces principes, aussi je ne m'étendrai pas plus avant. Passons au code.

V-K-4 - Code

V-K-4-a - En clair

OnVisible

' Initialisations diverses
vDisabled = DisplayMode.Edit; ' Enable tous les contrôles concernés
vEdit = false; ' Rend invisible la popup de correction
vDetail = false; ' Idem pour le détail
Donner le focus à ILogEqpt
Ttexte = "Patientez ... La recherche est en cours"
vVisible = false ' Rendre invisible la fenêtre d'attente
SI ILog=X ALORS
vLog=Blanc; ' Interdit la maj
Clic sur BListe ' Relance une recherche pour prendre en compte les modifications
FSI

OnSelect de la flèche gauche

Effacer ILogTri, ILogFin, ILogDebut, ILogCasier, ILogEqpt
vLog = Blanc
Vider mvtListe et mvtLste
Retourner au menu

OnSelect de BListe

LogTri = Pour tous les critères sélectionnés : Si critère = "Date de Mouvement" ALORS LogTri = LogTri + "DateMaj" SINON LogTri = LogTri + critère FSI FPOUR ' On remplace Date de Mouvement par DateMaj, car c'est le nom de la colonne qui est attendu pour le tri
SI ((ILogEqpt <> Blanc OU ILogCasier <> Blanc) ET Stock Négatif
ALORS
Afficher ("Équipement ou Casier interdit avec Stock négatif")
Focus sur IlogEqpt
SINON
vVisible = true ' Affiche Patientez...
mvtListe = Sélection des lignes P8_Mouvement telle que :
(ILogEqpt = Blanc OU ILogEqpt = P8_Mouvement.Equipement) ET
(ILogCasier = Blanc OU ILogCasier = P8_Mouvement.Casier) ET
(DateMaj - ILogDebut) >= 0 ET
(ILogFin - DateMaj) >= 0 ET
SI (Stock Négatif ALORS P8_Stock.Stock < 0 OU P8_Equipement.QteStock < 0) FSI
Ajouter Colonne MvtStock (Stock Casier)
Ajouter Colonne MvtEqpt (Stock Équipement)
Ajouter Colonne Détail avec Emoij Loupe
Ajoute Colonne Correction avec Emoij Crayon
vVisible = false ' faire disparaitre fenêtre patientez

Remarquez les colonnes MvtStock et MvtEqpt ainsi que le test du stock négatif. Pour le réaliser, nous aurons besoin de deux jointures, une vers P8_Stock et l'autre vers P8_Equipement.

items Dliste

SUIVANT Nombre de critères
SI 1 ALORS Trier sur le 1er critère,Descending FSI
SI 2 ALORS Trier sur 1er critère,Descending et sur le 2e critère,Descending FSI
DEFAUT Trier sur le 1er critère,Descending, sur le 2e critère,Descending et sur le 3e critère,Descending FDEFAUT
FSUIVANT

OnSelect de l’icône loupe (DListe - Détail)

VEquipement = Trouver P8_equipement quand Equipement=Équipement sélectionné de DListe
vDetail = true ' On affiche la popup détail
vDisabled = Disabled ' On rend indisponibles tous les contrôles permettant une saisie

OnSelect de l’icône crayon (DListe - Correction)

vEdit=true ' On rend visible la popup de correction
vDisabled = Disabled ' On rend indisponibles tous les contrôles permettant une saisie
Effacer INStock
Focus à INStock

OnSelect de l’icône X de la popup Détail

vDetail = false ' Rend invisible la popup
vDisabled = Edit ' Rend disponibles les contrôles de saisie

OnSelect du bouton du popup de correction

SI (INStock est numérique) ALORS
Activer l'icône ICloseCor
vLog = "X" ' Autorise la mise à jour
Aller vers EIOIMaj (Casier sélectionné de DListe,Équipement de P8_Equipement,Quantité renseignée,"I") ' Va vers l'écran de Mise à jour avec le type I(nventaire)
SINON
Afficher ("La quantité doit être numérique")
FSI

OnSelect de l’icône X de la popup Correction

vEdit = false ' Fermer la popup de correction
vDisabled = Edit ' Rend disponible les contrôles de saisie

V-K-4-b - Powerapps

OnVisible

UpdateContext({vDisabled:DisplayMode.Edit});;
UpdateContext({vEdit:false});;
UpdateContext({vDetail:false});;
SetFocus(ILogEqpt);;
UpdateContext({vVisible:false});;
If(ILog.Text = "X";UpdateContext({vLog:Blank()});;
Select(BListe))

OnSelect de la flèche gauche

Reset(ILogTri);;
Reset(ILogFin);;
Reset(ILogDebut);;
Reset(ILogCasier);;
Reset(ILogEqpt);;
UpdateContext({vLog:Blank()});;
Clear(mvtLste);;
Clear(mvtListe);;
Navigate(EMenu)

OnSelect de BListe

ClearCollect(LogTri;
ForAll(ILogTri.SelectedItems;
If(Value="Date de Mouvement";{triValue:"DateMaj"};{triValue:Value})));;
If((Not IsBlank(ILogEqpt.Text) || Not IsBlank(ILogCasier.Text))  && ILogStock.SelectedText.Value = "Oui";Notify("Equipement ou Casier interdit avec Stock négatif";Error);SetFocus(ILogEqpt);
UpdateContext({vVisible:true});;
ClearCollect(mvtListe;
AddColumns(ClearCollect(mvtLste;
Filter(AddColumns('[Power].[P8_mouvement]' As Mvt;"MvtStock";LookUp('[Power].[P8_stock]' As Stock;Mvt.Equipement=Stock.Equipement And Mvt.Casier=Stock.Casier;Stock.Stock);"MvtEqpt";LookUp('[Power].[P8_equipement]' As Eqpt;Mvt.Equipement=Eqpt.Equipement;Eqpt.QteStock));
(IsBlank(ILogEqpt.Text) || Equipement=Value(ILogEqpt.Text)) &&
(IsBlank(ILogCasier.Text) || Upper(Casier) = Upper(ILogCasier.Text)) &&DateDiff(ILogDebut.SelectedDate;DateMaj) >= 0 &&
DateDiff(DateMaj;ILogFin.SelectedDate) >= 0  &&
If(ILogStock.SelectedText.Value = "Oui";MvtStock <= 0 || MvtEqpt <= 0;1=1)));
"Détail";"????"; "Correction";"??"));; UpdateContext({vVisible:false}))

MvtStock est obtenu grâce à la jointure entre P8_Mouvement et P8_Stock.
MvtEqpt est obtenu grâce à la jointure entre P8_Mouvement et P8_Equipement.
Remarquez l'utilisation de As qui lève l’ambiguïté entre le casier de P8_Mouvement et celui de P8_Stock par exemple.
Pensez à toujours utiliser As et un alias quand vous êtes dans une situation ambiguë comme ici.

items Dliste

Switch (CountRows(LogTri);
1;SortByColumns(mvtListe;First(LogTri).triValue;Descending);
2;SortByColumns(mvtListe;First(LogTri).triValue;Descending;Last(LogTri).triValue;Descending);
SortByColumns(mvtListe;First(LogTri).triValue;Descending;Last(FirstN(LogTri;2)).triValue;Descending;Last(LogTri).triValue;Descending))

Pour atteindre le 1er élément d'une collection, c'est l'instruction First.
Le dernier, c'est Last, mais comment atteindre un élément intermédiaire ?
Un solution consiste à créer une collection dont le dernier élément est celui recherché grâce à FirstN. Il suffit ensuite d'utiliser Last.
Ici nous cherchons le deuxième critère de tri quand il y en a trois. On utilise donc Last(FisrtN(liste critères,2))

OnSelect de l’icône loupe (DListe - Détail)

UpdateContext({VEquipement:LookUp('[Power].[P8_equipement]';Equipement=DListe.Selected.Equipement)});;
UpdateContext({vDetail:true});;
UpdateContext({vDisabled:DisplayMode.Disabled})

Cliquer sur une ligne, dans une DataTable la sélectionne et donne accès à toutes les colonnes concernées

OnSelect de l’icône crayon (DListe - Correction)

UpdateContext({vEdit:true});;
UpdateContext({vDisabled:DisplayMode.Disabled});;
Reset(INStock);;
SetFocus(INStock)

OnSelect de l’icône X de la popup Détail

UpdateContext({vDetail:false});;
UpdateContext({vDisabled:DisplayMode.Edit})

OnSelect du bouton du popup de correction

If (IsNumeric(INStock.Text);
Select(ICloseCor);;
UpdateContext({vLog:"X"});;
Navigate(EIOIMaj;Fade;{rCasier:DListe.Selected.Casier;rEqpt:Text(DListe.Selected.Equipement);rQte:INStock.Text;rType:"I"});
Notify("La quantité doit être numérique";Error))

Remarquez que rendre invisible un contrôle n'interdit pas à celui-ci de continuer son exécution

OnSelect de l’icône X de la popup Correction

UpdateContext({vEdit:false});;
UpdateContext({vDisabled:DisplayMode.Edit})

V-K-4-c - Nota Bene

Résumons les instructions notables : ForAll qui permet de boucler sur l'ensemble d'une collection.
First, FirstN, Last, LastN qui permettent d'obtenir, dans une collection, une ligne précise. La combinaison de ces instructions est l'équivalent de l'indice dans un tableau. Associé à une table SQL, c'est l'équivalent de TOP N.
Comme montré ci-dessus, le système est assez souple pour « créer » la liste voulue en combinant Collect,Filter,AddColumns,LookUp.

V-K-4-d - Test

Test

Résultat

Entrez un équipement et sélectionnez Stock Négatif

Message « Équipement ou Casier interdit avec Stock négatif »

Entrez un équipement non existant et sélectionnez Non Stock Négatif

Liste vide

Entrez un équipement existant et sélectionnez Non Stock Négatif

Liste des mouvements

Sélectionnez une icône loupe

La popup détail apparaît, fermez celle-ci

Sélectionnez une icône crayon

La popup correction apparaît

Entrez une quantité non numérique et confirmez

Message « La quantité doit être numérique »

Entrez une quantité numérique et confirmez

Mise à jour du stock, fermeture popup et rafraîchissement de la liste

Retour à EMenu

Affichage EMenu

Pour lancer le test, mettez-vous sur App puis PF5 ou utilisez l'icône :> en haut à droite de l'écran.
En appuyant sur ALT, vous basculez en mode Test, ce qui permet de tester les contrôles un à un.

VI - Pièges à éviter pour développer avec PowerApps

Avant de se lancer dans le développement, il faut tout d’abord s’assurer que l’application cible ne présente pas de difficultés comme l’appel à un tiers (je pense, par exemple, à un accès MainFrame). D’autre part, comme cet outil est « Screen driven », il faut s’assurer que l’analyse fonctionnelle est correctement faite et que l’analyse technique a bien décrit les différentes fonctions.

Enfin, et c’est le plus important, il faut que la personne qui fera le développement soit rigoureuse et documente son code. PowerApps tend à uniformiser celui-ci en « obligeant » à écrire dans des cases (OnSelect, OnVisible…). Aussi, toute déviation par rapport à cette norme rend la maintenance compliquée. D’autre part, on a vu qu’il était possible d’imbriquer des instructions. Cette méthode peut rendre illisible ou/et non modifiable le code. Pour finir, l’éditeur ne colorie pas la syntaxe et devient vite confus quand le code est long. De plus, la séparation par des ; pour les IF THEN ELSE ajoute à cette confusion. Il est donc nécessaire d’avoir, « à côté », une documentation en clair qui explicite le code et donne les flux Ecrans. Cette documentation sera, bien sûr, mise à jour au fur et à mesure des évolutions. Pour toutes ces raisons, un agent peu rigoureux produira un code qui fonctionnera, mais dont la maintenance sera infaisable. (Ceux qui connaissent MSACCESS et qui ont dû maintenir des programmes « Métier » savent de quoi je parle.)

VII - En guise de conclusion

Nous voici arrivés à la fin de notre application de logistique en n'utilisant que les instructions présentes dans la documentation Microsoft, sans faire appel à des Flow ou composants particuliers et sans faire appel, non plus, à des connaissances préalables. Ceci et sa courbe d'apprentissage assez plate pour que des non-spécialistes IT puissent se l'approprier grâce à son éditeur WysWyg et son langage simple montrent que PowerApps est à sa place, dans une entreprise, pour le développement d’applications WEB simples avec, à la clé, un gain de ressources notable (soit on peut déléguer à un débutant, voire à un utilisateur un peu IT, soit on gagnera du temps, soit les deux).

Bien sûr, cet outil n'est pas magique et ne peut pas remplacer, dans des projets complexes, des techniques comme J2EE. D'autre part les temps de réponse sont plutôt mauvais et interdisent son utilisation sur des tables volumineuses.

J'ai aimé : sa simplicité de prise en main, l'éditeur wysiwyg, le côté « LEGO » et la promesse Low Cost assez bien tenue.
Je n'ai pas aimé : la lenteur des recherches en table, la fenêtre d'édition vite confuse, les messages d'erreurs parfois abscons.
J'ai détesté : le côté « tout payant », y compris le support d'outils natifs comme OleDb et ODBC.

VIII - Et la suite ?

Ceci conclut la 1re partie de ce tutoriel.
Dans la seconde partie, nous aborderons les composants et les FLOW.

IX - Remerciements

Je voudrais dire merci à :

- Malick de m’avoir guidé pour la publication de ce tutoriel ;

- Gaby277 pour ses remarques ;

- Claude Leloup pour la relecture orthographique.