Gestione degli errori

Nota

Il comportamento descritto in questo articolo è disponibile solo quando la funzionalità di anteprima Gestione errori a livello di formula in Impostazioni>Funzionalità in arrivo>Anteprima è attivata. Altre informazioni: Controllo delle funzionalità abilitate

Gli errori accadono. Le reti subiscono interruzioni, lo spazio di archiviazione si esaurisce e si introducono valori imprevisti. È importante che la logica continui a funzionare correttamente davanti a potenziali problemi.

Per impostazione predefinita, gli errori passano attraverso le formule di un'app e vengono segnalati all'utente finale dell'app. In questo modo, l'utente finale sa che si è verificato un imprevisto, può potenzialmente risolvere il problema da solo con un input diverso oppure può segnalare il problema al proprietario dell'app.

In qualità di autore di app, puoi assumere il controllo degli errori nell'app:

  • Rilevando e gestendo un errore. Se esiste la possibilità che si verifichi un errore, è possibile scrivere le formule dell'app per rilevare la condizione di errore e riprovare l'operazione. L'utente finale non deve preoccuparsi che si sia verificato un errore perché l'autore ha messo in conto la possibilità. Questa operazione viene eseguita con le funzioni IfError, IsError e IsErrorOrBlank all'interno di una formula.
  • Segnalando un errore. Se un errore non viene gestito nella formula in cui è stato rilevato, l'errore viene riportato al gestore App.OnError. In questo caso l'errore non può più essere sostituito poiché si è già verificato e fa parte dei calcoli della formula. Tuttavia, puoi usare App.OnError per controllare il modo in cui l'errore viene segnalato all'utente finale, inclusa la soppressione totale della segnalazione dell'errore. App.OnError rappresenta anche un collo di bottiglia per la gestione degli errori nell'intera app.
  • Creando e rigenerando un errore. Infine, puoi rilevare una condizione di errore con la tua logica, una condizione specifica dell'app. Usa la funzione Error per creare errori personalizzati. La funzione Error viene anche usata per rigenerare un errore dopo l'interrogazione in IfError o App.OnError.

Introduzione

Iniziamo con un semplice esempio.

  1. Crea una nuova schermata in un'app canvas Power Apps.
  2. Inserisci un controllo TextInput. Il nome predefinito sarà TextInput1.
  3. Inserisci un controllo Label.
  4. Imposta la proprietà Text del controllo Label sulla formula
1/Value( TextInput1.Text )

Banner di errore visualizzato con

Si è verificato un errore perché il testo predefinito di un controllo TextInput è "Text input", convertibile in un numero. Per impostazione predefinita, questa è una buona cosa: l'utente finale riceverà una notifica che qualcosa non funziona come previsto nell'app.

Ovviamente, non vogliamo che l'utente riceva un errore ogni volta che avvia questa app. Probabilmente, "Text input" non è il controllo predefinito giusto per la casella di testo. Per risolvere l'errore, cambiamo la proprietà Default del controllo TextInput su:

Blank()

Banner di errore visualizzato con

Ora abbiamo un errore diverso. Le operazioni matematiche con blank, ad esempio la divisione, vincoleranno il valore blank a zero. E questo ora sta causando un errore di divisione per zero. Per risolvere l'errore, dobbiamo individuare il comportamento appropriato per questa situazione in questa app. La risposta potrebbe consistere nel mostrare blank quando l'input di testo è blank. Possiamo eseguire questa operazione eseguendo il wrapping della formula con la funzione IfError:

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

Nessun banner di errore visualizzato, un errore dovuto a un valore vuoto è stato sostituito con uno spazio

Ora l'errore viene sostituito da un valore valido e il banner scompare. Forse non l'abbiamo precisato, ma IfError che abbiamo usato copre tutti gli errori, inclusa la digitazione di un valore non valido come "hello". Possiamo gestire questo problema regolando IfError per gestire solo il caso della divisione per zero e rigenerando tutti gli altri errori:

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

Nessun banner di errore visualizzato, un errore dovuto specificamente alla divisione per zero è stato sostituito da uno spazio, altrimenti l'errore viene rigenerato

Eseguiamo l'app e proviamo valori diversi.

Senza valori, ad esempio all'avvio dell'app, non viene visualizzata alcuna risposta poiché il valore predefinito è blank, ma non vengono visualizzati errori poiché IfError sostituisce l'errore di divisione per zero.

Nessuna risposta visualizzata e nessun banner di errore

Se digitiamo un 4, otteniamo il risultato previsto di 0,25:

0,25 visualizzato e nessun banner di errore

E se digitiamo qualcosa di non valido, ad esempio hello, riceveremo un banner di errore:

nessun valore visualizzato e banner di errore mostrato per l'impossibilità di convertire

