利用SharePoint Designer开发可循环工作流

介绍
大家都知道SharePoint工作流有两种开发(设计)方式:通过SharePoint Designer和Visual Studio.
l 使用Visual Studio,开发人员可以通过编码的方式灵活的开发SharePoint工作流.
l 使用SharePoint Designer,网站管理人员可以基于定义和规则设计SharePoint工作流,无需编码.
使用SharePoint Designer设计工作流是件简单的事情,SharePoint Designer工作流设计器可以帮助我们设计出顺序执行的工作流,然而许多真实场景中的工作流可能并非如此,那么SharePoint Designer是否可以设计出非顺序执行的工作流呢?
本文就将”利用”SharePoint Designer来设计一个可以循环的工作流.
使用SharePoint Designer设计一个简单的工作流
我们先利用SharePoint Designer来设计一个简单的工作流,这个工作流先判断一个Bool型变量是否为False,如果为False则向用户收集一个Bool型的数据,并把它赋给之前的变量.
1.用SharePoint Designer打开文档中心网站.
2.新建 > 工作流:
l 名称: WhileInDesigner
l 附加到列表: 文档

点击 下一步 .
3.新建两个变量.
点击 变量 (V)按钮,添加下列两个变量:


4.添加一个条件.
点击 条件按钮,选择 比较任意数据源.

点击 等于左边的  > 选择 工作流数据变量 :finish.

点击 等于右边的 ,选择 .

5.添加操作:收集用户数据
下面我们来添加一个收集用户数据的操作,事实上就是为用户创建一个任务.
点击 条件 > 从用户处收集数据.
 
点击 此用户,选择 创建当前项目的用户.

点击 数据 > 下一步,输入任务名称和说明信息.
l 任务名称: Task In While?

点击 下一步 > 添加,添加一个向用户收集的数据canFinish:
l 域名: canFinish
l 信息类型: / ( 复选框 )
l 默认值:

设置输出到变量taskID.

点击 变量 (V)删除自动生成的变量 collect.
6.添加操作:获取用户数据
再添加一个操作来获取刚才收集的canFinish值并将其赋给变量finish.
点击 操作 > 其他操作 > 设置工作流变量.

点击 工作流变量,选择 变量 :finish.
点击  > 按照下图设置:

最终的工作流如下图所示:

点击 完成,SharePoint Designer会 保存, 验证并自动将工作流 关联到之前选择附加的列表上.
7.测试工作流
现在来测试一下刚才设计的工作流.
打开 SharePoint 文档中心 > 文档,上传一个文档,为其启动WhileInDesigner工作流.
打开 任务,编辑WhileInDesigner工作流创建的 Task In While?任务,点击 完成任务,这时Task In While?任务和WhileInDesigner工作流的状态都是 已完成.
修改XOML实现循环
1.SharePoint Designer生成的文件
回到SharePoint Designer,我们发现SharePoint Designer自动生成了以下文件:

Task In While_003f_.aspx : Task In While?任务的寄主页
WhileInDesigner.aspx : 工作流初始化页
WhileInDesigner.xoml : 工作流定义文件
WhileInDesigner.xoml.rules : 工作流规则文件
WhileInDesigner.xoml.wfconfig.xml : 工作流配置文件
右键单击 WhileInDesigner.xoml,选择 XML 方式打开.

