Gestion des erreurs

Remarque

Le comportement décrit dans cet article n’est disponible que lorsque la fonctionnalité de version préliminaire Gestion des erreurs au niveau de la formule dans Paramètres>Fonctionnalités à venir>Version préliminaire est activée. Pour plus d’informations, voir : Contrôle des fonctionnalités activées

Les erreurs arrivent. Les réseaux tombent en panne, le stockage se remplit, des valeurs inattendues affluent. Il est important que votre logique continue à fonctionner correctement face à des problèmes potentiels.

Par défaut, les erreurs passent par les formules d’une application et sont signalées à l’utilisateur final de l’application. Ainsi, l’utilisateur final sait que quelque chose d’inattendu s’est produit, il peut éventuellement résoudre le problème lui-même avec une autre entrée, ou il peut signaler le problème au propriétaire de l’application.

En tant que créateur d’applications, vous pouvez contrôler les erreurs dans votre application :

  • Détection et traitement d’une erreur. Si une erreur risque de se produire, les formules de l’application peuvent être écrites de manière à détecter la condition d’erreur et à lancer une nouvelle tentative d’opération. L’utilisateur final n’a pas à s’inquiéter qu’une erreur survienne, car le créateur a tenu compte de cette possibilité. C’est possible grâce aux fonctions IfError, IsError et IsErrorOrBlank dans une formule.
  • Signalement d’une erreur. Si une erreur n’est pas traitée dans la formule où elle est survenue, l’erreur est alors remontée vers le gestionnaire App.OnError. Ici, l’erreur ne peut plus être remplacée car elle s’est déjà produite et fait partie des calculs de la formule. Mais vous pouvez utiliser App.OnError pour contrôler la façon dont l’erreur est signalée à l’utilisateur final, y compris la suppression totale du signalement des erreurs. La fonction App.OnError fournit également un point d’étranglement commun pour les rapports d’erreurs sur l’ensemble de l’application.
  • Création et relance d’une erreur. Enfin, vous pouvez détecter une condition d’erreur avec votre propre logique, une condition qui est spécifique à votre application. Utilisez la fonction Error pour créer et signaler des erreurs personnalisées. La fonction Error permet également de renvoyer une erreur après avoir été interrogée dans IfError ou App.OnError.

Démarrage

Commençons par un exemple simple.

  1. Créez un écran dans une application de canevas Power Apps.
  2. Insérez un contrôle TextInput. Par défaut, il portera le nom de TextInput1.
  3. Insérez un contrôle Label.
  4. Définissez la propriété Text du contrôle Label sur la formule
1/Value( TextInput1.Text )

Bannière d’erreur affichée avec « la valeur ne peut pas être convertie en nombre » pour le contrôle de saisie de texte contenant « Saisie de texte »

Nous obtenons une erreur car le texte par défaut d’un contrôle TextInput est "Text input", qui ne peut pas être converti en nombre. Par défaut, c’est une bonne chose : l’utilisateur final recevra une notification lui indiquant que quelque chose ne fonctionne pas comme prévu dans l’application.

Évidemment, nous ne voulons pas que l’utilisateur soit accueilli par une erreur à chaque fois qu’il lance cette application. "Text input" n’est probablement pas la bonne valeur par défaut pour la zone de saisie de texte. Pour remédier à cela, modifions la propriété Default du contrôle TextInput en :

Blank()

Bannière d’erreur affichée avec « division par zéro »

Hmm, à présent nous avons une erreur différente. Les opérations mathématiques avec des valeurs vides, telles que la division, contraindront la valeur vide à zéro. Et cela provoque maintenant une erreur de division par zéro. Pour y remédier, nous devons décider quel est le comportement approprié pour cette situation dans cette application. La réponse peut être d’afficher vide lorsque la saisie de texte est vide. Nous pouvons accomplir cela en enveloppant notre formule avec la fonction IfError :

IfError( 1/Value( TextInput1.Text ), Blank() )

Aucune bannière d’erreur n’est affichée, une erreur due à une valeur vide a été remplacée par une valeur vide

À présent, l’erreur est remplacée par une valeur valide et la bannière d’erreur a disparu. Mais nous en avons peut-être trop fait : la fonction IfError que nous avons utilisée couvre toutes les erreurs, y compris la saisie d’une mauvaise valeur telle que "hello". Nous pouvons résoudre ce problème en ajustant notre fonction IfError pour ne traiter que le cas de la division par zéro et rejeter toutes les autres erreurs :