Questo è un semplice esempio introduttivo. La gestione degli errori può essere eseguita in modi diversi, a seconda delle esigenze dell'app:

  1. Anziché un banner di errore, avremmo potuto mostrare "#Error" nel controllo label con la formula. Per mantenere i tipi delle sostituzioni compatibili con il primo argomento su IfError, dobbiamo convertire in modo esplicito il risultato numerico in una stringa di testo con la funzione Text.
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    nessun banner di errore e viene mostrato #Error come risultato
  2. Anziché eseguire il wrapping di questa istanza specifica con IfError, avremmo potuto scrivere un gestore App.OnError centralizzato. Non possiamo sostituire la stringa mostrata con "#Error" poiché l'errore si è già verificato e App.OnError viene fornito solo per controllare la segnalazione.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

Propagazione degli errori

Gli errori passano attraverso le formule proprio come avviene in Excel. In Excel, ad esempio, se la cella A1 contiene la formula =1/0, A1 visualizzerà il valore dell'errore #DIV0!:

Foglio di calcolo di Excel con A1=1/0 e #DIV/0! mostrato nella cella

Se la cella A2 si riferisce a A1 con una formula come =A1*2, l'errore si propaga anche attraverso quella formula:

Foglio di calcolo di Excel con A2=A1*2 e #DIV/0! mostrato nella cella

L'errore sostituisce il valore che sarebbe stato altrimenti calcolato. Non vi è alcun risultato per la moltiplicazione nella cella A2, solo l'errore della divisione in A1.

Power Fx funziona allo stesso modo. In generale, se viene fornito un errore come argomento di una funzione o di un operatore, l'operazione non avrà luogo e l'errore di input passerà come il risultato dell'operazione. Ad esempio, Mid( Text( 1/0 ), 1, 1 ) restituirà un errore di divisione per zero, poiché l'errore più interno passa attraverso la funzione Text e la funzione Mid:

Banner di errore che mostra un'operazione non valida: divisione per zero

In generale, gli errori non passano attraverso le proprietà di controllo di Power Apps. Estendiamo l'esempio precedente con un controllo aggiuntivo che mostra se la proprietà Text della prima etichetta è uno stato di errore:

Nessun errore mostrato sul secondo controllo di etichetta

È opportuno che gli errori non si propaghino attraverso un controllo perché il sistema osserverà gli errori sull'input a tutte le proprietà del controllo. L'errore non andrà perso.

La maggior parte delle funzioni e degli operatori segue la regola "errore in entrata, errore in uscita", ma ci sono alcune eccezioni. Le funzioni IsError, IsErrorOrBlank e IfError sono progettate per gestire gli errori in modo che non ne venga restituito uno anche se uno passa.

Osservazione degli errori

Gli errori non vengono osservati finché non viene usato il relativo valore.

Di conseguenza, le funzioni If e Select potrebbero anche non restituire un errore se ne passa uno. Considera la formula If( false, 1/0, 3 ). In questa formula è presente un errore di divisione per zero, ma poiché If non assume quel ramo a causa di false, Power Fx e Power Apps non segnaleranno un errore:

Nessun banner di errore visualizzato con la funzione If nella proprietà Text dell'etichetta

Se si usa la funzione Set con un errore, l'errore non verrà segnalato al punto in cui era stato inserito nella variabile. Ad esempio in Power Apps, ecco una formula in App.OnStart che inserisce un errore di divisione per zero nella variabile x:

Nessun banner di errore mostrato con Imposta chiamata di funzione in App.OnStart

Non viene segnalato alcun errore perché non si fa riferimento a x. Tuttavia, nel momento in cui aggiungiamo un controllo label e ne impostiamo la proprietà Text su x, viene visualizzato l'errore:

Banner di errore visualizzato con controllo di etichetta che fa riferimento alla variabile x

Puoi osservare errori all'interno di una formula con le funzioni IfError, IsError e IsErrorOrBlank. Con queste funzioni puoi restituire un valore alternativo, eseguire un'azione alternativa o modificare l'errore prima che venga osservato e segnalato.

Segnalazione degli errori

Dopo aver osservato un errore, il passaggio successivo consiste nel segnalarlo all'utente finale.

A differenza di Excel, non è sempre disponibile una posizione pratica per mostrare un risultato di errore, poiché il risultato di una formula potrebbe generare una proprietà come le coordinate X e Y di un controllo per il quale non esiste una posizione pratica per mostrare del testo. Ogni host Power Fx controlla il modo in cui gli errori vengono mostrati all'utente finale e quanto controllo ha l'autore su questo processo. In Power Apps viene mostrato un banner di errore e App.OnError viene usato per controllare il modo in cui viene segnalato l'errore.

