Обработка ошибок

Поведение, описанное в этой статье, доступно только в том случае, если включена функция управления ошибками на уровне формулы .

Power Fx поддерживает обработку ошибок на уровне формул. Эта функция включена по умолчанию для всех новых приложений. Однако в некоторых старых приложениях это может быть отключено в параметрах. Оставьте эту функцию включенной.

  1. Откройте приложение Canvas в режиме редактирования.
  2. Перейдите на вкладку Настройки>Обновления>Устаревшие.
  3. Убедитесь, что отключение управления на уровне формул отключено.

Дополнительные сведения см. в разделе "Управление включенными функциями".

Ошибки случаются. Сети выходят из строя, хранилище заполняется, приходят неожиданные значения. Важно, чтобы ваша логика продолжала работать правильно перед лицом потенциальных проблем.

По умолчанию ошибки проходят через формулы приложения и сообщаются конечному пользователю приложения. Таким образом, конечный пользователь знает, что-то непредвиденное произошло. Они могут устранить проблему с другими входными данными или сообщить о проблеме владельцу приложения.

В качестве разработчика приложений запустите управление ошибками в приложении:

  • Обнаружение и обработка ошибки. Если может возникнуть ошибка, напишите формулы приложения, чтобы обнаружить условие ошибки и повторить операцию. Конечному пользователю не нужно беспокоиться о том, что произошла ошибка, потому что создатель учел эту возможность. Зафиксировать ошибку с помощью функций IfError, IsError и IsErrorOrBlank в формуле.
  • Сообщите об ошибке. Если ошибка не обрабатывается в формуле, где она была обнаружена, то она поднимается до обработчика App.OnError. Невозможно заменить ошибку, так как она уже произошла и является частью вычислений формул. Но вы можете использовать App.OnError для управления тем, как ошибка сообщается конечному пользователю, включая полное подавление ее сообщения. App.OnError также предоставляет общую центральную точку для сообщений об ошибках во всем приложении.
  • Создайте и повторно создайте ошибку. Наконец, вы можете обнаружить ошибочное состояние, используя собственную логику, специфичную для вашего приложения. Используйте функцию Error для создания пользовательских ошибок. Используйте функцию Error, чтобы повторно выбросить ошибку после обработки в IfError или App.OnError.

Начало работы

Давайте начнем с простого примера.

  1. Создайте экран в приложении Power Apps Canvas.
  2. Вставьте элемент управления TextInput. По умолчанию используется имя TextInput1.
  3. Вставьте элемент управления Label.
  4. Задайте для свойства Text элемента управления Label формулу
1/Value( TextInput1.Text )

Снимок экрана баннера ошибки, отображающегося с

Вы видите ошибку, потому что текст по умолчанию элемента управления TextInput - это "Text input", который не может быть преобразован в число. По умолчанию это хорошая вещь: конечный пользователь получает уведомление о том, что что-то не работает должным образом в приложении.

Очевидно, что вы не хотите, чтобы ошибка приветствовала пользователя каждый раз, когда они запускают это приложение. Наверное, все равно "Text input" не является правильным значением по умолчанию для поля ввода текста. Чтобы устранить эту проблему, измените свойство Default элемента управления TextInput следующим образом:

Blank()

Снимок экрана: баннер ошибки, отображаемый с

Теперь вы увидите другую ошибку. Математические операции с пустыми значениями, такими как деление, преобразуют пустое значение в ноль. Это значение приводит к ошибке деления на ноль. Чтобы устранить эту проблему, необходимо решить, какое поведение подходит для этой ситуации в этом приложении. Ответ может быть пустым, если текстовое поле пустое. Эту задачу можно выполнить, завернув формулу с помощью функции IfError :

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

Снимок экрана: баннер ошибки не отображается, ошибка из-за пустого значения заменена пустым.

Теперь ошибка заменяется допустимым значением, а баннер ошибок исчезает. Но, возможно, вы перестарались, функция IfError, которую вы использовали, охватывает все ошибки, включая ввод недопустимого значения, например "hello". Эту проблему можно устранить, настроив IfError для обработки только в случае деления на ноль и повторно выбросив все остальные ошибки.

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

Снимок экрана: баннер ошибки не отображается, ошибка из-за деления на ноль заменена пустотой, в противном случае ошибка возникает снова.

Таким образом, запустите приложение и попробуйте несколько различных значений.

При отсутствии значения, когда приложение запускается, ответ не отображается, поскольку значение по умолчанию — пусто, однако также не отображается ошибка, поскольку IfError заменяет ошибку деления на ноль.

Снимок экрана: не отображается ответ и не отображается баннер об ошибке.

Если ввести 4, вы получите ожидаемый результат 0,25:

Снимок экрана, на котором отображается 0.25 и отсутствует баннер об ошибке.

И если вы вводите что-то незаконное, например hello, вы получите баннер об ошибке:

Снимок экрана, показывающий, что значение не отображается, и баннер ошибки, указывающий на невозможность преобразования

Это простой вводный пример. Ошибки можно обрабатывать различными способами в зависимости от потребностей приложения:

  1. Вместо баннера об ошибке можно отобразить "#Error" в элементе управления метками с формулой. Чтобы обеспечить совместимость типов замен с первым аргументом в IfError, необходимо явно преобразовать числовый результат в текстовую строку с помощью функции Text .
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    Снимок экрана: баннер ошибки не отображается и вместо этого #Error отображается в качестве результата.
  2. Вместо оборачивания этого конкретного экземпляра в IfError, можно написать централизованный обработчик App.OnError. Не удается заменить строку, показанную на "#Error", так как ошибка уже произошла, а App.OnError предоставляется только для управления отчетами.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

Распространение ошибок

Ошибки проходят через формулы так же, как и в Excel. Например, в Excel, если ячейка A1 имеет формулу =1/0, то A1 отображает значение #DIV0!ошибки:

Снимок экрана: электронная таблица Excel с A1=1/0 и #DIV/0! отображается в ячейке.

Если ячейка A2 ссылается на A1 с формулой, например =A1*2, ошибка также распространяется через эту формулу.

Снимок экрана: электронная таблица Excel с A2=A1*2 и #DIV/0! отображается в ячейке.

Ошибка заменяет значение, которое формула будет вычислять в противном случае. Результата умножения в ячейке A2 нет, только ошибка деления в A1.

Power Fx работает так же. Как правило, если вы предоставляете ошибку в качестве аргумента функции или оператора, операция не выполняется. Входная ошибка передается в качестве результата операции. Например, Mid( Text( 1/0 ), 1, 1 ) возвращает ошибку деления на ноль, так как самая глубокая ошибка проходит через функцию Text и функцию Mid:

Снимок экрана: баннер ошибки, показывающий недопустимую операцию: деление на ноль.

Как правило, ошибки не передаются через свойства элемента управления Power Apps. Давайте расширим предыдущий пример с другим элементом управления, который отображает, является ли свойство первой метки Text состоянием ошибки:

Снимок экрана, показывающий отсутствие ошибки на втором элементе управления метками.

Это хорошо, что ошибки не распространяются через элемент управления, так как система наблюдает ошибки во входных данных ко всем свойствам элемента управления. Ошибка не исчезла.

Большинство функций и операторов следуют правилу «ошибка на входе, ошибка на выходе», но есть и некоторые исключения. Функции IsError, IsErrorOrOrBlank и IfError предназначены для работы с ошибками, поэтому они могут не возвращать ошибку, даже если он передается в них.

Наблюдение за ошибками

Power Fx не наблюдает ошибок, пока формула не будет использовать значение ошибки.

В результате функции If и Select могут не возвращать ошибку, если она передается. Рассмотрим формулу If( false, 1/0, 3 ). В этой формуле есть ошибка деления на ноль, но поскольку функция If не выбирает эту ветвь из-за условия false, Power Fx и Power Apps не сообщают об ошибке.

Снимок экрана: ошибочный баннер не отображается при использовании функции If в свойстве 'Текст' метки.

Использование функции Set с ошибкой не сообщает об ошибке в точке, когда эта ошибка помещается в переменную. Например, в Power Apps есть формула в App.OnStart, которая помещает ошибку деления на нуль в переменную x:

Снимок экрана: баннер ошибки не отображается с вызовом функции Set в App.OnStart.

Об ошибке не сообщается, поскольку на x не ссылаются. Однако, как только вы добавляете элемент управления меткой и устанавливаете его свойство Text в x, отображается ошибка.

Снимок экрана: баннер ошибки с элементом управления метками, ссылающимся на переменную x.

Ошибки в формуле можно наблюдать с помощью функций IfError, IsError и IsErrorOrOrBlank. Используя эти функции, вы можете вернуть альтернативное значение, выполнить альтернативное действие или изменить ошибку перед наблюдением и отчетом.

Сообщение об ошибках

После того как Power Fx увидит ошибку, следующий шаг — сообщить об ошибке конечному пользователю.

В отличие от Excel, не всегда удобное место для отображения результата ошибки, так как результат формулы может привести к свойству, например координатам X и Y элемента управления, для которого нет удобного места для отображения текста. Каждый хост Power Fx контролирует, как ошибки в конечном итоге отображаются конечному пользователю и насколько разработчик может управлять этим процессом. В Power Apps отображается баннер ошибки, а App.OnError используется для управления способом сообщения об ошибке.

