变量
备注
Microsoft Power Fx 是画布应用公式语言的新名称。 当我们从画布应用中提取语言,将其与其他 Microsoft Power Platform 产品集成并使其作为开放源代码提供时,这些文章还在撰写。 从 Microsoft Power Fx 概述开始,了解对此语言的介绍。
如果您使用过其他编程工具(如 Visual Basic 或 JavaScript),您可能会问:变量在哪里?Microsoft Power Fx 稍有不同,需要不同的方法。 与其在编写公式时使用变量,不如问自己:我会在电子表格中执行哪些操作?
在其他工具中,您可能会显式执行某个计算,然后将结果存储在变量中。 但是,Power Fx 和 Excel 都会在输入数据更改时自动重新计算公式,因此您通常不需要创建和更新变量。 尽可能使用这种方法,您就可以更轻松地创建、了解和维护应用。
某些情况下,需要在 Power Fx 中使用变量,通过添加行为公式扩展 Excel 的模型。 这些公式在特定情况下(例如,用户选择某个按钮)运行。 在行为公式中,设置一个可在其他公式中使用的变量通常很有用。
一般情况下,应避免使用变量。 但有时候,只有使用变量才能获得所需的体验。 当变量出现在设置其值的函数中时,将隐式创建和键入变量。
将 Excel 转换成 Power Fx
Excel
让我们回顾一下 Excel 的工作原理。 单元格可以包含值(例如数字或字符串),也可以包含公式(基于其他单元格的值)。 用户向单元格输入其他值以后,Excel 会自动根据新的值重新计算任何公式。 不需编程即可启用此行为。
在下面的示例中,单元格 A3 设置为公式 A1+A2。 如果 A1 或 A2 更改,A3 会自动重新计算以反映更改。 此行为不需要在公式自身外部进行编码。
Excel 没有变量。 包含公式的单元格的值随输入而更改,但无法记住公式的结果,也无法将结果存储在单元格或任何其他地方。 如果更改某个单元格的值,则整个电子表格都会更改,以前计算出来的值就会丢失。 Excel 用户可以复制和粘贴单元格,但那是在用户的手动控制之下完成的,不可能通过公式来完成。
Power Fx
在 Power Fx 中创建的逻辑的行为与 Excel 很类似。 可以将控件添加到屏幕的任意位置,并根据其在公式中的用途为其命名,不需更新单元格。
例如,在 Power Apps 中,您可以通过添加一个标签控件(名为 Label1)和两个文本输入控件(分别名为 TextInput1 和 TextInput2)在应用中复制 Excel 行为。 如果随后将 Label1 的 Text 属性设置为 TextInput1.Text + TextInput2.Text,则会始终自动显示 TextInput1 和 TextInput2 中的数字之和。
请注意,上图选中的是 Label1 控件,在屏幕顶部的公式栏中显示了其 Text 公式。 在这里,我们可以找到公式 TextInput1.Text + TextInput2.Text。 该公式在这些控件之间创建了一个依赖关系,就像在 Excel 工作簿中的单元格之间创建依赖关系一样。 让我们更改一下 TextInput1 的值:
上图表明 Label1 的公式已自动重新计算,显示新值。
在 Power Fx 中,使用公式不仅可以确定控件的主值,还可以确定属性(例如格式设置)。 在下一示例中,标签的 Color 属性的公式会自动将负值显示为红色。 If 函数看起来应该与 Excel 中的相似:
If( Value(Label1.Text) < 0, Color.Red, Color.Black )
可将公式用于各种场景:
- 启用设备的 GPS 后,地图控件就可以使用公式通过 Location.Latitude 和 Location.Longitude 来显示当前位置。 移动时,地图会自动跟踪您的位置。
- 其他用户可能会更新数据源。 例如,团队中的其他人可能会更新 SharePoint 列表中的项。 刷新数据源时,相关公式会根据更新的数据自动重新计算。 就此示例来说,您可以进一步将库的 Items 属性设置为公式 Filter( SharePointList ),以便自动显示新筛选的记录集。
收益
使用公式生成应用具有很多优点:
- 如果您知道 Excel,您就知道 Power Fx。 二者的模型和公式语言是相同的。
- 如果您使用过其他编程工具,可以试想一下,完成这些示例需要多少代码。 在 Visual Basic 中,需要为每个文本输入控件上发生的更改事件编写事件处理程序。 在每个这样的处理程序中,用于执行计算的代码很冗长,并且可能会出现不同步的情况,或者需要您编写通用子例程。 而在 Power Fx 中,这一切只需一个单行公式即可完成。
- 若要了解 Label1 的文本源自何处,只需查看 Text 属性中的公式即可。 其他方式不会影响该控件的文本。 在传统编程工具中,可以从程序的任何位置通过任何事件处理程序或子例程更改该标签的值。 这就难以跟踪变量的更改时间和位置。
- 如果用户更改了滑块控件,然后又改变了主意,则可将滑块改回其原始值。 这样一来,就好像没有做过任何更改一样:应用所显示的控件值与以前显示的一样。 不需进行分支试验并询问假设性的问题,就像在 Excel 中一样。
如果可以使用公式达到某种效果,则通常会选择使用公式。 让 Power Fx 中的公式引擎为您服务。
了解何时使用变量
让我们将简单的加法器更改一下,使之操作起来就像一台老式的带汇总功能的加法机。 如果选择加按钮,则会将一个数字加到汇总中。 如果选择清除按钮,则会将汇总重置为零。
显示 | 描述 |
---|---|
应用启动时,汇总是 0。 红点表示用户在文本输入框中的手指,用户在框中输入 77。 |
|
用户选择添加按钮。 | |
汇总已加上 77。 用户再次选择添加按钮。 |
|
汇总再次加上 77,结果为 154。 用户选择清除按钮。 |
|
汇总重置为 0。 |
我们的加法机使用了某个 Excel 中不存在的东西:按钮。 在该应用中,不能仅使用公式来计算汇总,因为其值取决于用户采取的一系列操作。 必须手动记录和更新汇总。 大多数编程工具将该信息存储在变量中。
有时候,需要使用变量才能让应用的表现符合预期。 但该方法需注意以下事项:
- 必须手动更新汇总。 自动重新计算在此方面不会为您代劳。
- 不能再根据其他控件的值计算汇总。 汇总结果取决于用户选择加按钮的次数,以及每次操作时文本输入控件中的具体值。 在执行加法计算时,到底是用户输入了 77 并选择加两次,还是用户指定了 24 和 130? 您只知道总和为 154,但无法分辨上述两种过程。
- 可以通过不同的方式来改变总和。 在此示例中,加按钮和清除按钮都可以更新总和。 如果应用表现异常,则到底是哪个按钮引发的问题?
使用全局变量
创建加法机需要一个变量来存储汇总。 可用于 Power Fx 的最简单变量是全局变量。
全局变量的工作方式:
- 使用 Set 函数设置全局变量的值。 Set( MyVar, 1 ) 可将全局变量 MyVar 的值设置为 1。
- 可以通过引用 Set 函数使用的名称来使用全局变量。 在这种情况下,MyVar 将返回 1。
- 全局变量可以存储包括字符串、数字、记录和表在内的任何值。
让我们使用全局变量重新生成加法机:
添加一个文本输入控件,将其命名为 TextInput1,同时添加两个按钮,分别命名为 Button1 和 Button2。
将 Button1 的 Text 属性设置为 "Add",将 Button2 的 Text 属性设置为 "Clear"。
若要在用户选择添加按钮时更新汇总,请将 OnSelect 属性设置为以下公式:
Set( RunningTotal, RunningTotal + TextInput1.Text )
由于 + 运算符,仅存在此公式即可将 RunningTotal 建立为包含数字的全局变量。 您可以在应用中的任意位置引用 RunningTotal。 每当用户打开此应用时,RunningTotal 都有一个空白初始值。
用户第一次选择加按钮且 Set 运行时,RunningTotal 将被设置为值 RunningTotal + TextInput1。
若要在用户选择清除按钮时将汇总设置为 0,请将 OnSelect 属性设置为以下公式:
Set( RunningTotal, 0 )
添加一个 Label 控件,然后将 Text 属性设置为 RunningTotal。
此公式将自动重新计算,为用户显示的 RunningTotal 值随用户选择的按钮而变化。
预览该应用,我们创建的加法机完全符合上述说明。 在文本框中输入数字,然后按几次加按钮。 准备就绪时,使用 Esc 键返回到创作体验。
若要显示全局变量的值,请选择文件菜单,然后在左侧窗格中选择变量。
若要显示其中定义和使用变量的位置,请选择它。
变量类型
Power Fx 具有两种类型的变量:
变量类型 | 作用域 | 说明 | 建立的函数 |
---|---|---|---|
全局变量 | 应用 | 用法最为简单。 包含可从应用程序的任何位置进行引用的数字、文本字符串、布尔值、记录、表等。 | Set |
集合 | 应用 | 包含可从应用任意位置进行引用的一个表。 允许修改表的内容,而不是作为一个整体进行设置。 可以保存到本地设备,以供将来使用。 |
Collect ClearCollect |
当在 Power Apps 中使用时,有第三种类型的变量:
变量类型 | Scope | 描述 | 建立的函数 |
---|---|---|---|
上下文变量 | 屏幕 | 非常适合将值传递到屏幕,与其他语言中的过程的参数非常类似。 仅可以从一个屏幕进行引用。 |
UpdateContext Navigate |
创建和移除变量
当变量出现在 Set、UpdateContext、Navigate、Collect 或 ClearCollect 函数中时,将隐式创建所有变量。 要声明变量及其类型,只需要将其包括在应用中任何位置的任一函数中。 这些函数都不创建变量;他们只是用值填充变量。 您永远不会像在其他编程工具中那样显式声明变量,所有键入都是隐式使用的。
例如,您可能有一个按钮控件,其 OnSelect 公式等于 Set( X, 1 )。 此公式将 X 建立为具有数字类型的变量。 您可以将公式中的 X 用作数字,在打开应用之后在选择按钮之前,该变量的值为空白。 当您选择按钮时,会赋予 X 值 1。
如果您添加了另一个按钮并将其 OnSelect 属性设置为 Set( X, "Hello" ),则会发生错误,因为类型(文本字符串)与前一个 Set 中的类型(数字)不匹配。 变量的所有隐式定义在类型上必须是一致的。 同样,所有这一切都是因为您在公式中提到了 X,而不是因为这些公式中有任何一个在实际运行。
您可以通过删除隐式建立变量的所有 Set、UpdateContext、Navigate、Collect 或 ClearCollect 函数来删除变量。 没有这些函数,变量将不存在。 您还必须删除对变量的任何引用,因为它们会导致错误。
变量生存期和初始值
应用运行时,所有变量都保存在内存中。 应用关闭后,变量保留的值将丢失。
您可以使用 Patch 或 Collect 函数将变量的内容存储在数据源中。 您还可以使用 SaveData 函数将值存储在本地设备上的集合中。
当用户打开应用时,所有变量都会有一个空白初始值。
读取变量
可以使用变量名称读取其值。 例如,您可以使用以下公式定义变量:
Set( Radius, 12 )
然后,您只需在任何可以使用数字的地方使用 Radius,它将被替换为 12:
Pi() * Power( Radius, 2 )
如果为上下文变量指定与全局变量或集合相同的名称,上下文变量优先。 不过,如果您使用消除歧义运算符[@Radius],您仍然可以引用全局变量或集合。
使用上下文变量(仅 Power Apps)
我们来看看如何使用上下文变量而不是全局变量创建加法机。
上下文变量的工作原理:
- 您可以使用 UpdateContext 或 Navigate 函数隐式建立和设置上下文变量。 当应用启动时,所有上下文变量的初始值都将为空白。
- 使用记录创更新上下文变量。 在其他编程工具中,通常使用“=”来赋值,例如“x = 1”。 上下文变量则使用 { x: 1 } 这样的形式。 使用上下文变量时,无需记录语法即可直接使用其名称。
- 也可以在使用 Navigate 函数显示屏幕时设置上下文变量。 如果将屏幕视为一种过程或子例程,则此方法类似于其他编程工具中的参数传递。
- 上下文变量的作用范围仅限于单个屏幕的上下文(Navigate 除外),这也是其得名的原因。 不能超出相应的上下文使用或设置上下文变量。
- 上下文变量可以存储包括字符串、数字、记录和表在内的任何值。
让我们使用一个上下文变量重新生成加法机:
添加一个文本输入控件,将其命名为 TextInput1,同时添加两个按钮,分别命名为 Button1 和 Button2。
将 Button1 的 Text 属性设置为 "Add",将 Button2 的 Text 属性设置为 "Clear"。
若要在用户选择添加按钮时更新汇总,请将 OnSelect 属性设置为以下公式:
UpdateContext( { RunningTotal: RunningTotal + TextInput1.Text } )
由于 + 运算符,仅存在此公式即可将 RunningTotal 建立为包含数字的上下文变量。 您可以在此屏幕中的任意位置引用 RunningTotal。 每当用户打开此应用时,RunningTotal 都有一个空白初始值。
用户第一次选择加按钮且 UpdateContext 运行时,RunningTotal 将被设置为值 RunningTotal + TextInput1。
若要在用户选择清除按钮时将汇总设置为 0,请将 OnSelect 属性设置为以下公式:
UpdateContext( { RunningTotal: 0 } )
同样,UpdateContext 与公式 UpdateContext( { RunningTotal: 0 } ) 一起使用。
添加一个 Label 控件,然后将其 Text 属性设置为 RunningTotal。
此公式将自动重新计算,为用户显示的 RunningTotal 值随用户选择的按钮而变化。
预览该应用,我们创建的加法机完全符合上述说明。 在文本框中输入数字,然后按几次加按钮。 准备就绪时,使用 Esc 键返回到创作体验。
导航到屏幕时,可以设置上下文变量的值。 这对于将“上下文”或“参数”从一个屏幕传递到另一个屏幕很有用。 为了演示此技术,请插入一个屏幕,插入按钮,并将其 OnSelect 属性设置为以下公式:
Navigate( Screen1, None, { RunningTotal: -1000 } )
按住 Alt 键的同时选择此按钮,以显示 Screen1,同时将上下文变量 RunningTotal 设置为 -1000。
若要显示上下文变量的值,请选择文件菜单,然后在左侧窗格中选择变量。
要显示定义和使用上下文变量的位置,请选择它。
使用集合
最后,我们来看一下如何使用集合创建加法机。 由于集合包含一个易于修改的表,我们将使此加法机保留每个值输入时的“纸带”。
集合工作原理:
- 通过使用 ClearCollect 函数创建和设置集合。 可以改用 Collect 函数,但该函数实际上需要另一个变量,而不能替换旧的变量。
- 集合是一种类型的数据源,因此也是表。 若要访问集合中的单个值,请使用 First 函数,并从生成的记录中提取一个字段。 如果使用了单个值和 ClearCollect,则该字段为 Value 字段,如以下示例所示:
First(VariableName).Value
让我们使用集合重新创建加法机:
添加一个文本输入控件(名为 TextInput1)和两个按钮(分别名为 Button1 和 Button2)。
将 Button1 的 Text 属性设置为 "Add",将 Button2 的 Text 属性设置为 "Clear"。
若要在用户选择添加按钮时更新汇总,请将 OnSelect 属性设置为以下公式:
Collect( PaperTape, TextInput1.Text )
仅存在此公式即可将 PaperTape 建立为一个包含单列文本字符串表的集合。 您可以此应用中的任意位置引用 PaperTape。 每当用户打开此应用时,PaperTape 都是一个空表。
当此公式运行时,它会将新值添加到集合末尾。 由于我们添加了一个单值,因此,Collect 会自动将其置于列名为 Value 的单列中,稍后我们将使用它。
若要在用户选择清除按钮时清除纸带,请将其 OnSelect 属性设置为以下公式:
Clear( PaperTape )
若要显示汇总,请添加一个标签,然后将 Text 属性设置为以下公式:
Sum( PaperTape, Value )
若要运行加法机,请按 F5 打开“预览”,在文本输入控件中输入数字,然后选择相应的按钮。
若要返回到默认工作区,请按 Esc 键。
要显示纸带,请插入 Data table 控件,并将其 Items 属性设置为此公式:
PaperTape
在右侧窗格中,选择编辑字段,然后选择添加字段,选择值列,然后选择添加显示它。
若要查看集合中的值,请在文件菜单上选择集合。
要存储和检索集合,请添加两个附加按钮控件,并将其 Text 属性设置为 Load 和 Save。 将加载按钮的 OnSelect 属性设置为此公式:
Clear( PaperTape ); LoadData( PaperTape, "StoredPaperTape", true )
您首先需要清除集合,因为 LoadData 会将存储的值附加到集合末尾。
将保存按钮的 OnSelect 属性设为以下公式:
SaveData( PaperTape, "StoredPaperTape" )
按 F5 键再次预览,在文本输入控件中输入数字,然后选择按钮。 选择保存按钮。 关闭并重新加载应用,然后选择加载按钮以重新加载集合。