Error、IfError、IsError、IsBlankOrError 函数
适用于:画布应用 Dataverse 公式列桌面流模型驱动应用 Power Platform CLI
检测错误并提供替代值或执行操作。 创建自定义错误或传递错误。
备注
- 本文介绍的行为仅在设置 > 即将推出的功能 > 预览中的公式级错误管理预览功能打开时才可用。
IfError
IfError 函数会测试值,直到发现错误为止。 如果此函数发现错误,函数将求值,然后返回相应的替换值,并停止进一步的求值。 如果没有发现错误,也可能提供默认值。 IfError 的结构类似于 If 函数的结构:IfError 测试错误,而 If 测试是否为 true。
使用 IfError 将错误替换为有效值,以使下游计算可以继续。 例如,如果用户输入可能导致被零除,请使用此函数:
IfError( 1/x, 0 )
如果 x
的值为零,此公式将返回 0
,因为 1/x
将产生错误。 如果 x
不为零,则返回 1/x
。
停止进一步处理
Patch( DS1, ... );
Patch( DS2, ... )
即使对 DS1
的 Patch 失败,也会尝试对 DS2
运行第二个 Patch 函数。 错误的范围仅限于链接的每个公式。
使用 IfError 来执行操作,并且仅在操作成功后再继续处理。 将 IfError 应用于此示例:
IfError(
Patch( DS1, ... ), Notify( "problem in the first action" ),
Patch( DS2, ... ), Notify( "problem in the second action" )
)
如果 DS1
的 Patch 有问题,则执行第一个 Notify。 不会发生进一步的处理,包括 DS2
的第二个 Patch。 如果第一个 Patch 成功,将执行第二个 Patch。
如果提供,在未发现错误时,将返回可选的 DefaultResult 参数。 如果没有此参数,将返回最后一个 Value 参数。
基于上一个示例构建,可以检查 IfError 的返回值来确定是否存在任何问题:
IfError(
Patch( DS1, ... ), Notify( "problem in the first action" ); false,
Patch( DS2, ... ), Notify( "problem in the second action" ); false,
true
)
类型兼容性
IfError 将返回其参数之一的值。 IfError 可能返回的所有值的类型必须兼容。
在上一个示例中,Patch 将返回与 Replacement 公式或 DefaultResult 所使用的布尔值不兼容的记录。 这样很好,因为在任何情况下,IfError 都不会返回这些 Patch 调用的返回值。
备注
当更改的行为正在进行时,当前 IfError 的所有参数的类型都必须兼容。
在前面介绍的简单示例中:
IfError( 1/x, 0 )
1/x
和 0
的类型是兼容的,因为它们都是数字。 如果不兼容,第二个参数将被强制匹配第一个参数的类型。
当除数为零时,Excel 将显示 #DIV/0!。
考虑将 IfError 替换为以下内容:
IfError( 1/x, "#DIV/0!" )
上面的公式不起作用。 文本字符串 "#DIV/0!"
将被强制转换为 IfError 的第一个参数的类型,即数字。 IfError 的结果仍将是另一个错误,因为文本字符串无法被强制匹配。 作为解决方法,将第一个参数转换为文本字符串,以让 IfError 始终返回文本字符串:
IfError( Text( 1/x ), "#DIV/0!" )
如上所示,如果 Replacement 或 DefaultResult 是错误,IfError 可能返回错误。
FirstError/AllErrors
在替换公式中,可通过 FirstError 记录和 AllErrors 表获得有关所发现的错误的信息。 AllErrors 是一个错误信息记录表,其中的 FirstError 是此表第一个记录的快捷方式。 FirstError 将始终返回与 First( AllErrors ) 相同的值。
错误记录包括:
字段 | 类型 | 说明 |
---|---|---|
Kind | ErrorKind 枚举(数字) | 错误的类别。 |
Message | 文本字符串 | 有关错误的消息,适合显示给最终用户。 |
源 | 文本字符串 | 错误发生的位置,用于报告。 例如,对于绑定到控件属性的公式,其形式为 ControlName.PropertyName。 |
已遵守 | 文本字符串 | 向用户显示错误的位置,用于报告。 例如,对于绑定到控件属性的公式,其形式为 ControlName.PropertyName。 |
详细信息 | 记录 | 有关错误的详细信息。 目前,仅针对网络错误提供详细信息。 此记录包括包含 HTTP 状态代码的 HttpStatusCode,和包含来自连接器或服务的响应正文的 HttpResponse。 |
例如,将以下公式视为 Button 控件的 OnSelect 属性:
Set( a, 1/0 )
此公式在第二个按钮控件的 OnSelect 属性上:
IfError( a, Notify( "Internal error: originated on " & FirstError.Source & ", surfaced on " & FirstError.Observed ) )
当两个按钮按顺序激活时,上面的示例公式将显示以下横幅:
通常,只有一个错误 FirstError 可以充分处理。 但是,在某些情况下可能会返回多个错误。 例如,当使用公式链接运算符或 Concurrent 函数时。 即使在这些情况下,报告 FirstError 也有可能足以揭示问题,而不会向用户过载多个错误。 如果您仍然需要单独处理每个错误,可以使用 AllErrors 表。
IsError
IsError 函数测试错误值。
返回值为布尔值 true 或 false。
使用 IsError 将阻止对错误进行进一步处理。
IsBlankOrError
IsBlankOrError 函数测试是否有空白值或错误值,等效于 Or( IsBlank( X ), IsError( X ) )
。
为现有应用启用错误处理时,考虑将 IsBlank 替换为 IsBlankOrError 以保留现有应用行为。 在添加错误处理之前,空白值用于同时表示数据库中的空值和错误值。 错误处理将两个空白解释分开,这可能会改变继续使用 IsBlank 的现有应用的行为。
返回值为布尔值 true 或 false。
使用 IsBlankOrError 将阻止对错误的任何进一步处理。
使用 Error 函数创建和报告自定义错误。 例如,您可能有逻辑来确定任何给定值对您的上下文是否有效—没有自动检查是否有问题的内容。 您可以创建并返回您自己的错误,包括 Kind 和 Message,使用上述 IfError 函数的相同记录。
在 IfError 的上下文中,使用 Error 函数重新抛出或传递错误。 例如,您在 IfError 中的逻辑可能决定在某些情况下可以安全地忽略错误,但在其他情况下,错误很重要,需要发送。 在 IfError 或 App.OnError 中,使用 Error( FirstError ) 传递错误。
也可以向 Error 函数传递一个错误表,如 AllErrors 表中的错误。 使用 Error( AllErrors ) 重新抛出所有错误,而不只是第一个。
传递给 Error 的空白记录或空表不会导致错误。
语法
Error( ErrorRecord )
Error( ErrorTable )
- ErrorRecord – 必需。 错误消息记录,包括 Kind、Message 和其他字段。 Kind 是必需的。 FirstError 可以直接传递。
- ErrorTable – 必需。 错误信息记录表。 AllErrors 可以直接传递。
IfError( Value1, Replacement1 [, Value2, Replacement2, ... [, DefaultResult ] ] )
- Value(s) – 必需。 测试错误值的公式。
- Replacement(s) – 必需。 匹配的 Value 参数返回错误时要求值的公式和要返回的值。
- DefaultResult – 可选。 公式未发现任何错误时要求值的公式。
IsError( Value )
IsBlankOrError( Value )
- Value – 必需。 要测试的公式。
示例
简单的 IfError
公式 | 描述 | 结果 |
---|---|---|
IfError( 1, 2 ) | 第一个参数不是错误。 函数没有其他错误要检查,也没有默认返回值。 函数返回最后一个求值的 value 参数。 | 1 |
IfError( 1/0, 2 ) | 第一个参数返回一个错误值(由于除数为零)。 函数对第二个参数求值并将其作为结果返回。 | 2 |
IfError( 10, 20, 30 ) | 第一个参数不是错误。 函数没有其他错误要检查,但有默认返回值。 函数返回 DefaultResult 参数。 | 30 |
IfError( 10, 11, 20, 21, 300 ) | 第一个参数 10 不是错误,因此函数不对该参数的对应替换值 11 求值。 第三个参数 20 也不是错误,因此函数不对该参数的对应替换值 21 求值。 第五个参数 300 没有对应的替换值,是默认结果。 函数返回该结果,因为公式中不包含错误。 | 300 |
IfError( 1/0, Notify( "There was an internal problem" ) ) | 第一个参数返回一个错误值(因为除数为零)。 函数对第二个参数求值,并向用户显示一条消息。 IfError 的返回值是 Notify 的返回值,强制转换为与 IfError 的第一个参数相同的类型(数字)。 | 1 |
简单的 IsError
公式 | 描述 | 结果 |
---|---|---|
IsError( 1 ) | 参数不是错误。 | 否 |
IsError( Blank() ) | 参数是空白,但不是错误。 | 否 |
IsError( 1/0 ) | 参数是错误。 | true |
If( IsError( 1/0 ), Notify( "There was an internal problem" ) ) | IsError 的参数返回一个错误值(由于除数为零)。 此函数返回 true,这会导致 If 使用 Notify 函数向用户显示消息。 If 的返回值是 Notify 的返回值,强制转换为与 If 的第一个参数相同的类型(布尔)。 | true |
简单 IsBlankOrError
公式 | 描述 | 结果 |
---|---|---|
IsBlankOrError( 1 ) | 参数不是错误或空白。 | 否 |
IsBlankOrError( Blank() ) | 参数是空白。 | true |
IsBlankOrError( 1/0 ) | 参数是错误。 | true |
简单错误
在此示例中,日期是相对于彼此进行验证的,如果有问题,将会导致错误。
If( StartDate > EndDate,
Error( { Kind: ErrorKind.Validation, Message: "Start Date must be before End Date" } ) )
在此示例中,一些错误被允许传递,而另一些则被阻止并替换为一个值。 在第一种情况下,b 将处于错误状态,因为 Value 函数包含无效参数。 因为公式编写者没有预料到此情况,所以它会被传递,用户会看到它。 在第二种情况下,使用相同的公式,b 的值将为 0,导致除数为零。 在这种情况下,公式编写者可能知道这对于此逻辑是可以接受的,因而阻止错误(不显示横幅),改为返回 -1。
With( {a: 1, b: Value("a")},
IfError( a/b, If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ), -1 ) ) )
// returns an error with Kind = ErrorKind.InvalidArgument
With( {a: 1, b: 0} )
IfError( a/b, If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ), -1 ) ) )
// returns -1
AllErrors 表可以像任何其他表一样进行筛选。 与 Error 函数一起使用时,可以删除预期的错误,保留并报告其余错误。 例如,如果我们知道除数为零在特定上下文中不会成为问题,则可以筛选掉这些错误,使用以下公式保留所有其他错误:
Error( Filter( AllErrors, Kind <> ErrorKind.Div0 ) )
分步操作
添加 Text input 控件,将它命名为 TextInput1(如果默认名称不是这样)。
添加 Label 控件,将它命名为 Label1(如果默认名称不是这样)。
将 Label1 的 Text 属性的公式设置为:
IfError( Value( TextInput1.Text ), -1 )
在 TextInput1 中,输入 1234。
Label1 将显示值 1234,因为这是对 Value 函数的有效输入。
在 TextInput1 中,输入 ToInfinity。
Label1 将显示值 -1,因为这不是对 Value 函数的有效输入。 在未使用 IfError 包装 Value 函数的情况下,标签将不会显示任何值,因为错误值被视为空白。