异常是由程序在运行过程中出现的各种无法预知的错误导致的、当这种错误发生后程序的执行会中断在异常位置而不会继续执行后面的代码。一段好的代码可以从容应对任何异常的情况,保证程序能平稳运行而不崩溃,这就是常说的代码健壮性。想要处理程序运行中的异常除了需要尽可能的预判到所有会出现的情况之外还需有好的机制来处理无法预判的状况。编程语言中一般都会提供一种异常处理机制:
1、定义并抛出异常
2、 获取处理异常。
在M语言中也有类似的机制,接下来我们详细介绍。
M语言的异常及异常标记
M语言中的异常有哪些?常见的异常主要有以下几个方面:
1、函数使用了错误的参数产生的错误
比如 Number.ToText(number) 只能处理数字类型的参数,当参数为其他类型的时候程序会直接报错。
let
result = Number.ToText("1")
in
result
2、操作符操作了不恰当的数据:
比如加号+只能用于数字或时间类型的数据相加,但是当加号两边出现了其他类型的数据的时候程序也会报错
let
result = 1+"1"
in
result
这些黄色区域的错误信息都是由PowerBI提前定义好的,当错误发生后就会直接抛出来展示给我们。
错误信息如何定义呢?其实很简单,使用关键字 error + 错误信息就可以了
举个小例子:
let
a = -1,//定义变量a 假如a初始值为-1,这样就可以抛出异常了
result = if a>0 then a else error "not positive"//这是一个if表达式,当a>0 返回 a的值否则抛出错误
in
result
通过执行结果,我们可以看出系统已经获取到错误信息。但这不是我们想要的,这种情况下代码已经从错误的位置处停止了,也许后续还有很多数据需要处理的数据。因此我们需要让我们写的程序获取错误,而不是由系统获取。接下来我们介绍M语言获取错误的方式方法。
M语言种获取异常的方法
我们想要查看一个表达式是否会抛出异常需要用到try 关键字。用法如下:
try 待测试的表达式
这个表达式运行之后会返回一个记录,当待测试的表达式有异常抛出的时候,记录大概是这个样子的:
[
HasError = true,
Error =
[
Reason = "Expression.Error",
Message = "错误信息", //此处的错误信息即为 error关键字后面所跟的字符串
Detail = null
]
]
当待测试的表达式没有异常抛出的时候,返回的记录是这个样子的
[
HasError = FALSE,
Value = 待测试的表达式正确的结果
]
我们可以将表达式的值赋给一个变量
result = try 待测试的表达式
然后可以通过对result这个记录 进行索引来获取表达式是否错误以及错误信息或者最后的value。
result[HasError]//判断该值为TRUE 还是 FALSE
当result[HasError] 为 TRUE 的时候说明有异常抛出,可以使用 result[Error][Message]来获取错误信息
当result[HasError] 为 FALSE 的时候说明没有异常抛出,可以使用 result[Value]获取表达式的结果
一个小例子:
let Sales =
[
ProductName = "Fishing rod", //产品名称
Revenue = 2000, // 收入
Units = 1000, //数量
UnitPrice = if Units = 0 then error "No Units"
else Revenue / Units //当Units为0的时候抛出异常否则返回均价
],
textUnitPrice = try Number.ToText(Sales[UnitPrice]),
//将均价由数字类型准换为文本类型
Label = "Unit Price: " &
(if textUnitPrice[HasError] then
textUnitPrice[Error][Message]
else
textUnitPrice[Value])
in
Label
上面的示例访问该Sales[UnitPrice]
字段并格式化生成结果的值:
"Unit Price: 2"
如果Units字段为0,则该UnitPrice
字段会抛出一个异常Error,该错误将由try获取处理。结果值将是:
"Unit Price: No Units"
常见的情况是用默认值替换错误。try表达式可以与一个可选的otherwise子句一起使用,以更紧凑、简单的形式实现上述过程:
let Sales =
[
ProductName = "Fishing rod",
Revenue = 2000,
Units = 1000,
UnitPrice = if Units = 0 then error "No Units"
else Revenue / Units
],
textUnitPrice = try Number.ToText(Sales[UnitPrice]) otherwise "No Units",
Label = "Unit Price: " & textUnitPrice
in
Label
这样也可以得到最终的结果而无需去访问并索引 try 的返回值。
需要注意的是M语言中的许多函数、操作符在微软开发的时候就已经定义好了error信息,我们在使用的时候直接使用try 就能获取到表达式的错误信息,小伙伴们还记得前面介绍的 当使用加号 + 将文本与数字相加导致的报错,这报错信息就是开发者已经定义好的。