数据类型

备注

Microsoft Power Fx 是画布应用公式语言的新名称。 当我们从画布应用中提取语言,将其与其他 Microsoft Power Platform 产品集成并使其作为开放源代码提供时,这些文章还在撰写。 从 Microsoft Power Fx 概述开始,了解对此语言的介绍。

信息以小的离散值流经应用,与电子表格的单元格非常类似。 例如,生日字段和纪念日字段中的数据都将作为包含年份、月份和日期的日期值流经。 应用知道如何设置这些值的格式,将输入限制为适合每个值的值,并与数据库共享这些值。 生日与人们的纪念日不同,但系统以完全相同的方式处理生日。 这种情况,数据类型的一个示例日期

本文提供画布应用支持的数据类型的详细信息。 当应用连接到外部数据源时,该源中的每种数据类型都将映射到画布应用的数据类型。

数据类型 描述 示例
布尔值 truefalse 值。 无需比较即可直接在 IfFilter 和其他函数中使用。 true
颜色 颜色规范,包括 alpha 通道。 Color.Red
ColorValue( "#102030" )
RGBA( 255, 128, 0, 0.5 )
货币 存储在浮点数中的货币值。 货币值与带有货币格式选项的数字值相同。 123
4.56
日期 没有时间的日期,以应用用户所在时区计。 Date( 2019, 5, 16 )
日期时间 带时间的日期,以应用用户所在时区计。 DateTimeValue( "May 16, 2019 1:23:09 PM" )
小数 具有高精度、以 10 为基数运算且范围有限的数。 123
十进制 ("1.2345")
GUID 一个全局唯一标识符 GUID()
GUID( "123e4567-e89b-12d3-a456-426655440000" )
超链接 用于保留超链接的文本字符串。 "https://powerapps.microsoft.com"
Image .jpeg、.png、.svg、.gif 或其他常见 Web 图像格式的图像的统一资源标识符 (URI) 文本字符串。 MyImage 添加为应用资源
"https://northwindtraders.com/logo.jpg"
"appres://blobmanager/7b12ffa2..."
媒体 用于视频或音频录制的 URI 文本字符串。 MyVideo 添加为应用资源
"https://northwindtraders.com/intro.mp4"
"appres://blobmanager/3ba411c..."
数字浮点 具有标准精度、以 2 为基数运算且范围宽的数。 123
8.903e121
1.234e200
单选 对一组选项的选择,以数字方式支持。 此数据类型将可本地化的文本标签与数字值组合在一起。 标签出现在应用中,数字值被存储并用于比较。 ThisItem.OrderStatus
记录 数据值的记录。 此复合数据类型包含本主题中列出的其他数据类型的实例。 详细信息:使用表 { Company: "Northwind Traders",
Staff: 35,
NonProfit: false }
记录引用 对表中记录的引用。 此类引用通常与多态查找一起使用。 详细信息:使用引用 First(Accounts).Owner
Table 一个记录表。 所有记录中数据类型相同的字段都必须具有相同名称,省略的字段将被视为空白。 此复合数据类型包含本主题中列出的其他数据类型的实例。 详细信息:使用表 Table( { FirstName: "Sidney",
LastName: "Higa" },
{ FirstName: "Nancy",
LastName: "Anderson" } )
文本 一个 Unicode 文本字符串。 "Hello, World"
时间 没有日期的时间,以应用用户所在时区计。 Time( 11, 23, 45 )
双选项 对一组双重选项的选择,以布尔值方式支持。 此数据类型将可本地化的文本标签与布尔值组合在一起。 标签出现在应用中,布尔值被存储并用于比较。 ThisItem.Taxable
非类型化对象 未声明类型的对象。 基础对象可以是任何现有类型,并可以使用 Boolean()Value()Table() 等函数转换为兼容类型。有关更多信息,请参阅非类型化对象使用 JSON ParseJSON("{ ""Field"" : 1234 }").Field

这些数据类型中有许多是相似的,并且具有相同的基础表示形式,如超链接字段被作为文本处理。 其他数据类型在窗体和其他控件中提供更好的默认体验。