IfError( 1/Value( TextInput1.Text ), 
         If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )

Aucune bannière d’erreur n’est affichée, une erreur due spécifiquement à la division par zéro a été remplacée par un blanc, sinon l’erreur est renvoyée à nouveau

Exécutons donc notre application et testons différentes valeurs.

Sans valeur, comme au démarrage de l’appli, il n’y a pas de réponse affichée car la valeur par défaut est vide, mais il n’y a pas non plus d’erreur affichée car la fonction IfError remplace l’erreur de division par zéro.

Aucune réponse affichée et aucune bannière d’erreur

Si nous saisissons un 4, nous obtenons le résultat attendu de 0,25 :

0,25 affiché et aucune bannière d’erreur

Et si nous saisissons quelque chose d’illégal, comme hello, nous obtenons une bannière d’erreur :

aucune valeur affichée ni bannière d’erreur affichée pour l’incapacité de convertir « hello » en un nombre

Il s’agit d’un exemple d’introduction simple. La gestion des erreurs peut se faire de différentes manières, en fonction des besoins de l’application :

  1. Au lieu d’une bannière d’erreur, nous aurions pu afficher "#Error" dans le contrôle d’étiquette avec la formule. Pour garder les types des remplacements compatibles avec le premier argument de la fonction IfError nous devons convertir explicitement le résultat numérique en une chaîne de texte à l’aide de la fonction Text.
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    pas de bannière d’erreur et à la place #Error est affiché comme résultat
  2. Au lieu d’envelopper cette instance spécifique avec la fonction IfError nous aurions pu écrire un gestionnaire App.OnError centralisé. Nous ne pouvons pas remplacer la chaîne affichée par "#Error" car l’erreur s’est déjà produite et la fonction App.OnError est uniquement fournie pour contrôler les rapports.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

Propagation des erreurs

Les erreurs circulent dans les formules comme elles le font dans Excel. Par exemple, dans Excel, si la cellule A1 présente la formule =1/0, alors A1 affichera la valeur d’erreur #DIV0! :

Feuille de calcul Excel avec A1=1/0 et #DIV/0! affiché dans la cellule

Si la cellule A2 fait référence à A1 avec une formule telle que =A1*2, alors l’erreur se propage également à travers cette formule :

Feuille de calcul Excel avec A2=A1*2 et #DIV/0! affiché dans la cellule

L’erreur remplace la valeur qui aurait autrement été calculée. Il n’y a pas de résultat pour la multiplication dans la cellule A2, seulement l’erreur de la division dans A1.

Power Fx fonctionne de la même manière. En général, si une erreur est fournie comme argument d’une fonction ou d’un opérateur, l’opération n’aura pas lieu et l’erreur de saisie sera considérée comme le résultat de l’opération. Par exemple, Mid( Text( 1/0 ), 1, 1 ) renvoie une erreur de division par zéro, car l’erreur la plus interne passe par la fonction Text et la fonction Mid :

Bannière d’erreur indiquant une opération non valide : division par zéro

En général, les erreurs ne transitent pas par les propriétés de contrôle Power Apps. Étendons l’exemple précédent avec un contrôle supplémentaire qui s’affiche si la propriété Text de la première étiquette renvoie un état d’erreur :

Aucune erreur affichée sur le deuxième contrôle d’étiquette

Le fait que les erreurs ne se propagent pas à travers un contrôle ne pose pas de problème, car le système observera les erreurs sur l’entrée de toutes les propriétés du contrôle. L’erreur ne sera pas perdue.

La plupart des fonctions et des opérateurs suivent la règle « erreur d’entrée, erreur de sortie », mais il existe quelques exceptions. Les fonctions IsError, IsErrorOrBlank et IfError sont conçues pour fonctionner avec des erreurs, elles peuvent donc ne pas renvoyer d’erreur même si une erreur leur est transmise.

Observation des erreurs

Les erreurs ne sont pas observées tant que leur valeur n’est pas utilisée.