Важно отметить, что App.OnError не может заменить ошибку так же, как функция IfError. На момент выполнения App.OnError произошла ошибка, и результат распространяется по другим формулам. App.OnError контролирует только то, как ошибка сообщается конечному пользователю, и предоставляет создателю возможность зарегистрировать ошибку при необходимости.

Переменные области FirstError и AllErrors предоставляют контекстную информацию об ошибке или ошибках. Этот контекст содержит сведения о типе ошибки, в которой возникла ошибка и где она была замечена.

Остановка после ошибки

Формулы поведения поддерживают выполнение действий, изменение баз данных и изменение состояния. Эти формулы позволяют выполнять несколько действий в последовательности с помощью ; оператора цепочки (или ;; в зависимости от языкового стандарта).

В этом случае элемент управления сеткой показывает, что находится в T таблице. Каждый раз при выборе кнопки изменяется состояние в этой таблице двумя вызовами Patch:

Снимок экрана: анимация с двумя записями в таблице T обновляется случайными числами после нажатия каждой кнопки.

В формуле связанного поведения действия не прекращаются после первой ошибки. Давайте изменим наш пример, чтобы передать недопустимый номер индекса в первом вызове Patch. Второй Patch продолжает работу, несмотря на эту предыдущую ошибку. Первая ошибка сообщается конечному пользователю и отображается как ошибка в Studio на элементе управления:

Снимок экрана: анимация, показывающая только вторую запись в таблице T, обновляемую случайными числами после каждого нажатия кнопки, первая запись приводит к ошибке.

Используйте IfError , чтобы остановить выполнение после ошибки. Подобно функции If, третий аргумент этой функции предоставляет место для размещения действий, которые должны выполняться только в случае отсутствия ошибки:

Снимок экрана: анимация без изменений в любой записи в таблице T, так как IfError не позволяет выполнить вторую операцию после ошибки.

Если во время одной из итерации ForAll возникает ошибка, остальные итерации не останавливаются. ForAll предназначен для независимого выполнения каждой итерации, что позволяет осуществлять параллельное выполнение. После завершения ForAll возвращается ошибка, которая содержит все возникшие ошибки (проверив AllErrors в IfError или App.OnError).

Например, следующая формула приводит к тому, что ForAll возвращает две ошибки (деления на ноль для Value дважды) и Collection содержит три записи (когда Value не 0): [1, 2, 3]

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

Работа с несколькими ошибками

Поскольку формула поведения может выполнять более одного действия, она также может столкнуться с более чем одной ошибкой.

По умолчанию приложение сообщает о первой ошибке конечному пользователю. В этом примере оба вызова Patch завершаются ошибкой, но второй вызов завершается ошибкой деления на ноль. Пользователь видит только первую ошибку, касающуюся индекса.

Снимок экрана: первая ошибка индекса, отображаемая в баннере об ошибке, вторая ошибка не сообщается.

Функция IfError и App.OnError могут получить доступ ко всем ошибкам, возникшим с помощью переменной области AllErrors . В этом случае вы можете задать эту переменную как глобальную и просмотреть обе обнаруженные ошибки. Они отображаются в таблице в том порядке, в котором они возникли:

Снимок экрана записи ошибок в глобальную переменную PatchErrors, где можно увидеть, что обе ошибки присутствуют.

Формулы неопределённого поведения также могут возвращать несколько ошибок. Например, использование функции Patch с пакетом обновляемых записей может возвращать несколько ошибок, по одной на каждую ошибочную запись.

Ошибки в таблицах

Как вы видели ранее, вы можете хранить ошибки в переменных. Также можно включать ошибки внутри стpуктур данных, таких как таблицы. Этот подход важен, так как он гарантирует, что ошибка в любой записи не может сделать всю таблицу недопустимой.

Например, рассмотрим этот элемент управления таблицей данных в Power Apps:

Снимок экрана таблицы данных, показывающей ошибку для поля

Вычисление в AddColumns обнаружило деление по нулевой ошибке для одного из значений. Для этой одной записи в столбце Reciprocal есть значение ошибки (деление на ноль), но в других записях ее нет, и все в порядке. IsError( Index( output, 2 ) ) возвращает false и IsError( Index( output, 2 ).Value ) возвращает true.

Если при фильтрации таблицы возникает ошибка, вся запись является ошибкой. Операция по-прежнему возвращает запись в результате, чтобы конечный пользователь знал, что-то было там, и возникла проблема.

Возьмем этот пример. Здесь в исходной таблице нет ошибок, но акт фильтрации создает ошибку всякий раз, когда Value равно 0:

Снимок экрана: таблица данных с ошибками для двух записей, которые не могут обрабатываться критериями фильтра.