Blank

所有数据类型都可以有一个空白值(即没有值)。 术语“null”通常用于此概念的数据库。

Blank 函数与 SetPatch 函数一起使用,可以将变量或字段设置为空白。 例如,Set( x, Blank() ) 将删除全局变量 x 中的任何值。

使用 IsBlank 函数测试空白值。 使用 Coalesce 函数将可能的空白值替换为非空白值。

由于所有数据类型都支持空白,因此布尔双选项数据类型实际上具有三个可能的值。

所有这四种数据类型均基于 Unicode 文本字符串。

嵌入文本

公式中的嵌入文本字符串用双引号括住。 同时使用两个双引号表示文本字符串中的单个双引号。 例如,在 Button 控件的 OnSelect 属性中使用以下公式:

Notify( "Jane said ""Hello, World!""" )

按下按钮时会出现横幅,这里省略了第一个和最后一个双引号(因为它们分隔文本字符串),Hello, World! 周围的重复双引号被替换为单个双引号:

弹出通知,显示消息 Jane said

单引号用于包含特殊字符且在文本字符串中没有特殊意义的标识符名称

字符串内插

使用字符串内插在文本字符串中嵌入公式。 这通常比使用 Concatenate 函数或 & 运算符更容易处理和可视化输出。

添加美元符号 $ 作为文本字符串的前缀,并用花括号 { } 将要嵌入的公式括起来。 要在文本字符串中包含花括号,使用重复的花括号:{{}}。 字符串内插可用于任何可以使用标准文本字符串的地方。

例如,考虑以下公式,其中全局变量 Apples 设置为 3,Bananas 设置为 4:

$"We have {Apples} apples, {Bananas} bananas, yielding {Apples+Bananas} fruit total."

此公式返回文本字符串 We have 3 apples, 4 bananas, yielding 7 fruit total.变量 ApplesBananas 与数学公式 Apples+Bananas 的结果一起插入到替换大括号的文本中。 花括号周围的空格和其他字符将按原样保留。

嵌入式公式可以包含任何函数或运算符。 所需要的只是可以将公式的结果强制转换为文本字符串。 例如,如果提供,此公式将在问候语中插入 NickName,如果未提供,则插入 FirstName

$"Welcome {Coalesce( NickName, FirstName )}, it's great to meet you!" )

如果 NickName 设置为“Joe”,此公式将生成文本字符串 Welcome Joe, it's great to meet you!。 但是如果 NickName空白FirstName 是“Joseph”,此公式将转而生成 Dear Joseph, great to meet you!

字符串内插可以在嵌入公式中包含标准文本字符串。 例如,如果既没有提供 NickName 也没有提供 FirstName,我们仍然可以提供 "Friend" 作为替代:

$"Welcome {Coalesce( NickName, FirstName, "Friend" )}!"

字符串内插甚至可以嵌套。 考虑以下示例,其中 FirstMiddleLast 名字组合到问候语中。 即使这些值中的一个或两个是空白,也会在名字部分之间保留正确的空格数。 如果没有提供任何部分,内部字符串内插将折叠为空字符串,由 Coalesce 函数替换为“Friend”。

$"Welcome {Coalesce( Trim( $"{First} {Middle} {Last}"}), "Friend" )}!"
First Middle Last 结果
John Qunicy Doe Welcome John Quincy Doe!
John 空白 Doe Welcome John Doe!
空白 空白 Doe Welcome Doe!
空白 空白 空白 Welcome Friend!

换行符

嵌入的文本字符串可以包含换行符。 例如,考虑将 Label 控件的 Text 属性设置为以下内容:

"Line 1
Line 2
Line 3"

上面公式的结果是 label 控件中显示三行:

嵌入的文本字符串和显示三行的 label 控件,行 1、行 2 和行 3。

字符串内插也支持换行符,如下所示:

$"Line {1}
Line {1+1}
Line {1+1+1}"

上述公式会产生相同的输出:

字符串内插公式和显示三行的 label 控件,行 1、行 2 和行 3。

图像和媒体资源