È importante notare che App.OnError non può sostituire l'errore nello stesso modo di IfError. Nel punto in cui App.OnError viene eseguito, l'errore si è già verificato e il risultato si è propagato ad altre formule. App.OnError controlla solo il modo in cui l'errore viene segnalato all'utente finale e fornisce un hook all'autore per registrare l'errore, se lo desidera.

Le variabili di ambito FirstError e AllErrors forniscono informazioni di contesto sull'errore o gli errori. Fornisce informazioni sul tipo di errore, sulla relativa origine e sul punto in cui è stato osservato.

Interruzione dopo un errore

Le formule di comportamento supportano l'azione, la modifica di database e il cambiamento di stato. Queste formule consentono di eseguire più di un'azione in sequenza usando l'operatore di concatenamento ; (o ;; a seconda delle impostazioni locali).

In questo caso, ad esempio, il controllo grid mostra il contenuto della tabella T. Ogni selezione di pulsante cambia lo stato in questa tabella con due chiamate Patch:

Animazione che mostra i due record nella tabella T che vengono aggiornati con numeri casuali dopo ogni clic del pulsante

In una formula di comportamento concatenato, le azioni non si interrompono dopo il primo errore. Modifichiamo l'esempio per passare un numero di indice non valido nella prima chiamata Patch. La seconda chiamata Patch continua nonostante l'errore precedente. Il primo errore viene segnalato all'utente finale e mostrato come tale in Studio sul controllo:

Animazione che mostra solo il secondo record nella tabella T che viene aggiornato con numeri casuali dopo ogni clic del pulsante, il primo record genera un errore

IfError può essere usato per interrompere l'esecuzione dopo un errore. Analogamente alla funzione If, il terzo argomento di questa funzione fornisce un punto in cui inserire le azioni da eseguire solo se non si verificano errori:

Animazione che non mostra modifiche a nessuno dei due record nella tabella T, perché IfError impedisce il completamento della seconda operazione dopo un errore

Se si verifica un errore durante una delle iterazioni di ForAll, le iterazioni rimanenti non si interrompono. ForAll è progettato per eseguire ogni iterazione in modo indipendente, consentendo l'esecuzione parallela. Al completamento di ForAll, viene restituito un errore, che contiene tutti gli errori rilevati (esaminando AllErrors in IfError o App.OnError).

Ad esempio, la seguente formula restituirà ForAll con due errori (per la divisione per zero per Value di 0, due volte) e Collection conterrà tre record (per quando Value non è 0): [1, 2, 3].

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

Gestione di più errori

Poiché una formula di comportamento può eseguire più di un'azione, può anche rilevare più di un errore.