Par conséquent, les fonctions If et Select peuvent également ne pas renvoyer d’erreur si une erreur leur est transmise. Prenons la formule If( false, 1/0, 3 ). Il y a une erreur de division par zéro présente dans cette formule, mais puisque la fonction If n’emprunte pas cette branche à cause de la valeur false, Power Fx et Power Apps ne signaleront pas d’erreur :

Aucune bannière d’erreur affichée avec la fonction Si dans la propriété Texte de l’étiquette

L’utilisation de la fonction Set avec une erreur ne renverra pas d’erreur au moment où l’erreur est placée dans la variable. Par exemple dans Power Apps, voici une formule dans la fonction App.OnStart qui place une erreur de division par zéro dans la variable x :

Aucune bannière d’erreur affichée avec l’appel de fonction Set dans App.OnStart

Aucune erreur n’est signalée, car la valeur x n’est pas référencée. Cependant, au moment où nous ajoutons un contrôle d’étiquette et définissons sa propriété Text sur x, l’erreur s’affiche :

Bannière d’erreur affichée avec le contrôle d’étiquette renvoyant à la variable x

Vous pouvez observer les erreurs dans une formule avec les fonctions IfError, IsError et IsErrorOrBlank. Grâce à ces fonctions, vous pouvez renvoyer une autre valeur, prendre une autre mesure ou modifier l’erreur avant qu’elle ne soit observée et signalée.

Signalement d’erreurs

Après avoir observé une erreur, l’étape suivante consiste à signaler l’erreur à l’utilisateur final.

Contrairement à Excel, il n’y a pas toujours un endroit pratique pour afficher le résultat d’une erreur, car le résultat d’une formule peut piloter une propriété telle que les coordonnées X et Y d’un contrôle pour lequel il n’y a pas d’endroit pratique pour afficher du texte. Chaque hôte Power Fx contrôle la manière dont les erreurs sont finalement affichées à l’utilisateur final et le degré de contrôle que le créateur a sur ce processus. Dans Power Apps, une bannière d’erreur s’affiche et la fonction App.OnError est utilisée pour contrôler la manière dont l’erreur est signalée.

Il est important de noter que la fonction App.OnError ne peut pas remplacer l’erreur de la même manière que la fonction IfError. Au moment où la fonction App.OnError est exécutée, l’erreur s’est déjà produite et le résultat s’est propagé à travers d’autres formules. La fonction App.OnError contrôle uniquement la manière dont l’erreur est signalée à l’utilisateur final et fournit un hook permettant au créateur de consigner l’erreur s’il le souhaite.

Les variables d’étendue FirstError et AllErrors fournissent des informations contextuelles sur l’erreur ou les erreurs. Cela fournit des informations sur le type d’erreur, l’origine de l’erreur et l’endroit où elle a été observée.

Arrêt après une erreur

Les formules de comportement prennent en charge l’action, la modification des bases de données et le changement d’état. Ces formules permettent d’effectuer plusieurs actions dans une séquence à l’aide de l’opérateur de chaînage ; (ou ;; selon les paramètres régionaux).

Dans ce cas, par exemple, le contrôle de grille affiche ce qui se trouve dans la table T. Chaque bouton sélectionné modifie l’état dans cette table avec deux appels de la fonction Patch :

Animation montrant les deux enregistrements de la table T mis à jour avec des nombres aléatoires après chaque clic sur un bouton

Dans une formule de comportement chaîné, les actions ne s’arrêtent pas après la première erreur. Modifions notre exemple pour transmettre un numéro d’index invalide dans le premier appel à la fonction Patch. Le deuxième appel à la fonction Patch continue malgré cette erreur précédente. La première erreur est signalée à l’utilisateur final et affichée comme une erreur dans Studio sur le contrôle :

Animation montrant uniquement le deuxième enregistrement de la table T mis à jour avec des nombres aléatoires après chaque clic sur un bouton, le premier enregistrement entraînant une erreur

La fonction IfError peut être utilisée pour arrêter l’exécution après une erreur. Semblable à la fonction If, le troisième argument de cette fonction fournit un emplacement pour placer des actions qui ne doivent être exécutées qu’en l’absence d’erreur :

Animation ne montrant aucune modification de l’un ou l’autre des enregistrements de la table T, car l’erreur IfError empêche la deuxième opération de se terminer après une erreur