通过文件菜单,您可以将图像、视频和音频文件添加为应用资源。 导入文件的名称将成为应用中的资源名称。 在此图形中,名为 nwindlogo 的罗斯文商贸徽标已添加到应用:

Northwind 资源。

要在应用中使用此资源,请在 Image 控件的 Image 属性中指定它:

Northwind 图像。

图像和其他媒体的 URI

您可以通过将标签控件的 Text 属性设置为 nwindlogo,来深入一些地探索最后一个示例。 标签显示文本字符串:

Northwind 文本。

画布应用通过 URI 文本字符串引用每个图像或其他媒体文件,无论是在云中还是作为应用资源添加。

例如,Image 控件的 Image 属性不仅接受应用资源,还接受指向 Web 上图像的链接,如“https://northwindtraders.com/logo.jpg"”。 此属性还接受使用数据 URI 架构的内联图像,如以下示例:

"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFAQMAAACtnVQoAAAABlBMVEUAAAB0J3UMNU6VAAAAAXRSTlMAQObYZgAAABRJREFUCNdjUGJgCGVg6GgAkkA2AA8/AffqCEBsAAAAAElFTkSuQmCC"

该 URI 显示两个紫色钻石的放大版本:

双菱形。

如果将图像控件的 Image 属性设置为相机控件的 Photo 属性,则可以显示相机控件中捕获的最新图像。 应用将图像保存在内存中,Camera 控件的 Photo 属性返回对图像的 URI 引用。 例如,您可能会拍摄一张照片,相机的 Photo 属性可能返回 "appres://blobmanager/7b12ffa2ea4547e5b3812cb1c7b0a2a0/1"

您使用 URI 来引用存储在数据库中的图像或另一个媒体文件。 这样,应用只有在实际需要时才检索实际数据。 例如,Microsoft Dataverse 表中的附件可能会返回“appres://datasources/Contacts/table/...”与相机示例中一样,您可以通过将 Image 控件的 Image 属性设置为此引用来显示此图像,这将检索二进制数据。

当您将媒体数据类型(如图像)保存到数据库时,应用会发送实际的图像或媒体数据,而不是 URI 引用。

大小限制

作为文本字符串和 URI,这些数据类型的长度没有预设的限制。

这些数据类型引用的二进制数据也没有大小的预设限制。 例如,通过 Camera 控件捕获的图像现在引用为 "appres://...",其大小和分辨率可与设备相机要求的一样大。 媒体文件的分辨率、帧速和其他属性不受数据类型的限制,但是用于播放和捕获媒体的特定控件可能会有其自身的限制。

但是,所有数据大小均取决于应用中的可用内存量。 在台式计算机上运行的浏览器通常支持超过 100 MB 的数据。 但是,诸如手机之类的设备上的可用内存量可能要低得多,通常在 30-70 MB 之间。 要确定您的应用是否将在这些限制内运行,请在应运行它的所有设备上测试常见场景。

最佳做法是仅在必要时将数据保留在内存中。 尽快将图像上传到数据库;仅在应用用户请求下载时才下载图像。

数字

备注

Power Apps目前仅支持浮点,它是所有数字的类型。 十进制支持将很快添加。

Power Fx 支持两种数字:十进制数浮点数(同义词为数字货币)。

十进制数最适合大多数商业计算。 它可以准确地表示以 10 为基数的数字,这意味着 0.1 可以准确地表示出来,并且在计算过程中不会出现舍入误差。 它具有足够大的范围,可满足任何业务需求,最高可达 1028,精度最高可达 28 位。 十进制数是大多数 Power Fx 主机的默认数字数据类型,仅在编写 2*2 时使用。

浮点最适合科学计算。 它可以表示更大范围内的数字,最大为 10308。 精度限于 15 位小数,数学以 2 为基数,所以它不能精确地表示一些常见的十进制值。 浮点也具有更高的性能,如果这是一个因素并且精度不是关键因素,则更受青睐。

十进制数字

十进制数据类型通常使用 .NET 十进制数据类型。 某些主机(如在 SQL Serer 中运行的 Dataverse 公式列)使用 SQL Server 十进制数据类型。