可以看到如下XOML文件:
< ns0:RootWorkflowActivityWithData x:Class = "Microsoft.SharePoint.Workflow.ROOT"x:Name="ROOT"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:ns0="clr-namespace:Microsoft.SharePoint.WorkflowActions;Assembly=Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0, Culture=neutral, PublicKeyToken=null">
     < ns0:RootWorkflowActivityWithData.WorkflowFields >
         < ns0:WorkflowDataField Name = "__list"Type="System.String" />
         < ns0:WorkflowDataField Name = "__item"Type="System.Int32" />
         < ns0:WorkflowDataField Name = "__context"Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" />
         < ns0:WorkflowDataField Name = "__initParams"Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties" />
         < ns0:WorkflowDataField Name = "__workflowId"Type="System.Guid" />
         < ns0:WorkflowDataField Name = "finish"Type="System.Boolean" />
         < ns0:WorkflowDataField Name = "taskId"Type="System.Int32" />
         < ns0:WorkflowDataField Name = "_x005f_String0"Type="System.String" />
         < ns0:WorkflowDataField Name = "_x005f_Boolean0"Type="System.Boolean" />
         < ns0:WorkflowDataField Name = "_x005f_Int320"Type="System.Int32" />
     </ ns0:RootWorkflowActivityWithData.WorkflowFields >
     < ns0:OnWorkflowActivated WorkflowProperties = "{ActivityBind ROOT,Path=__initParams}"x:Name="ID1">
         < ns0:OnWorkflowActivated.CorrelationToken >
              < wf0:CorrelationToken Name = "refObject"OwnerActivityName="ROOT"xmlns:wf0="http://schemas.microsoft.com/winfx/2006/xaml/workflow" />
         </ ns0:OnWorkflowActivated.CorrelationToken >
     </ ns0:OnWorkflowActivated >
     < ns0:ApplyActivation __Context = "{ActivityBind ROOT,Path=__context}"x:Name="ID2"__WorkflowProperties="{ActivityBind ROOT,Path=__initParams}" />
     < IfElseActivity x:Name = "ID6"Description=" 步骤 1 ">
         < IfElseBranchActivity x:Name = "ID3">
              < IfElseBranchActivity.Condition >
                   < RuleConditionReference ConditionName = "__Rule_ID3_1" />
              </ IfElseBranchActivity.Condition >
              < ns0:LookupActivity ListId = "{}{A4716DC6-6214-4B4E-A400-BBEEEFBA74CD}"x:Name="ID9"FieldName="Author"LookupFunction="LookupUser"__Context="{ActivityBind ROOT,Path=__context}"ListItem="{ActivityBind ROOT,Path=__item}">
                   < ns0:LookupActivity.ReturnValue >
                       < ActivityBind Name = "ROOT"Path="_x005f_String0" />
                   </ ns0:LookupActivity.ReturnValue >
              </ ns0:LookupActivity >
              < ns0:CollectDataTask x:Name = "ID8"ContentTypeId="0x01080100D337657FD8FFC44B8D75294F67F6900E00E892A7A4399FB5499230A2887D54EDD4"TaskId="{ActivityBind ROOT,Path=taskId}"Title="Task In While?"InProperties="{x:Null}"__Context="{ActivityBind ROOT,Path=__context}"OutProperties="{x:Null}"AssignedTo="{ActivityBind ROOT,Path=_x005f_String0}" />
              < ns0:FindValueActivity x:Name = "ID12"ReturnValue="{ActivityBind ROOT,Path=_x005f_Int320}"ExternalFieldName="canFinish"__Context="{ActivityBind ROOT,Path=__context}"ValueType="System.Boolean"ExternalListId="{}{B0880D9F-DD1C-47AA-9369-FB1081BF054C}">
                   < ns0:FindValueActivity.FindValue >
                       < ns1:Boolean xmlns:ns1 = "clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">false</ns1:Boolean>
                   </ ns0:FindValueActivity.FindValue >
              </ ns0:FindValueActivity >
              < ns0:LookupActivity ListId = "{}{B0880D9F-DD1C-47AA-9369-FB1081BF054C}"x:Name="ID11"FieldName="canFinish"LookupFunction="LookupBool"__Context="{ActivityBind ROOT,Path=__context}"ListItem="{ActivityBind ROOT,Path=_x005f_Int320}">
                   < ns0:LookupActivity.ReturnValue >
                       < ActivityBind Name = "ROOT"Path="_x005f_Boolean0" />
                   </ ns0:LookupActivity.ReturnValue >
              </ ns0:LookupActivity >
              < ns0:SetVariableActivity x:Name = "ID10"ValueType="System.Boolean">
                   < ns0:SetVariableActivity.Variable >
                       < ActivityBind Name = "ROOT"Path="finish" />
                   </ ns0:SetVariableActivity.Variable >
                   < ns0:SetVariableActivity.Value >
                       < ActivityBind Name = "ROOT"Path="_x005f_Boolean0" />
                   </ ns0:SetVariableActivity.Value >
              </ ns0:SetVariableActivity >
         </ IfElseBranchActivity >
     </ IfElseActivity >
