为 SharePoint 创建版本流
以下是我使用 Microsoft Flow 和 SharePoint Online 进行的一个实验,用于在文档更改时访问版本信息
背景
我通常认为,在大多数情况下,当我们谈论内容管理时,记录应与文档分开。文档通常是在协作过程的一部分创建的,而记录通常是在合规过程的一部分创建的。为了尝试支持这一原则,我尝试使用 SharePoint 进行一些模拟,将文档的主要版本发送到另一个系统(在本例中为电子邮件),以最小的用户交互来模拟记录保存过程。
问题是,SharePoint 无法轻松公开文档版本信息。我尝试搜索了一下,但没有找到太多有帮助的信息。这时 Microsoft Flow 就派上用场了。
Microsoft Flow
Microsoft Flow 是一个低代码工作流工具,可以连接到 SharePoint Online,功能相当强大。使用 Flow,我着手设计了一个工作流,该工作流将监视 SharePoint Online 文档库,并在发布主要版本时采取行动。但是,要做到这一点,我需要能够获取文件的版本信息。解决方法基本上是使用 SharePoint Online API 在文档更改时检索版本信息,并在版本为主要版本更改时根据该信息采取行动。让我们深入了解工作流是如何构建的。
步骤 1 - 文件更改触发器

第一步是监视 SharePoint 的文件更改。将其添加为起始触发器,并提供您要管理的站点和文档库。
步骤 2 - 获取文件元数据

接下来,我们添加一个操作来获取文件元数据。再次提供相关站点,并添加从触发器传递的动态“文件标识符”对象。
步骤 3 - 获取文件属性

最后,我们添加一个操作来获取文件的属性。这次,我们再次指定站点和文档库,并将已更改文件的 ItemID
传递过去。
步骤 4 - 发送 HTTP 请求

现在到了比较棘手的部分。我们在“发送 HTTP 请求”操作中使用从前面步骤收集的信息来检索 SharePoint 存储的有关文件的某些属性。再次指定我们正在使用的站点,将请求类型设置为 GET
,并使用以下 API 端点来检索文档属性:
_api/web/GetFolderByServerRelativeUrl('$FolderPath')/Files('$FileName')
确保您将 $FolderPath
替换为动态的“文件夹路径”对象,将 $FileName
替换为动态的“带扩展名的文件名”对象。
注意:之前,我使用以下端点来检索与文件相关的所有版本。最近,有人指出该端点不包含文档的当前版本。我不确定这是否是最近更改的,还是我遗漏了。
_api/web/GetFolderByServerRelativeUrl('$FolderPath')/Files('$FileName')/Versions')
步骤 5 - 解析 JSON

HTTP 请求操作将返回一个 JSON 对象,我们现在需要对其进行解析,因此添加一个“解析 JSON”操作,并指定上一个操作中的“Body
”对象。在提供架构方面,您有两个选项。首先,您可以将流运行到步骤 4,复制返回的结果,然后单击“使用示例载荷生成架构”选项来定义架构。或者,您可以使用我生成的架构,这应该是 SharePoint Online 的标准、开箱即用的架构(截至本文撰写之时)。
{
"type": "object",
"properties": {
"d": {
"type": "object",
"properties": {
"__metadata": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"uri": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"Author": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"CheckedOutByUser": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"EffectiveInformationRightsManagementSettings": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"InformationRightsManagementSettings": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"ListItemAllFields": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"LockedByUser": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"ModifiedBy": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"Properties": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"VersionEvents": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"Versions": {
"type": "object",
"properties": {
"__deferred": {
"type": "object",
"properties": {
"uri": {
"type": "string"
}
}
}
}
},
"CheckInComment": {
"type": "string"
},
"CheckOutType": {
"type": "integer"
},
"ContentTag": {
"type": "string"
},
"CustomizedPageStatus": {
"type": "integer"
},
"ETag": {
"type": "string"
},
"Exists": {
"type": "boolean"
},
"IrmEnabled": {
"type": "boolean"
},
"Length": {
"type": "string"
},
"Level": {
"type": "integer"
},
"LinkingUri": {
"type": "string"
},
"LinkingUrl": {
"type": "string"
},
"MajorVersion": {
"type": "integer"
},
"MinorVersion": {
"type": "integer"
},
"Name": {
"type": "string"
},
"ServerRelativeUrl": {
"type": "string"
},
"TimeCreated": {
"type": "string"
},
"TimeLastModified": {
"type": "string"
},
"Title": {
"type": "string"
},
"UIVersion": {
"type": "integer"
},
"UIVersionLabel": {
"type": "string"
},
"UniqueId": {
"type": "string"
}
}
}
}
}
此载荷和 JSON 解析为我们提供了许多有用的变量,包括主要和次要版本号。
深入探讨
为了更进一步,以下是一些可选步骤,我添加这些步骤来确定文档是否为主要版本(x.0),如果是,则模拟一个“将文件保存为记录”的电子邮件来证明该过程。
步骤 6 - 只处理主要版本