十进制按照您在学校学习的方式进行数学运算。 这对于避免在使用二进制数学(如浮点所用)时因微小差异而产生的舍入误差非常重要。

范围从正 79,228,162,514,264,337,593,543,950,335 到负 79,228,162,514,264,337,593,543,950,335。 小数分隔符可以放在这些数字中的任何位置,提供高达 28 位的精度,并且仍然可以精确表示。 例如,79,228,162,514,264.337593543950335 可以精确地表示为 7.9228162514264337593543950335 也可以。

浮点数

浮点数据类型,也称为数字货币,使用 IEEE 754 双精度浮点标准。 此标准提供很大的可选择数字范围,从 –1.79769 x 10308 到 1.79769 x 10308。 可表示的最小值为 5 x 10–324

浮点可以精确地表示介于 –9,007,199,254,740,991 (–(253 – 1)) 和 9,007,199,254,740,991 (253 – 1)(包括)之间的整数。 此范围大于数据库通常使用的 32 位(或 4 字节)整数数据类型。 但是,画布应用不能表示 64 位(或 8 字节)整数数据类型。 您可能希望将数字存储在文本字段中,或使用计算所得的列在文本字段中建立数字副本,以将其映射到画布应用中的文本数据类型中。 通过这种方式,您可以保留、显示和输入这些值,也可以将它们进行比较以确定它们是否相等;但是,您不能以这种形式对它们执行数值计算。

浮点算术是近似的,因此在许多记录的示例中,有时它可能会给出意外的结果。 您可能预期公式 55 / 100 * 100 会精确返回 55,(55 / 100 * 100) - 55 精确返回零。 但是,后一个公式将返回 7.1054 x 10–15,此值非常小,但不为零。 这种微小差异通常不会导致问题,应用会在显示结果时对其进行舍入。 但是,小差异会在随后的计算中加重并给出错误的答案。

数据库系统通常使用十进制数学来存储货币和执行计算,这提供了较小的范围,但对精度的控制更大。 默认情况下,画布应用将货币映射到浮点值之中或之外;因此,结果可能与以本机十进制数据类型进行的计算不同。 如果这种类型的差异会引起问题,可能需要将这些值作为文本进行处理,就像使用本节前面所述的大整数一样。

默认值和转换

备注

Power Apps目前仅支持浮点,它是所有数字的类型。 十进制支持将很快添加。

默认情况下,大多数 Power Fx 主机使用十进制。 这会影响:

  • 公式中的字面数值。 数字 1.234 将被解读为一个十进制值。 例如,公式 1.234 * 21.2342 解读为十进制,并返回十进制结果。
  • 值函数。 Value( "1.234" ) 将返回一个十进制值。 例如,公式 Value( "1.234" ) * 2函数会将文本字符串 "1.234" 的内容解释为十进制

要处理浮点值,需要使用浮点函数。 扩展上面的示例,Float( 1.234 ) 会将十进制1.234转换为浮点浮点也可以替代,将包含浮点数(如 Float( "1.234" ))的字符串转换为浮点值,如果该数字不能表示为十进制,则需要使用该值。

总而言之:

用法 小数 浮点
公式中的字面数值 1.234 Float( 1.234 )
Float( "1.234" )
从文本字符串转换 Value( "1.234" )
Decimal( "1.234" )
Float( "1.234" )
数字类型之间的转换 Decimal( float ) Float( decimal )
转换为文本字符串 Text( decimal ) Text( float )

混合数字类型

浮点十进制值可以自由混合。 混合时,由于范围较大,十进制值会转换为浮点值。 由于这可能导致精度损失,因此非必要不要将两者混在一起,这一点很重要。 由于十进制是默认的字面数据类型,并且大多数数值函数将保留该类型,因此避免在不需要的情况下移动到浮点相对容易。

例如,考虑在安装 Power Platform CLI后使用 pac power-fx repl 进行的以下计算。 由于两个数字都是十进制,因此计算是以十进制进行的,结果保持完全精确:

>> 1.0000000000000000000000000001 * 2
2.0000000000000000000000000002