</ ns0:RootWorkflowActivityWithData >
2.根元素:RootWorkflowActivityWithData元素
从根元素 RootWorkflowActivityWithData的三个名称空间可以看出,SharePoint Designer设计的工作流需要 Windows Workflow Foundation Windows SharePoint Services 3.0共同支持.
3.替换IfElseActivity
继续往下看, IfElseActivity元素表示我们添加的条件,它对应于WinWF中的IfElseActivity活动.在XOML中,WinWF元素和活动的名称是相同的.
在SharePoint Designer设计的工作流中, 步骤总是 SequenceActivity元素或者 IfElseActivity元素.
所以这里我们将IfElseActivity元素替换为SequenceActivity元素.
IfElseActivity活动的每一条分支都是一个 IfElseBranchActivity活动,我们不再需要它,把它修改为 WhileActivity.
IfElseBranchActivity.Codition改为 WhileActivity.Codition.
这就是我们之前设计工作流时添加条件的目的,利用条件来生成我们需要的规则文件,因为在本文中,WhileActivity循环的条件也是 finish=false.
现在原来的IfElseActivity已经被修改为SequenceActivity和及其子元素WhileActivity了.
4.WhileActivity的子活动
在WinWF中, WhileActivity有且只能有一个子活动,然而我们现在的WhileActivity中却包含了多个子活动(基本上一个元素就是一个子活动),所以我们还需要添加一个SequenceActivity将其余的子活动包含在内.
然后我们来看看这些SequenceActivity的子活动们.
5.LookUpActivity与SharePoint Designer自动生成的变量
LookUpActivity的名称空间前缀是ns0,表示它是一个SharePoint Workflow Action.
有过Visual Studio工作流开发经验的朋友一定会想起CreateTask等活动,不错,LookUpActivity与CreateTask活动同属于SharePoint Workflow Actions,但却有所不同, CreateTask等活动被Visual Studio 2005 Designer for Windows Workflow Foundation支持,支持编码开发;而LookUpActivity等活动基于定义和规则,且不被Visual Studio 2005 Designer for Windows Workflow Foundation支持.
LookUpActivity的作用是从指定的列表项中获取某一域的值,这里,它从我们上传的文档中获取上传者的名称,并将其存储在变量 _x005f_String0中.
_x005f_String0是SharePoint Designer自动生成的变量.其前缀 _x005f_表示它是由SharePoint自动生成的,如果没有此前缀,那么我们可以在SharePoint Designer工作流设计器中看到此变量,中间的 String表示其类型,末位 0表示序号(这也是SharePoint Designer自动生成的中间变量的命名规则).
6.CollectDataTask
CollectDataTask用来收集用户数据(创建任务),它的属性描述了该任务的内容类型,分配对象,标题,甚至GUID(CollectDataTask将任务的 TaskID绑定到了变量 taskID上).
7.FindValueActivity
FindValueActivity的作用大概和LookUpActivity差不多,但是FindValueActivity会提供一个默认值,本文的实验中它的存在与否似乎无关紧要,于是删之.
8.又一个LookUpActivity
接着又是一个LookUpActivity,将其ListItem属性值中的 _x005f_Int320修改为 taskID,这样LookUpActivity就会从Task In While?任务中获取 canFinish域的值并将其存储在变量 _x005f_Boolean0
9.SetVariableActivity
SetVariableActivity是一个给变量赋值的活动,这里它将 _x005f_Boolean0的值赋给变量 finish.
10.最终的XOML文件及其逻辑
OK,所有活动已经介绍并且修改完毕,最终的XOML文件内容如下:
< ns0:RootWorkflowActivityWithData x:Class = "Microsoft.SharePoint.Workflow.ROOT"x:Name="ROOT"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:ns0="clr-namespace:Microsoft.SharePoint.WorkflowActions;Assembly=Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0, Culture=neutral, PublicKeyToken=null">
     < ns0:RootWorkflowActivityWithData.WorkflowFields >
         < ns0:WorkflowDataField Name = "__list"Type="System.String" />
         < ns0:WorkflowDataField Name = "__item"Type="System.Int32" />
         < ns0:WorkflowDataField Name = "__context"Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" />
         < ns0:WorkflowDataField Name = "__initParams"Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties" />
         < ns0:WorkflowDataField Name = "__workflowId"Type="System.Guid" />
         < ns0:WorkflowDataField Name = "finish"Type="System.Boolean" />
         < ns0:WorkflowDataField Name = "taskId"Type="System.Int32" />
         < ns0:WorkflowDataField Name = "_x005f_String0"Type="System.String" />
         < ns0:WorkflowDataField Name = "_x005f_Boolean0"Type="System.Boolean" />
         < ns0:WorkflowDataField Name = "_x005f_Int320"Type="System.Int32" />
     </ ns0:RootWorkflowActivityWithData.WorkflowFields >
     < ns0:OnWorkflowActivated WorkflowProperties = "{ActivityBind ROOT,Path=__initParams}"x:Name="ID1">
         < ns0:OnWorkflowActivated.CorrelationToken >
              < wf0:CorrelationToken Name = "refObject"OwnerActivityName="ROOT"xmlns:wf0="http://schemas.microsoft.com/winfx/2006/xaml/workflow" />
         </ ns0:OnWorkflowActivated.CorrelationToken >
     </ ns0:OnWorkflowActivated >
     < ns0:ApplyActivation __Context = "{ActivityBind ROOT,Path=__context}"x:Name="ID2"__WorkflowProperties="{ActivityBind ROOT,Path=__initParams}" />
     < SequenceActivity x:Name = "ID6"Description=" 步骤 1 ">
         < WhileActivity x:Name = "ID3">
              < WhileActivity.Condition >
                   < RuleConditionReference ConditionName = "__Rule_ID3_1" />
              </ WhileActivity.Condition >
              < SequenceActivity x:Name = "subSequence">
                   < ns0:LookupActivity ListId = "{}{A4716DC6-6214-4B4E-A400-BBEEEFBA74CD}"x:Name="ID9"FieldName="Author"LookupFunction="LookupUser"__Context="{ActivityBind ROOT,Path=__context}"ListItem="{ActivityBind ROOT,Path=__item}">
                       < ns0:LookupActivity.ReturnValue >
                            < ActivityBind Name = "ROOT"Path="_x005f_String0" />
                       </ ns0:LookupActivity.ReturnValue >
                   </ ns0:LookupActivity >
                   < ns0:CollectDataTask x:Name = "ID8"ContentTypeId="0x01080100D337657FD8FFC44B8D75294F67F6900E00E892A7A4399FB5499230A2887D54EDD4"TaskId="{ActivityBind ROOT,Path=taskId}"Title="Task In While?"InProperties="{x:Null}"__Context="{ActivityBind ROOT,Path=__context}"OutProperties="{x:Null}"AssignedTo="{ActivityBind ROOT,Path=_x005f_String0}" />
                   < ns0:LookupActivity ListId = "{}{B0880D9F-DD1C-47AA-9369-FB1081BF054C}"x:Name="ID11"FieldName="canFinish"LookupFunction="LookupBool"__Context="{ActivityBind ROOT,Path=__context}"ListItem="{ActivityBind ROOT,Path=taskId}">
                       < ns0:LookupActivity.ReturnValue >
                            < ActivityBind Name = "ROOT"Path="_x005f_Boolean0" />
                       </ ns0:LookupActivity.ReturnValue >
                   </ ns0:LookupActivity >
                   < ns0:SetVariableActivity x:Name = "ID10"ValueType="System.Boolean">
                       < ns0:SetVariableActivity.Variable >
                            < ActivityBind Name = "ROOT"Path="finish" />
                       </ ns0:SetVariableActivity.Variable >
                       < ns0:SetVariableActivity.Value >
                            < ActivityBind Name = "ROOT"Path="_x005f_Boolean0" />
                       </ ns0:SetVariableActivity.Value >
                   </ ns0:SetVariableActivity >
              </ SequenceActivity >
         </ WhileActivity >
     </ SequenceActivity >
