Power Automate实用常见问题解答(FAQ)

犀渠玉剑良家子,白马金羁侠少年。这篇文章主要讲述Power Automate实用常见问题解答(FAQ)相关的知识,希望能为你提供帮助。
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复395或者20200224可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
Dynamics 365 Customer Engagement已经强烈推荐使用Power Automate代替Workflow,我这篇文章主要收集常见的问题做解答。
1. Power Automate如何调用Dynamics 365 Customer Engagement中的操作(Action)?
可以登录 https://make.powerapps.com/ 或者 https://flow.microsoft.com ,打开左边的Solutions ,新建或者打开已有Solution。

Power Automate实用常见问题解答(FAQ)

文章图片



然后新建Flow。
Power Automate实用常见问题解答(FAQ)

文章图片



调用操作时候,注意Connector 要选择 Common Data Service (current environment ).
Power Automate实用常见问题解答(FAQ)

文章图片


然后可以选择 Perfrom a bound action 或者 Perform an unbound action 进行调用即可。如果选不到,确认action已经激活,然后看看 https://***.crm.dynamics.com/api/flow/openapi 这个url访问是否报错。
Power Automate实用常见问题解答(FAQ)

文章图片



2. 如何获取选项集字段的显示文本。
我开始以为直接查询的时候获取不到,以为只能获取到存储值,后来经高人指点是可以的。
之前我的方法很笨,就是再查询一次stringmap实体,比如 https://***.crm.dynamics.com/api/data/v9.1/stringmaps?$filter=objecttypecode eq \'ly_demo\' and attributename eq \'statuscode\' and langid eq 1033 and attributevalue eq 1 。
更好的办法是直接从trigger返回的body中获取值,注意选项集字段若为statuscode,需要写成 _statuscode_label。
需要使用表达式输入,例如: triggerOutputs()?[\'body/_lvo_addresschangetype_label\'] ,当然不要全部手写,可以选一个字段值,然后选择 Peek Code,查看使用的表达式,然后自己用表达式来输入,修改自动生成的表达式为自己想要的字段值即可。
如果是通过 Get a record等查询方式,请通过类似 outputs(\'Your_Action_Name\')?[\'body/ly_optionsetfieldname@OData.Community.Display.V1.FormattedValue\'] 的表达式来获取。
Power Automate实用常见问题解答(FAQ)

文章图片


3.如何获取当前环境的base url。
这个url很重要,我们在邮件或者别的地方插入链接让用户可以点击打开Dynamics 365的记录就需要这个。
参考文章 Quick Tip: CDS Base URL in Flow 可以知道从前面的查询中获取body中的@odata.id元素的值,然后分割下获取第一元素值即可,表达式类似:
first(split(outputs(\'Get_Creators_primary_emailaddress\')?[\'body\'][\'@odata.id\'],\'/api/\')) 。
或者
first(split(outputs(\'Get_Creators_primary_emailaddress\')?[\'body\'][\'@odata.context\'], \'/api/\'))
我一般用一个变量将这个值保存起来,假设变量名是CurrentEnvBaseUrl ,那么插入url使用的表达式就类似:
concat(variables(\'CurrentEnvBaseUrl\'),\'/main.aspx?pagetype=entityrecord& etn=ly_demo& id=\',triggerOutputs()?[\'body/ly_demoid\'])
Power Automate中可以用到的函数参考文档:Reference guide to using functions in expressions for Azure Logic Apps and Power Automate
Dynamics 365 Customer Engagement通过URL打开记录,窗体,视图等请参考官方文档: Open forms, views, dialogs, and reports with a URL
4.如何查询的时候同时获取查找字段的其他信息(含主属性信息)。
使用Common Data Service (current environment) 这个connector中的Get a record或者List records查询记录的时候,默认情况下对于查询字段只返回类似如下的三个属性:
"_modifiedby_value@Microsoft.Dynamics.CRM.lookuplogicalname": "systemuser", "_modifiedby_value@odata.type": "#Guid", "_modifiedby_value": "21c43fb9-f446-ea11-a816-000d3a3788d7",


如果我要获取查找字段的主属性值甚至其他值呢?如果我要获取modifiedby这个人主属性fullname的值甚至其邮箱呢?当然,通过再一次查询肯定可以。
我这里介绍的是另外一种方法,原理可以参考我的文章 Dynamics 365 We API ODATA语法根据父记录查询子记录,根据子记录查询父记录(附上根据团队,队列名称查成员) 。
具体设置类似如下:
Power Automate实用常见问题解答(FAQ)

文章图片


然后你可能会问如何获取这个值?对于使用Get a record,类似的表达式是 outputs(\'Get_a_record\')?[\'body/modifiedby\'][\'internalemailaddress\']
对于使用List records,类似的表达式是 items(\'Apply_to_each\')?[\'modifiedby\'][\'internalemailaddress\'] 。
也不用特别记忆,看自动生成的语法是什么样的,自己修改下即可。
5.能调用自定义工作流活动吗?
我认为当前不能,不代表后续不能。 对比可以参考官方文档,https://docs.microsoft.com/en-us/power-automate/replace-workflows-with-flows ,Power Automate的功能在不断增强。
6.能发送邮件并显示在D365中的Timeline吗?
在Power Automate中可以通过Outlook这个Connector来发送邮件,但是这种邮件与Dynamics 365的关系不大。有些时候我们希望能调用Dynamics 365中Workflow那种发送邮件的能力,发送的邮件能和D365的记录关联,并展示在关联记录的Timeline中。答案是可以的,详情可以参考 Send Dynamics 365 Emails from Power Automate或者 Creating and Sending an Email from Dynamics 365 using Power Automate。我总结下重点,也是创建 Email Messages 这个实体记录,收件人可以通过 Activity Party Attribute Name 设置为To,然后在其对应的 Activity Party Attribute Value中设置值来设置,可以设置为类似 /contacts(@{triggerOutputs()?[\'body/contactlid\']}) 这种。邮件的主题当然是Subject字段,内容是Description字段,关于字段会出现很多类似 Regarding (Opportunities) 的字段,找到你要管理的实体类型,设置为类似 /contacts(@{triggerOutputs()?[\'body/contactlid\']}) 这种格式。发送邮件是通过 Common Data Service (current environment ) 这个Connector通过 Perform an bound action来做的,调用的Action Name是SendEmail,参考下图。如果要将收件人设置为文本字段的值,可以参考我这个博文 Dynamics 365中使用工作流发邮件让其可以发往文本字段指定的邮箱 注册一个插件来实现。
Power Automate实用常见问题解答(FAQ)

文章图片


7.有类似child flow的功能吗?
答案是有,2019年10月份GA的,可以参考官方文档 Call Child Flows ,博文可以参考 October Updates for Microsoft Flow 。
一般对于child flow我选择Power Apps作为触发器,如果child flow有输出参数,那么它的最后一个action一般是Respond to a Power App or flow 或者 Response。
parent flow调用child flow的时候选择Flows连接器下面的 Run a Child Flow 这个action来调用。
8.异常处理一般如何做?
可以参考 Advanced Error Handling With Power Automate , Microsoft Flow Error Handling ,Try-Catch pattern in Microsoft Flow。
主要使用result函数,函数参考见 Reference guide to using functions in expressions for Azure Logic Apps and Power Automate 。
参考官方文档:Handle errors and exceptions in Azure Logic Apps。
还需要考虑一些limit,官方文档请参考:Limits and configuration information for Azure Logic Apps
我的如下可以供参考:
用到的表达式分别是:
result(\'Main_Scope\')
createArray(\'Failed\', \'TimedOut\')
item()[\'status\'])
body(\'Filter_array\')
items(\'Apply_to_each_result\')[\'name\']
items(\'Apply_to_each_result\')[\'status\']
items(\'Apply_to_each_result\')[\'code\']
items(\'Apply_to_each_result\')[\'outputs\'][\'body\'][\'error\'][\'message\']
Power Automate实用常见问题解答(FAQ)

文章图片



9.查询CDS步骤如何判断是否返回了记录?
可以使用类似的表达式 length(body(\'Query_Accont\')?[\'value\']) 来判断,其中Query_Accont是Common Data Servie (current)这个connector的List records查询步骤的名称,你输入名称中的空格请以_替换。比如查询步骤名称你更改为了Query Account,那么用的时候是用Query_Accont 。
10.利用Trigger Conditions拆分flow,减少flow的运行
我们做的时候常见的触发条件是字段的变更,这样做的话,一般字段变化就会触发一次。如果可以在字段变更后,自己可以加一些条件来限制flow是否运行就更好了,减少flow的运行次数。
如果flow分支多,比较复杂,维护起来就比较麻烦,可以直接拆分flow称为多个,根据不同的条件触发不同的flow呢?
利用Trigger Conditions是可以做到的,可以参考 Power Automate Trigger Conditions made EASY 和 Microsoft Power Automate Flow Trigger Conditions 。
就是在trigger中点击如下右上角的【...】符号,在出来的菜单中选择 【Settings】。
Power Automate实用常见问题解答(FAQ)

文章图片


在Trigger Conditions文本输入框中输入表达式,类似 @equals(triggerBody()?[\'_ly_accountid_value\'],\'a6d94ece-384c-ea11-a812-000d3a378f47\') 这种,然后点击【Done】按钮。
Power Automate实用常见问题解答(FAQ)

文章图片


这个Trigger Condition可以加多行的,如果某行中要判定是某个值中的一个,可靠考虑类似下边写法:
@contains(createArray(\'1\',\'552590009\',\'552590006\',\'552590007\'), string(triggerBody()?[\'statuscode\']))
11.判断列表是否包括/不包括某个值
可以使用createArray函数放在判断的左边,中间的操作符使用 contain 或者 does not contain ,右边是要比较的值或者表达式。比如我下图用的是:
表达式分别是:
createArray(\'CHINA\',\'JAPAN\',\'INDIA\')
toUpper(outputs(\'Get_request_info\')?[\'body/ly_countryname\'])
Power Automate实用常见问题解答(FAQ)

文章图片


12.我只需要查询结果的第一行记录进行处理如何写表达式避免循环?
前面步骤使用Common Data Service (Current) 这个Connector 的List records这个action做查询,并且指定了Top Count 为1,也就是会最多返回一条记录。
后面的步骤可以用这样的表达式 outputs(\'retrieve_config_entity_of_myconfigur\')?[\'body/value\'][0][\'ly_value\']来获取返回结果中的某个字段的值。

13. 多种方式可以访问Common Data Service服务,推荐哪种?
推荐使用 Common Data Service (current environment) connector ,官方文档描述如下,链接为 Create an automated flow by using Common Data Service (current environment)
Important
There are three connectors available to connect to Common Data Service. This article covers the recommended Common Data Service (current environment) connector for connecting to Common Data Serivce. The Common Data Service connector and the Dynamics 365 connector are also available for use if you cannot use the recommended connector.
Common Data Service (current environment) connector 没有Throttling Limits章节,而Common Data Service connector则有,如下图所示:
Power Automate实用常见问题解答(FAQ)

文章图片



不过截至2020-07-26,Common Data Service (current environment) connector 并不支持中国大陆的云服务。
Power Automate实用常见问题解答(FAQ)

文章图片



14. flow运行慢,如何排查?
请参考官方文档:Troubleshooting Slow Running Flows 。

15. 可以通过Web API来查询flow的信息吗?
答案是可以的,请参考官方文档:Power Automate Web API ,比如查询目前开启的flow:
GET https://luoyongdemo.crm5.dynamics.com/api/data/v9.1/workflows?$filter=category eq 5 and statecode eq 1

16. 判断字符串为空后传递null值的表达式如何写?
请参考下面写法,因为如果是CDS更新记录,对于查找字段,传递空字符串会报错,可以传递null。
If(equals(variables(\'CurrencyId\'),\'\'),null,variables(\'CurrencyId\'))

17. 针对日期时间字段进行查询
可以参考 Advanced | Flow of the Week: Filtering Data with OData ,采用类似如下的Filter Query:
ly_orderdate gt addDays(utcnow(\'yyyy-MM-ddTHH:mm:ssZ\'),-30)
formatDateTime(addHours(formatDateTime(addDays(addHours(utcNow(),8),-1),\'yyyy-MM-dd\'),-8),\'yyyy-MM-ddTHH:mm:ssZ\')
18. 如何搜索flow的运行记录(run history)
请参考官方博文: Download flow run history, build advanced recurring schedules and more . 也就是在查看All run history的时候,有 Download CSV功能,不过一次最多导出100个run history.

19.Canvas App中调用flow传递参数的常用方法
最好是传递Json数据,我这里提供我常用的方法,调用flow使用类似的代码:

ClearCollect( colFilter, { StartDate: dpStartDate.SelectedDate, EndDate: dpEndDate.SelectedDate } ); ClearCollect( colAggregate, GetEntityRecordCountFlow.Run(JSON(First(colFilter))).outResult );



在flow里面添加一个Data Operation 下面的Parse JOSN action,类似如下,Content通过【Ask in PowerApps】来添加,然后点击【Generate from sample】按钮来生成Schema。
Power Automate实用常见问题解答(FAQ)

文章图片



下图是一个完成设置的例子。
Power Automate实用常见问题解答(FAQ)

文章图片



可以看到后面步骤可以通过Dynamic content来获取解析出来的输入参数的值。
Power Automate实用常见问题解答(FAQ)

文章图片



20.Canvas App中调用flow获得JSON返回值的常用方法
在flow的最后步骤,添加一个Request 中的 Response 这种action。
Power Automate实用常见问题解答(FAQ)

文章图片



Power Automate实用常见问题解答(FAQ)

文章图片



记得将Status Code设置为200,Body设置为要返回的JSON内容,然后一定要点击 【Show advanced options】,再点击【Generate from sample】按钮来生成Schema。这样就可以了。
Power Automate实用常见问题解答(FAQ)

文章图片


21.转义Dataverse中多行文本中的换行符的方法
发邮件如果包括了多行文本字段的值,会发现换行丢了,如果要保留的话,参考下面的表达式。
uriComponentToString(replace(uriComponent(triggerOutputs()?[\'body/lvo_commentsdetails\']),\'%0A\',\'
\'))
22.利用表达式设置Owner字段的方法
示例如下:
if(equals(triggerOutputs()?[\'body/_ownerid_type\'],\'systemusers\'),concat(\'/systemusers(\',triggerOutputs()?[\'body/_ownerid_value\'],\')\'),concat(\'/teams(\',triggerOutputs()?[\'body/_ownerid_value\'],\')\'))

【Power Automate实用常见问题解答(FAQ)】

    推荐阅读