Значения –5 и –3 правильно отфильтрованы. Значения 0 приводят к ошибке при обработке фильтра, поэтому неясно, должна ли запись быть включена в результат или нет. Чтобы максимально повысить прозрачность для конечных пользователей и помочь разработчикам отладки, операция включает запись об ошибке вместо исходного. В этом случае IsError( Index( output, 2 ) ) возвращает значение true.

Ошибки источника данных

Функции, которые изменяют данные в источниках данных, такие как Patch, Collect, Remove, RemoveIf, Update, UpdateIf и SubmitForm, сообщают об ошибках двумя способами:

  • Каждая из этих функций возвращает значение ошибки в результате операции. Ошибки можно обнаруживать с помощью IsError и замены или подавления ошибок с помощью IfError и App.OnError как обычно.
  • После операции функция "Ошибки" также возвращает ошибки для предыдущих операций. Это поведение может быть полезно для отображения сообщения об ошибке на экране формы, не требуя записи ошибки в переменной состояния.

Например, эта формула проверяет ошибку функции Collect и отображает пользовательское сообщение об ошибке.

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

Функция Errors также возвращает информацию о прошлых ошибках во время операций времени выполнения. Это может быть полезно для отображения ошибки на экране формы без необходимости захвата ошибки в переменной состояния.

Повторный вызов ошибок

Иногда вы ожидаете потенциальные ошибки и можете безопасно игнорировать их. Внутри IfError и App.OnError, если обнаружена ошибка, которая должна быть передана следующему более высокому обработчику, повторно выбросьте её с помощью Error( AllErrors ).

Создание собственных ошибок

Вы также можете создать собственные ошибки с помощью функции error .

При создании собственных ошибок используйте значения, превышающие 1000, чтобы избежать потенциальных конфликтов с будущими системными значениями ошибок.

Значения перечисления ErrorKind

Перечисление ErrorKind Ценность Description
AnalysisError 18 Системная ошибка. Существует проблема с анализом компилятора.
НеправильныйКодЯзыка 14 Был использован недопустимый или нераспознанный код языка.
BadRegex 15 Недопустимое регулярное выражение. Проверьте синтаксис, используемый с функциями IsMatch, Match или MatchAll.
Конфликт (Conflict) 6 Запись, которую вы обновляете, уже была изменена в исходном источнике, и вам необходимо разрешить конфликт. Распространенным решением является сохранение любых локальных изменений, обновление записи и повторное применение изменений.
Нарушение ограничения 8 Запись не прошла проверку ограничений на сервере.
СоздатьРазрешение 3 У вас нет разрешения на создание записи для источника данных. Например, была вызвана функция Collect.
УдалитьРазрешения 5 У вас нет разрешения на удаление записи для источника данных. Например, была вызвана функция Remove.
Div0 13 Деление на ноль.
Редактировать разрешения 4 У вас нет разрешения на создание записи для источника данных. Например, была вызвана функция Patch.
СгенерированноеЗначение 9 Значение было ошибочно передано серверу для поля, которое сервер автоматически вычисляет.
НекорректноеИспользованиеФункции 16 Недопустимое использование функции. Часто один или несколько аргументов функции неверны или используются недопустимым образом.
ФайлНеНайден 17 Не удалось найти хранилище SaveData.
НедостаточноПамяти 21 На устройстве недостаточно памяти или хранилища для операции.
НедействительныйАргумент 25 В функцию был передан недопустимый аргумент.
Внутренний 26 Системная ошибка. Существует внутренняя проблема с одной из функций.
ТребуемоеОтсутствует 2 Необходимое поле записи отсутствует.
Сеть 23 Возникла проблема с сетевыми коммуникациями.
нет 0 Системная ошибка. Нет ошибок.
Неприменимо 27 Нет доступных значений. Эта ошибка полезна для отличия пустого значения, которое можно рассматривать как нуль в числовых вычислениях, от пустых значений, которые должны быть помечены как потенциальная проблема, если используется значение.
Не найдено 7 Не удается найти запись. Например, запись, которую необходимо изменить в функции Patch.
NotSupported 20 Операция не поддерживается этим проигрывателем или устройством.
Числовое значение 24 Числовая функция использовалась ненадлежащим образом. Например, Sqrt с аргументом –1.
ПревышенаКвота 22 Превышена квота хранилища.
ReadOnlyValue 10 Столбец доступен только для чтения и не может быть изменен.
РазрешениеНаЧтение 19 У вас нет разрешения на чтение записей для источника данных.
Синхронизация 1 Источник данных сообщил об ошибке. Чтобы узнать больше, просмотрите столбец "Message".
Неизвестно 12 Произошла неизвестная ошибка.
Проверка 11 Запись не прошла проверку.