</ ns0:RootWorkflowActivityWithData >
如我们之前的描述,工作流启动之后,WhileActivity将检查变量finish的值,如果为false(默认就是false),则执行WhileActivity的子活动.
WhileActivity的子活动的执行过程是:LookUpActivity获取文档的创建者, CollectDataTask为文档创建者分配任务,待任务完成后, LookUpActivity获取任务中canFinish域的值, SetVariableActivity将其值赋给变量finish.
子活动执行完毕,WhileActivity再次检查finish的值,而此时finish的值可能被SetVariableActivity改变,从而根据此值来继续或停止循环.
11.工作流的关联与测试
现在保存XOML文件并关闭,然后双击以工作流方式打开,因为我们修改了XOML文件,所以相比之前的图片有所区别.

步骤1中只包含一个操作: 子步骤 (ID:ID3).在该工作流的XOML文件中可以看到,ID3正是WhileActivity的ID,说明SharePoint Designer可以识别WhileActivity,但无法正确的将其表示出来.
点击 完成来完成工作流与文档的关联,如果忽略了这一步,SharePoint中的工作流将不发生任何变化.
最后来 测试一下,编辑任务时,不要勾选canFinish,则工作流会自动再分配一项任务,直到你勾选了canFinish.

总结
通过修改SharePoint Designer生成的XOML文件,使SharePoint Designer设计的工作流能够支持WhileActivity,那我们也有理由相信它可以支持更多的WinWF活动.
而且,SharePoint Workflow Actions中的两类活动虽然使用方法不尽相同,但是实现的功能却是一样的(如CreateTask和CollectDataTask),这是不是意味着使用Visual Studio开发的工作流也可以使用SharePoint Designer间接的设计出来?
虽然经过修改的工作流已经无法在SharePoint Designer中再设计,那么我们可不可以扩展SharePoint Designer的工作流设计器使其支持更加复杂的工作流?或者干脆开发第三方工作流设计工具?
留待慢慢研究…
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SharePoint工作流是一种自动化的流程,可以在SharePoint环境中管理和协调业务流程。它可以帮助您自动化和简化商业流程,例如审批、任务协作、申请流程等等。以下是一些关于SharePoint工作流的常见问题和答案: 1. SharePoint工作流是什么? SharePoint工作流一个自动化的流程,它可以在SharePoint环境中管理和协调业务流程。它可以帮助您自动化和简化商业流程,例如审批、任务协作、申请流程等等。 2. SharePoint工作流有哪些类型? SharePoint工作流有三种类型:序列工作流、状态机工作流和外部工作流。 3. 序列工作流和状态机工作流有什么区别? 序列工作流是一种线性流程,每个操作都必须按照指定的顺序执行。状态机工作流是一种基于状态的流程,每个操作都是基于当前状态和触发条件执行。 4. SharePoint工作流可以用于哪些业务流程? SharePoint工作流可以用于各种业务流程,例如审批流程、任务协作流程、申请流程、报告流程等等。 5. SharePoint工作流的优点是什么? SharePoint工作流可以帮助您自动化和简化商业流程,节省时间和精力。它还可以提高效率和准确性,减少错误和遗漏。 6. SharePoint工作流如何创建? SharePoint工作流可以使用SharePoint Designer、Visual Studio或第三方工具创建。 7. SharePoint工作流如何启动? SharePoint工作流可以通过列表、文档库、网站或其他应用程序启动。 8. SharePoint工作流如何监视和管理? SharePoint工作流可以通过工作流状态页面、日志文件、任务列表等方式进行监视和管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值