Per impostazione predefinita, il primo errore viene segnalato all'utente finale. In questo esempio, entrambe le chiamate Patch avranno esito negativo, la seconda con un errore di divisione per zero. All'utente viene mostrato solo il primo errore (sull'indice):

Il primo errore di indice viene visualizzato in un banner di errore, il secondo errore non viene segnalato

La funzione IfError e App.OnError possono accedere a tutti gli errori rilevati con la variabile di ambito AllErrors. In questo caso, possiamo impostarlo su una variabile globale e osservare gli errori rilevati. Appaiono nella tabella nello stesso ordine in cui sono stati rilevati:

Acquisizione degli errori nella variabile globale PatchErrors dove possiamo vedere che sono presenti entrambi gli errori

È possibile che più errori vengano restituiti anche nelle formule non di comportamento. Ad esempio, l'uso della funzione Patch con un batch di record da aggiornare può restituire più errori, uno per ogni record non riuscito.

Errori nelle tabelle

Come osservato in precedenza, le variabili possono archiviare errori. Gli errori possono anche essere inclusi in strutture dati, ad esempio tabelle. Questo è importante in modo che un errore in qualsiasi record non renda nulla l'intera tabella.

Ad esempio, considera questo controllo data table in Power Apps:

Tabella di dati che mostra un errore per il campo Reciproco per un input di 0, che risulta in un errore di divisione per zero

Il calcolo in AddColumns ha rilevato un errore di divisione per zero per uno dei valori. Per quel record, la colonna Reciprocal ha un valore di errore (divisione per zero), ma gli altri record no, pertanto sono corretti. IsError( Index( output, 2 ) ) restituisce false e IsError( Index( output, 2 ).Value ) restituisce true.

Se si verifica un errore durante il filtro di una tabella, l'intero record è un errore ma viene comunque restituito nel risultato in modo che l'utente finale sappia che c'è un problema.

Usiamo questo esempio. Qui, la tabella originale non ha errori, ma l'azione di filtro crea un errore ogni volta che Value è uguale a 0:

Tabella di dati che mostra gli errori per due record che non possono essere elaborati dai criteri di filtro

I valori -5 e -3 sono filtrati correttamente. I valori 0 restituiscono un errore nell'elaborazione del filtro, pertanto non è chiaro se il record debba essere incluso o meno nel risultato. Per ottimizzare la trasparenza per gli utenti finali e aiutare gli autori a eseguire il debug, includiamo un record di errore al posto dell'originale. In questo caso, IsError( Index( output, 2 ) ) restituisce true.

Errori dell'origine dati

Le funzioni che modificano i dati nelle origini dati, ad esempio Patch, Collect, Remove, RemoveIf, Update, UpdateIf e SubmitForm segnalano gli errori in due modi:

  • Ognuna di queste funzioni restituirà un valore di errore come risultato dell'operazione. Gli errori possono essere rilevati con IsError e sostituiti o eliminati con IfError e App.OnError come abitualmente.
  • Dopo l'operazione, la funzione Errors restituirà anche gli errori delle operazioni precedenti. Ciò può essere utile per visualizzare il messaggio di errore su una schermata modulo senza la necessità di acquisire l'errore in una variabile di stato.

Ad esempio, questa formula verificherà la presenza di un errore da Collect e visualizzerà un messaggio di errore personalizzato:

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

La funzione Errors restituisce anche informazioni sugli errori passati durante le operazioni di runtime. Può essere utile per visualizzare un errore su una schermata modulo senza la necessità di acquisire l'errore in una variabile di stato.

Rigenerazione di errori

Talvolta, sono previsti alcuni potenziali errori che possono essere ignorati. All'interno di IfError e App.OnError, se viene rilevato un errore che deve essere passato al gestore superiore successivo, può essere rigenerato con Error( AllErrors ).

Creazione di propri errori

Puoi anche creare i tuoi errori con la funzione Error.

Se crei i tuoi errori, ti consigliamo di usare valori superiori a 1.000 per evitare potenziali conflitti con futuri valori di errore di sistema.

Valori di enumerazione ErrorKind

Enumerazione ErrorKind Valore Descrizione
AnalysisError 18 Errore di sistema. Si è verificato un problema con l'analisi del compilatore.
BadLanguageCode 14 È stato usato un codice lingua non valido o non riconosciuto.
BadRegex 15 Espressione regolare non valida. Verifica la sintassi usata con le funzioni IsMatch, Match o MatchAll.
Conflitto 6 Il record in corso di aggiornamento è già stato modificato all'origine e il conflitto deve essere risolto. Una soluzione comune consiste nel salvare eventuali modifiche locali, aggiornare il record e riapplicare le modifiche.
ConstraintViolated 8 Il record non ha superato un controllo di vincolo sul server.
CreatePermission 3 L'utente non dispone dell'autorizzazione per la creazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Collect.
DeletePermissions 5 L'utente non dispone dell'autorizzazione per l'eliminazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Remove.
Div0 13 Divisione per zero.
EditPermissions 4 L'utente non dispone dell'autorizzazione per la creazione di record per l'origine dati. Ad esempio, è stata chiamata la funzione Patch.
GeneratedValue 9 È stato erroneamente passato al server un valore per un campo calcolato automaticamente dal server.
InvalidFunctionUsage 16 Utilizzo non valido di una funzione. Spesso uno o più argomenti della funzione non sono corretti o sono usati in modo non valido.
FileNotFound 17 Impossibile trovare l'archiviazione SaveData.
InsufficientMemory 21 La memoria o lo spazio di archiviazione sul dispositivo non è sufficiente per l'operazione.
InvalidArgument 25 Argomento non valido passato a una funzione.
Internal 26 Errore di sistema. Si è verificato un problema interno con una delle funzioni.
MissingRequired 2 Campo obbligatorio di un record mancante.
Network 23 Si è verificato un problema con le comunicazioni di rete.
None 0 Errore di sistema. Nessun errore.
NotApplicable 27 Nessun valore disponibile. Utile per differenziare un valore blank che può essere trattato come uno zero nei calcoli numerici da valori vuoti che devono essere contrassegnati come un potenziale problema se il valore viene usato.
NotFound 7 Impossibile trovare il record. Ad esempio, il record da modificare nella funzione Patch.
NotSupported 20 Operazione non supportata da questo dispositivo o lettore.
Numeric 24 Una funzione numerica è stata usata in modo improprio. Ad esempio, Sqrt con -1.
QuotaExceeded 22 Quota archiviazione superata.
ReadOnlyValue 10 La colonna è di sola lettura e non può essere modificata.
ReadPermission 19 L'utente non dispone dell'autorizzazione per la lettura di record per l'origine dati.
Sync 1 È stato identificato un errore dall'origine dati. Controlla la colonna dei messaggi per altre informazioni.
Unknown 12 Si è verificato un errore di tipo sconosciuto.
Validation 11 Il record non ha superato un controllo di convalida.