我是微软Dynamics 365 & Power Platform方面的工程师/顾问罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复460或者20211123可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
前面的博文:读取Excel对用户执行增加/移除角色的控制台程序 我用的是程序,微软大力推荐低代码平台Power Platform,我今天就做个简单的例子,我就读取Excel来授予用户角色。
大致包括几个步骤:
- 读取Excel中的所有记录
- 每行看下【增加角色】列是否有值
- 【增加角色】列有值的话,查询下用户是否已经有这个角色
- 若用户没有这个角色,再去Dynamics 365中查询这个角色的信息
- 若是Dynamics 365存在这个角色的信息,将其授予给用户
我的Excel内容示例如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM1czX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xCNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2ITOwUTNyEDO0MzN0EGZ1QDO5MjZjRGNwUGZ4IGMyQmYkRDMyM2LcFTMxIDMy8CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
首先需要对Excel进行处理,选择要处理的内容,点击 【Insert】 > 【Table】,其余保持默认即可。
还需要将要处理的Excel上传到某个地方,我这里上传到Onedriver for business中,如下:
登录 https://make.powerapps.com/ ,点击 Solutions,打开自己的某个Solution,点击【New】>【Automation】>【Cloud flow】>【Instance】,我这里是新界面,如果不一样也不用担心,Instant类型的flow一般是手工触发运行,其他两种类型的Cloud flow从名字可以看出来,第一种是事件触发的flow,第三种是定期运行的flow。
弹出界面我这么设置,触发器(trigger)我选择Manually trigger a flow。
我先使用Initialize variable 这个Action 声明两个数组类型的变量。
然后使用Excel Online (Business)中的 List rows present in a table这个Action来获取excel中的数据。
这个步骤的具体设置如下:
对于每行数据我要循环处理,都要查询其用户信息,所以我添加一个Microsoft Dataverse下面的List rows 这个Action。
我根据用户名来查询用户,写法如下,我这里只查询处我需要的三列fullname,_businessunitid_value,systemuserid,注意对于查找字段不能写字段逻辑名,前面要加上_,后面要加上 _value,这个用户名我使用前面步骤返回的【用户主体名称】这个字段的值,选择后可以看到自动会帮我生成一个for each。我这里还设置了Row count为1,因为我只需要第一条记录即可。
我先检查要增加的角色列的值不为空,如下:
检查的左边的表达式是:empty(items('Apply_to_each_Excel_Row')?['增加角色'])
操作符是:is not equal to
右边的表达式是 true。
如果不为空我这里会将之前声明的变量 toAssociateRoles 设置为null,用来存储每个用户需要添加的角色清单。
下面我还是用一个for each将角色放到变量toAssociateRoles待用。这个for each针对的表达式是 split(items('Apply_to_each_Excel_Row')?['增加角色'],';') ,也就是每行excel的【增加角色】列的值使用;分隔成一个数组,然后逐个添加到变量toAssociateRoles。
然后我需要找出用户当前有哪些角色,需要添加的角色用户当前不拥有我才添加给用户。所以我查询下用户的角色,这里我用的FetchXml进行查询,如下:
<fetch version='1.0' mapping='logical' distinct='true' no-lock='true'>
<entity name='role'>
<attribute name='name' />
<attribute name='roleid' />
<link-entity name='systemuserroles' from='roleid' to='roleid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ad'>
<filter type='and'>
<condition attribute='systemuserid' operator='eq' value='@{items('Apply_to_each_User')?['systemuserid']}' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>
类似的,我清空 CurrentRolesofUser变量后用个foreach将用户的角色添加到CurrentRolesofUser变量中,用变量是为了后面维护起来方便。
然后我需要针对每个要添加的角色,看下用户当前是否存在。这个for each的输入表达式是 variables('toAssociateRoles') ,检查表达式左边是 contains(variables('CurrentRolesofUser'),items('Apply_to_each_toAssiciateRoles')) ,右边是false。
如果不存在,当然我们要先查询出这个角色的id,查询角色id需要根据角色名称+用户的业务部门来查询,类似如下:
name eq '@{items('Apply_to_each_toAssiciateRoles')}' and _businessunitid_value eq '@{items('Apply_to_each_User')?['_businessunitid_value']}'
如果查询到了角色,也就是判断这个查询结果是否返回记录,我这里进行如下判断:
length(outputs('Get_role_info_by_role_name_and_business_unit')?['body/value']) 的值是否等于1.
如果找到的话就授予用户这个角色,没有找到可能就是角色名称写错了。
授予角色不是更新记录,需要用到 Relate rows这个Action
具体的Action设置如下:
Row ID我设置的表达式是:items('Apply_to_each_User')?['systemuserid']
Relate with我设置的表达式是:first(outputs('Get_role_info_by_role_name_and_business_unit')?['body/value'])['@odata.id']
因为我知道前面步骤返回role的数组只有一个元素,所以我这里也不想自动生成for each了,直接取第一行,让flow看起来更加简单一点。