Si une erreur survient pendant l’une des itérations de la fonction ForAll, le reste des itérations ne s’arrête pas. La fonction ForAll est conçue pour exécuter chaque itération indépendamment, permettant une exécution parallèle. Lorsque la fonction ForAll prend fin, une erreur est renvoyée, qui contient toutes les erreurs rencontrées (en examinant AllErrors dans la fonction IfError ou App.OnError).

Par exemple, dans la formule suivante, la fonction ForAll renvoie deux erreurs (pour la division par zéro pour Value de 0, deux fois) et la fonction Collection aura trois enregistrements (pour les cas où Value n’est pas égal à 0) : [1, 2, 3].

Clear( Collection ); 
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );

Travailler avec plusieurs erreurs

Puisqu’une formule de comportement peut exécuter plusieurs actions, elle peut également rencontrer plusieurs erreurs.

Par défaut, la première erreur est signalée à l’utilisateur final. Dans cet exemple, les deux appels à la fonction Patch échouent, le second avec une erreur de division par zéro. Seule la première erreur (à propos de l’index) est affichée à l’utilisateur :

Première erreur d’index affichée dans une bannière d’erreur, la deuxième erreur n’est pas signalée

Les fonctions IfError et App.OnError peuvent accéder à toutes les erreurs rencontrées avec la variable d’étendue AllErrors. Dans ce cas, nous pouvons définir ceci sur une variable globale et examiner les deux erreurs rencontrées. Elles apparaissent dans la table dans l’ordre où elles ont été rencontrées :

Capture des erreurs dans la variable globale PatchErrors où nous pouvons voir les deux erreurs présentes

Plusieurs erreurs peuvent également être renvoyées dans les formules sans comportement. Par exemple, l’utilisation de la fonction Patch avec un lot d’enregistrements à mettre à jour peut renvoyer plusieurs erreurs, une pour chaque enregistrement qui échoue.

Erreurs dans les tables

Comme nous l’avons vu précédemment, les erreurs peuvent être stockées dans des variables. Les erreurs peuvent également être incluses dans des structures de données, telles que des tables. Ceci est important pour qu’une erreur sur un enregistrement ne puisse pas invalider la table entière.

Par exemple, prenons ce contrôle de table de données dans Power Apps :

Table de données montrant une erreur pour le champ Réciproque pour une entrée de 0, ce qui entraîne une erreur de division par zéro

Le calcul dans AddColumns a rencontré une erreur de division par zéro pour l’une des valeurs. Pour cet enregistrement, la colonne Reciprocal a une valeur d’erreur (division par zéro) mais les autres enregistrements n’en ont pas et sont corrects. IsError( Index( output, 2 ) ) renvoie false et IsError( Index( output, 2 ).Value ) renvoie true.

Si une erreur survient lors du filtrage d’une table, l’enregistrement entier est une erreur mais il est tout de même renvoyé dans le résultat afin que l’utilisateur final sache qu’il y avait quelque chose à cet endroit et qu’il y a un problème.

Prenons l’exemple suivant. Ici, la table d’origine ne contient pas d’erreurs, mais le fait de filtrer crée une erreur chaque fois que Value est égale à 0 :

Table de données montrant les erreurs pour deux enregistrements qui n’ont pas pu être traités par les critères de filtre

Les valeurs -5 et -3 sont correctement filtrées. Les valeurs 0 entraînent une erreur dans le traitement du filtre, et il n’est donc pas clair si l’enregistrement doit être inclus ou non dans le résultat. Pour maximiser la transparence pour les utilisateurs finaux et aider les créateurs à déboguer, nous incluons un enregistrement d’erreur à la place de l’original. Dans ce cas, IsError( Index( output, 2 ) ) renvoie true.

Erreurs dans les sources de données

Les fonctions qui modifient les données dans les sources de données, telles que Patch, Collect, Remove, RemoveIf, Update, UpdateIf et SubmitForm signalent les erreurs de deux manières :

  • Chacune de ces fonctions renverra une valeur d’erreur comme résultat de l’opération. Les erreurs peuvent être détectées avec IsError et remplacées ou supprimées avec IfError et App.OnError comme d’habitude.
  • Après l’opération, la fonction Errors renverra également les erreurs des opérations précédentes. Cela peut être utile pour afficher le message d’erreur sur l’écran d’un formulaire sans avoir à capturer l’erreur dans une variable d’état.