我只想处理主要版本,因为从这个工作流的角度来看,我将主要版本保存为记录实例。因此,让我们添加一个条件来检查最新版本是否为主要版本,方法是检查 JSON 解析中的次要版本变量是否设置为 0
。
步骤 7 - 示例动态属性

Flow 的最后一个步骤显示了一个电子邮件操作,其中包含一系列您可以使用的动态内容,这些内容将在 Flow 的末尾使用。在此示例中,我将向文件创建者发送一封电子邮件,其中包含有关已发布版本的信息、在 SharePoint Online 中运行的发布命令附带的任何注释,以及附件到电子邮件中的文件。
奖励!- 将版本号保存到文档属性
在此原始帖子的评论中,Eyo Sama 和 Dave Albrecht 在将版本号保存到文档以便在文档本身中使用时遇到了一些问题。让我们来扩展上面的 Flow,创建一个 status
字段来保存当前版本。在 SharePoint 中,添加一个新列(我称之为 status
)来保存版本标签。添加新列后,它将在 Word 的文档属性中可用,并可用于“快速部件”之类的函数。
奖励步骤 1 - 锁定布尔值

我们需要做的第一件事是创建一个变量来测试“锁定使用中”问题。因为我们将更新文档,所以我们需要确保它不会被锁定编辑。最初将此变量设置为 true
。
奖励步骤 2 - 循环

接下来,添加一个 do until
循环,以便我们可以在文档被锁定时重试将版本添加到文档属性。
奖励步骤 3 - 作用域和文档签出

循环中的第一个操作是尝试执行文档签出,以便我们可以在不创建新版本的情况下更新文档属性。我们希望在作用域内尝试签出此文档。Microsoft Flow 中的作用域允许我们实现 Try
/Catch
逻辑,也就是说,我们可以尝试执行一系列任务并输出这些任务的结果。在这种情况下,我们执行一个 HTTP Post
请求来签出文档,因此再次指定我们正在使用的站点,将请求类型设置为 POST
,并使用以下 API 端点来签出文档:
_api/web/GetFolderByServerRelativeUrl('$FolderPath')/Files('$FileName')/CheckOut()
奖励步骤 4 - 检查结果

现在让我们检查 scope
语句的结果。我们通过检查我们使用 if
语句和以下动态表达式创建的 scope
的结果来做到这一点:
result('Scope')[0]['status']
上面语句中的 Scope
指的是我们在上一步中添加的 Scope
语句的名称。
奖励步骤 5 - 即使失败也要继续运行

默认情况下,Microsoft Flow 会在流中的某个项目失败时停止处理。因为我们对此有计划,所以我们需要将 if
语句设置为即使 Scope
组失败也要运行。单击 if
语句标题栏上的三个点 (…),然后选择“配置运行后操作”,并确保所有退出状态都已勾选。
奖励步骤 6a - 成功!更新版本

如果作用域成功,那么我们已经签出了文件。如果我们添加“更新文件属性”项,使用我们正在处理的站点和库,并指定 itemId
,您应该还会看到与文档库关联的任何其他文档属性。如您所见,我库中的状态文档属性显示出来,我已向该属性添加了版本标签。
奖励步骤 6b - 成功!重新签入

现在我们已经填充了版本属性,让我们使用另一个 HTTP 命令将其重新签入。再次指定我们正在使用的站点,将请求类型设置为 POST
,并使用以下 API 端点来签入文档:
_api/web/GetFolderByServerRelativeUrl('$FolderPath')/Files('$FileName')/CheckIn(checkintype=2)
我们使用签入类型 2 来签入文档,而无需增加版本号。供您参考,类型 0 是增加次要版本,类型 1 是增加主要版本,类型 2 是覆盖且版本不变。
奖励步骤 6c - 成功!关闭循环

最后,我们通过将 lock
变量设置为 false
来关闭循环。这确保我们不会一直循环并重复工作。
奖励步骤 7 - 处理失败

让我们处理文档被打开编辑或签出的情况下的失败状态。首先,创建一个 if
语句来检查我们尝试签出文档的次数。我们这样做是因为我们不希望 Flow 无限循环。我将我的迭代次数设置为 20。如果迭代次数等于或大于 20,则将 Is Locked
变量设置为 false
。这将中断我们的循环并基本上关闭 Flow。如果您愿意,也可以在此处发送警告,但我假设如果在尝试 20 次后仍无法更新,则有人仍在更改文档,并且将会有另一次保存。如果我们还没有达到迭代限制,让我们添加一个延迟,这样我们就不必每隔几秒/几分钟就尝试一次。在这种情况下,我添加了五分钟的延迟。根据您的用户,您可以根据需要增加或减少此值。
后续步骤
所以,从头到尾,这就是(非奖励部分的)完整工作流。

如果这是一个生产环境的交付项,例如,我们可以使用此 Flow 并添加一个操作来调用录制保存系统的 API,通过 HTTP POST 将文档和收集的元数据发送出去,从而独立于用户的交互来保存记录。或者我们可以执行任何其他类似的操作。
历史
本文已更新,以反映使用版本端点时遇到的一些问题,并发布版本数据回文档属性。