相反,如果第二个操作数更改为浮点,则整个计算将在浮点中完成,微小的小数部分将会丢失:

>> 1.0000000000000000000000000001 * Float(2)
2

日期、时间和日期/时间

时区

日期/时间值属于以下类别:

  • 用户当地时间:这些值以 UTC(协调世界时)存储,但是应用用户的时区会影响应用如何显示这些值以及应用用户如何指定它们。 例如,相同的时刻对于加拿大用户与日本用户看起来会有所不同。
  • 时区无关:应用以相同的方式显示这些值,应用用户以相同的方式指定它们,而不管时区如何。 相同的时刻对于加拿大用户和日本用户看起来相同。 不希望自己的应用在不同时区运行的应用作者会使用这些值,因为它们总体上更简单。

下表显示了一些示例:

日期/时间类型 存储在数据库中的值 显示并进入 UTC 以西 7 小时的值 显示并进入 UTC 以东 4 小时的值
用户当地时间 Sunday,May19,2019
4:00 AM
Saturday,May18,2019
9:00 PM
Sunday,May19,2019
8:00 AM
时区无关 Sunday,May19,2019
4:00 AM
Sunday,May19,2019
4:00 AM
Sunday,May19,2019
4:00 AM

对于用户当地时间日期/时间,画布应用使用浏览器或设备的时区,而模型驱动应用使用 Dataverse 中的用户设置。 这些设置通常匹配,但是如果这些设置不同,则结果会有所不同。

使用 DateAddTimeZoneInformation 函数将本地时间转换为 UTC,然后返回。 请参阅这些函数的文档结尾处的示例。

数字等效项

画布应用以 UTC 保留和计算所有日期/时间值,无论是用户当地时间还是时区无关。 在显示值和应用用户指定值时,应用将根据应用用户的时区转换这些值。

当画布应用从数据源读取时区无关值或将此类值写入数据源时,应用会自动调整值来补偿应用用户的时区。 然后,应用将该值视为 UTC 值,与应用中的所有其他日期/时间值一致。 由于此补偿,当应用针对应用用户的时区调整 UTC 值时,原始的时区无关值将出现。

您可以通过使用 Value 函数访问日期/时间值的基础数字值来更接近地观察此行为。 此函数以 1970 年 1 月 1 日 00:00:00.000 UTC 以来的毫秒数返回日期/时间值。

由于每个日期/时间值都以 UTC 保留,因此在世界上大部分地区,公式 Value( Date( 1970, 1, 1 ) ) 都不会返回零,因为 Date 函数返回 UTC 日期。 例如,此公式将以与 UTC 偏移八个小时的时区返回 28,800,000。 此数字反映八小时的毫秒数。

从上面回到我们的示例:

日期/时间类型 存储在数据库中的值 显示并进入 UTC 以西 7 小时的值 Value 函数返回
用户当地时间 Sunday,May19,2019
4:00 AM
Saturday,May18,2019
9:00 PM
1,558,238,400,000
(Sunday,May19,2019
4:00 AM UTC)
时区无关 Sunday,May19,2019
4:00 AM
Sunday,May19,2019
4:00 AM
1,558,263,600,000
(Sunday,May19,2019
11:00 AM UTC)

转换 Unix 时间

Unix 时间反映自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数。 由于画布应用使用毫秒而不是秒,因此可以通过乘以除以 1,000 来在两者之间进行转换。

例如,Unix 时间将 2001 年 9 月 9 日上午 1:46:40 UTC 显示为 1,000,000,000。 要在画布应用中显示该日期/时间值,将该数字乘以 1,000 以将其转换为毫秒,然后在 Text 函数中使用它。 公式 Text( 1000000000 * 1000, DateTimeFormat.UTC ) 将返回字符串 2001-09-09T01:46:40.000Z

但是,如果您在 UTC 偏移 -7 小时(UTC 以西 7 小时)的时区使用 DateTimeFormat.LongDateTime24 格式,该函数将返回 Saturday, September 8, 2001 18:46:40。 此结果将根据本地时区正确显示日期/时间值。