Par exemple, cette formule recherche une erreur à partir de la fonction Collect et affiche un message d’erreur personnalisé :

IfError( Collect( Names, { Name: "duplicate" } ),
         Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )

La fonction Errors renvoie également des informations sur les erreurs passées lors des opérations d’exécution. Elle peut être utile pour afficher une erreur sur l’écran d’un formulaire sans avoir à capturer l’erreur dans une variable d’état.

Relancer les erreurs

Parfois, certaines erreurs potentielles sont attendues et peuvent être ignorées en toute sécurité. Dans les fonctions IfError et App.OnError, si une erreur est détectée, elle doit être transmise au gestionnaire supérieur suivant. Vous pouvez relancer l’erreur à l’aide de Error( AllErrors ).

Créer vos propres erreurs

Vous pouvez également créer vos propres erreurs avec la fonction Error.

Si vous créez vos propres erreurs, il est recommandé d’utiliser des valeurs supérieures à 1 000 pour éviter les conflits potentiels avec les futures valeurs d’erreur système.

Valeurs d’enum ErrorKind

enum ErrorKind Valeur Description
AnalysisError 18 Erreur système. Un problème s’est produit avec l’analyse du compilateur.
BadLanguageCode 14 Un code de langue non valide ou non reconnu a été utilisé.
BadRegex 15 Expression régulière non valide. Vérifiez la syntaxe utilisée avec les fonctions IsMatch, Match ou MatchAll.
Conflict 6 L’enregistrement en cours de mise à jour a déjà été modifié à la source et le conflit doit être résolu. Une solution courante consiste à enregistrer les modifications locales, à actualiser l’enregistrement et à réappliquer les modifications.
ConstraintViolated 8 L’enregistrement n’a pas passé un contrôle de contrainte sur le serveur.
CreatePermission 3 L’utilisateur n’a pas l’autorisation de création d’enregistrement pour la source de données. Par exemple, la fonction Collect a été appelée.
DeletePermissions 5 L’utilisateur n’a pas l’autorisation de suppression d’enregistrement pour la source de données. Par exemple, la fonction Remove a été appelée.
Div0 13 Division par zéro.
EditPermissions 4 L’utilisateur n’a pas l’autorisation de création d’enregistrement pour la source de données. Par exemple, la fonction Patch a été appelée.
GeneratedValue 9 Une valeur a été transmise par erreur au serveur pour un champ calculé automatiquement par le serveur.
Usage Non valide 16 Utilisation non valide d’une fonction Souvent, un ou plusieurs des arguments de la fonction sont incorrects ou utilisés de manière non valide.
FileNotFound 17 Le stockage SaveData est introuvable.
InsufficientMemoy 21 Il n’y a pas assez de mémoire ou de stockage sur l’appareil pour l’opération.
Annulation non valide 25 Un argument invalide a été transmis à une fonction.
Internal 26 Erreur système. Il y a eu un problème interne avec l’une des fonctions.
MissingRequired 2 Il manquait un champ d’enregistrement obligatoire.
Network 23 Il y a eu un problème avec les communications du réseau.
None 0 Erreur système. Il n’existe aucune erreur.
Sans objet 27 Aucune valeur n’est disponible. Utile pour différencier une valeur vide qui peut être traitée comme un zéro dans les calculs numériques des valeurs vides qui doivent être signalées comme un problème potentiel si la valeur est utilisée.
NotFound 7 Enregistrement introuvable. Par exemple, l’enregistrement à modifier dans la fonction Patch.
NotSupported 20 Opération non prise en charge par ce lecteur ou cet appareil.
Numérique 24 Une fonction numérique a été utilisée de manière inappropriée. Par exemple, la fonction Sqrt avec la valeur -1.
QuotaExceeded 22 Quota de stockage dépassé.
Valeur readOnly 10 La colonne est en lecture seule et ne peut pas être modifiée.
ReadPermission 19 L’utilisateur n’a pas l’autorisation de lecture d’enregistrement pour la source de données.
Synchroniser 1 Une erreur a été signalée par la source de données. Vérifiez la colonne Message pour plus d’informations.
Inconnu 12 Une erreur d’un genre inconnu a eu lieu.
Validation 11 L’enregistrement n’a pas passé un contrôle de validation.