要转换为 Unix 时间,将的结果除以 1,000:
RoundDown( Value( UnixTime ) / 1000, 0 )

如果需要日期值中的 Unix 时间来进行进一步计算或在 Power Apps 中显示,请使用以下公式:
DateAdd( Date( 1970,1,1 ), UnixTime, Seconds )

SQL Server

SQL Server 具有日期/时间日期/时间 2 和其他日期/时间数据类型,这些数据类型不包含时区偏移,也不指示它们所在的时区。 画布应用假定这些值以 UTC 存储,并将它们视为用户当地时间。 如果这些值与时区无关,请使用 TimeZoneOffset 函数针对 UTC 转换进行更正。

将值转换为应用的内部 UTC 表示形式时,画布应用会使用 Datetimeoffset 字段中包含的时区信息。 这些应用在写入数据时始终使用 UTC 作为时区(零时区偏移)。

画布应用以 ISO 8601 持续时间格式的文本字符串读取和写入 SQL Server 中时间数据类型的值。 例如,您必须解析此字符串格式,然后使用 Time 函数将文本字符串 "PT2H1M39S" 转换为时间值:

With(
    Match( "PT2H1M39S", "PT(?:(?<hours>\d+)H)?(?:(?<minutes>\d+)M)?(?:(?<seconds>\d+)S)?" ),
    Time( Value( hours ), Value( minutes ), Value( seconds ) )
)
// Result: 2:01 AM (as shown in a label control, use the Text function to see the seconds)

混合日期和时间信息

日期时间日期/时间具有不同的名称,但是它们都会保留关于日期和时间的相同信息。

日期值中可能包含时间信息,通常是午夜。 时间值可能携带日期信息,通常为 1970 年 1 月 1 日。 Dataverse 还使用仅限日期字段存储时间信息,但默认情况下仅显示日期信息。 同样,画布应用有时会区分这些数据类型,来确定默认格式和控件。

不建议直接添加和减去日期和时间值,因为时区和其他转换可能会导致结果混乱。 您可以使用 Value 函数将日期/时间值首先转换为毫秒,然后考虑应用用户的时区,或者使用 DateAddDateDiff 函数在其中一个值上进行加减。

选择项和“是/否”

选择项和双选项数据类型为应用用户提供两个或多个可以选择的选择项。 例如,订单状态选择项可能会提供已发货已开票已结束选择项。 双选项数据类型仅提供两个选择。

这两种数据类型均在文本字符串上下文中显示其标签。 例如,如果控件的 Text 属性设置为引用该选择项的公式,label 控件会显示订单状态选项之一。 选项标签可能已针对不同位置的应用用户进行了本地化。

当应用用户选择一个选项并保存更改时,应用会将数据传输到数据库,该数据库以独立于语言的表示形式存储该数据。 选择项中的选项以数字形式传输和存储,双选项数据类型中的选项以布尔值形式传输和存储。

标签仅用于显示目的。 您无法对标签进行直接比较,因为它们特定于语言。 而每个选择项都有一个与基础数字或布尔值一起使用的枚举。 例如,您不能使用以下公式:

If( ThisItem.OrderStatus = "Active", ...

但您可以使用以下公式:

If( ThisItem.OrderStatus = OrderStatus.Active, ...

对于全局选择项(哪些表共享),选项集枚举的名称将与全局选择项的名称匹配。 对于本地选择项(范围划定为表),名称可能包含表的名称。 如果多个表具有名称相同的选择项,此行为可避免冲突。 例如,客户表可能有一个 OrderStatus 选择项,其名称可能是 OrderStatus(客户)。 该名称包含一个或多个空格和括号,因此,如果在公式中引用它,则必须用单引号括住。

此外,双选项值也可以充当布尔值。 例如,一个名为 TaxStatus 的双选项值可能具有标签应纳税非应纳税,它们分别对应于 truefalse。 要进行演示,您可以使用以下公式:

If( ThisItem.Taxable = TaxStatus.Taxable, ...

您还可以使用以下等效公式:

If( ThisItem.Taxable, ...