应用对象
Microsoft 365 中的 SharePoint Microsoft 365 小型企业版中的 SharePoint

作者:Justin Joyce,LANtek

注意: 本文是 SharePoint 最终用户 获取点 博客四年文章集的一部分。

概述:不带代码的自定义老化报表

SharePoint 网站经常请求的功能部分之一是任务或列表项的过期报表。 换句话说,自上次修改此列表项以来,它已经多少天/月了?

从表面上看,这似乎是一个非常简单的要求。 毕竟,我们有要创建和修改的项的日期,当通过事件接收器对项目进行某些更改时,我们可以存储自定义日期。 我们已计算列,其中可以包含类似 Excel 的公式来处理我们的信息。 这似乎是一个相当直接的命题。 我们选取一个日期字段,创建一个计算列,然后按照 [DateField] – [Today] 行执行公式作。 啊,没那么快! 任何尝试过此“简单”任务的人都知道,尝试在计算列中使用类似 [Today] 的内容会导致问题。 尝试将 [Today] 插入计算列的公式框中将显示如下所示的错误消息:

错误消息

为什么会这样? 嗯,这与计算列的计算方式有关。

让我们以一个简单的公式为例:

= IF ( [Column1]<=[Column2], “OK”, “Not OK”)

所有这说明是,如果 Column1 小于或等于 Column2,则显示“确定”,否则显示“不确定”。 这是计算列的一个相当典型的基本公式,它对包含这些列的列表项进行了基本假设:Column1 和 Column2 的值在列表项上没有 Update 事件时永远无法更改。

没错,计算列仅在列表更新 (或创建) 时重新计算,因为它们假定你正在计算的信息包含在项本身中。 当你尝试使用与项字段无关的内容(例如今天日期)时,这会产生问题。

现在,我没有参加会议,他们决定计算列的工作方式是这样,但是,如果我不得不做出有根据的猜测,我会假设它们以这种方式工作,以达到性能。 假设你有一个包含数千个项目的列表,其中每个项都包含一个需要“实时”更新的计算列。 这意味着某些机制(可能是计时器作业)必须经常循环访问包含该计算列的每个项,并更新其值。 这在性能方面可能非常繁重,因为对于更大的部署,此作业可能会不断运行和更改内容。 这只是我的猜测, 但如果你考虑一下, 它就很有意义了。

有一些关于类似解决方案的建议,这些建议涉及先创建一个名为 Today 的列,再将其添加到公式中,然后删除它,从而诱使 SharePoint 接受 Today 值。 这些都是很好和好的,但请记住我在更新计算列时所说的话。 仅当更新项目时,此值才会更改,这意味着你的值很快就会不正确,尤其是在一天计算的情况下。

我见过其他人使用巧妙的 JavaScript 将值写入页面。 这也可以工作,但几乎断然反对客户端脚本,如果可以避免它。

实现:

那该怎么做呢? 计算列不适用于所谓的“易失性”函数,例如 Today。 我们可以开发一些自定义代码来处理这一点,例如计算列、计时器作业或计划进程,以便随之而来并更新需要进行此计算的每个单个项。 这让我们回到了我在最后一段中提到的性能问题,此外,它是一个脆弱的解决方案,将高度特定于相关的网站/列表/列。 除了这两个问题,你还必须去找一个书的人,如我自己,知道如何编码并说服他为你开发这个解决方案。 但有一种更简单的方法!

如果您有权在网站上创建字段和编辑页面,并且对 XSLT 和创建视图有一些了解,则可以将可包含在列表视图中的 XSL 模板组合在一起,并在每次请求页面时忠实地计算值。 此方案消除了我们对性能的担忧,并且不需要通过解决方案开发和部署自定义代码。

非常好。 那么,我们如何做到呢?

  1. 创建或选择将充当源的字段。 它必须是日期类型。

  2. 创建将用作所计算值的占位符的字段。

  3. 将这两个字段添加到内容类型,并将该内容类型添加到列表。

  4. 创建包含源列和占位符列的列表视图。

  5. 将 XSL 模板上传到样式库。

  6. 通过 UI 设置列表视图 Web 部件的“XSL 链接”属性。

  7. 成功!

让我们探讨一个示例用例,并演练实现。 我们的客户希望查看其main列表,以告知他们特定列表项处于其状态的时间。 此列表包含从 Item 类型派生并添加到列表的自定义网站内容类型。 已经有一个事件接收器,每次列表项上的状态字段发生更改时,该事件接收器都会捕获该日期,并将该日期保存到名为“已更改日期状态”的列中。 所有这些接线都不是必需的,并且可以使用任何日期字段完成 (恰好发生这种情况,这是我们的实现,但请随意试验) 。 你需要的最小需求是源日期字段和占位符字段,用于保存计算 (下一段中) 添加到列表的更多内容,不过我建议使用网站栏和网站内容类型,以防你想要在网站上的其他位置重复使用此解决方案。

因此,我们有了源日期,可以在针对当前日期进行计算时使用。 现在,我们可以创建自定义网站栏,用作计算值的容器。 在这种情况下,我选择使用计算列,因为它无法在新的或编辑项窗体上进行更改,但可以选择在视图中显示,因为我们不希望用户在此列中输入任意值。 它可能会令人困惑,为什么它没有显示在视图中,等等。

创建网站栏后,可以将其添加到将在列表中使用的内容类型。 接下来,我们需要创建稍后将使用 XSLT 自定义的视图。 请确保创建一个标准视图,其中包含源日期列和将充当计算值的占位符的新计算列。

现在,我们已准备好支持自定义老化报表所需的一切。 剩下的就是创建 XSL 模板,将其上传到网站的样式库,并将其链接到列表视图。 我们将使用的 XSL 模板将包含一些用于生成视图的普通 SharePoint 生成的标记,以及我们自己的自定义标记,用于替代此部分并为我们计算所需的值。

MSDN 论坛上的“swirch”慷慨地提供了用于执行我用于此解决方案的实际计算的 XSL 模板:http://social.msdn.microsoft.com/Forums/en-US/sharepointcustomization/thread/aeda905b-9bc6-40c4-bd22-21306c5cb0d2/

下载 XSL 样式表, (aging.zip) 位于此处:https://OneDrive.live.com/?cid=c262e8e2d59a86d9&permissionsChanged=1&id=C262E8E2D59A86D9!104

在喜欢的文本编辑器中打开此内容,你将看到许多用于呈现视图的普通 SharePoint XSL 标记,如果继续向下滚动到第 357 行,你将看到我添加到标记的自定义模板的开头,第一个是“DateDiff”模板,后跟“calculate-julian-day”和“FieldRef_printTableCell_EcbAllowed.Days_x0020_At_x0020_Status”。 这是我们的三个模板,它们将在视图中生成并显示我们的计算。 如果要使用与本文前面指定的字段名称不同的字段名称,则需要浏览这些模板并替换对其他名称的任何引用。 请记住,为此,需要使用字段的内部名称,而不是显示名称。

对模板准备就绪后,导航到样式库并将其上传到“XSL 样式表”文件夹下,然后复制文件的链接。 这将使我们能够稍后轻松对其进行更改,或根据需要将其添加到网站的不同部分。

接下来,转到列表,选择本文前面创建的视图。 在“网站作”菜单中,单击“编辑页面”。

“网站操作”菜单上的“编辑页面”命令

在页面上找到列表视图 Web 部件,并通过单击右上角的向下小箭头打开 Web 部件菜单。 从此菜单中选择“编辑 Web 部件”。

“Web 部件”菜单上的“编辑 Web 部件”命令

这会在浏览器窗口右侧打开 Web 部件的菜单。

Web 部件菜单

单击“杂项”部分的 + 并找到“XSL 链接”属性。

“Web 部件”菜单上的“XSL 链接”属性

粘贴之前复制的样式库中 XSL 文件的链接, (此链接可以是相对链接或绝对链接) 。

粘贴的 XSL 文件链接

单击“确定”保存更改,然后单击页面顶部“页面”功能区上的“停止编辑”按钮。

“页面”选项卡上的“停止编辑”按钮

如果已正确配置所有内容,现在应在“状态为天数”列中看到数字。

显示数字的“状态”列中的天数

最后,以下是不同日期的一些测试数据的外观:

显示测试数据的帐龄分析表

摘要:

这是一种格式良好、可靠且性能更好的方法,用于在 SharePoint 中创建过时的报表。通过简单的无代码实现完成。 除了我们在此处探讨的一个用例之外,这还具有相当多的潜在应用程序。 这种类型的报表的另一种常见方案是将其附加到任务列表,以便你可以一目了然地查看创建任务以来的时长。

祝使用愉快!

--贾斯汀

贾斯汀·乔伊斯,拉恩泰克

批注

缺少步骤 2012/10/8 凌晨 3:51 好吧,我遵循了这些步骤,但一定缺少一些内容 - XSL 如何知道要使用哪个日期,或者要添加自该日期到哪个字段? 错过步骤时讨厌它。

无代码,同意! 8/30/2012 12:12 PM 我同意 - 我不认为这真的算不上“没有代码”。有趣的是,通过 SharePoint 的一些搞砸,我有一个工作计算列使用 Today...不确定如何或为什么,因为我不能再做一次, 但那个仍然在那里和工作。

“状态为天数”计算列的公式? 2012/5/2 上午 7:39 Justin - 你用于“状态中的天数”计算网站栏 (占位符列) 的公式是什么? 是“=today”吗?

SharePoint 2007 2011/12/2 上午 11:29 目前,我尚未尝试将此解决方案应用于 SharePoint 2007,但我正在寻找它。 遗憾的是,Web 部件上没有通过 UI 显示 XslLink 属性。

伟大的帖子 2011/11/30 上午 9:53 你好 伟大的帖子。我使用的是 SharePoint 2007。我没有如上所述的杂项部分。是否有 SP2007 配置的步骤? 谢谢。

重:无代码解决方案:显示自上次更改 SharePoint 列表项以来的天数 2011/10/11 上午 8:24 你好克里斯很好的发现! 我将看看你今天晚些时候发布的内容,看看我是否可以使此解决方案更可靠一点。我很高兴你喜欢这个帖子, 我很高兴你能够找到欧洲日期格式的解决方案。 :) -贾斯汀

欧洲日期格式解决方案 2011/10/11 上午 6:45 大家好贾斯汀, FYI,我找到了一个解决方案,我之前在此页面上提到的问题:https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/

欧洲日期格式 2011/10/7 凌晨 3:59 你好贾斯汀, 这是一个非常好的解决方案,谢谢,只是我花了过去两天寻找的东西! 然而, 我有点问题, 我希望你能帮助我。我稍微更改了代码,以计算某些事情发生之前的天数,而不是从此,通过切换“DateDiff”函数的最后一行中的变量; <xsl:value-of select=“$JulianToday - $JulianStartDate”></xsl:value-of> 但是,我只能让它正确限定差异的一半时间。 例如,使用此日期 (格式 dd/MM/yyyy) ; 30/12/2011 计算正确,但此日期 (相同的格式) 2011/12/10 计算结果就像 2011 年 12 月 10 日,而不是 2011 年 10 月 12 日一样。我只是尝试在“JulianStartDate”变量中切换日值和月份值的位置,如下所示: <xsl:with-param name=“Month” select=“substring (ddwrt:FormatDateTime (string ($StartDate) , 1033, 'yyyyMdd') ,7,2) ”/> <xsl:with-param name=“Day” select=“substring (ddwrt:FormatDateTime (string ($StartDate) , 1033, 'yyyyMdd') ,5,2) ”/> 这更正了第二个日期的问题,但第一个日期不正确! 我还尝试更改 FormatDateTime 调用以使用欧洲 LCID,对 FormatDateTime (的最后一个参数(例如 ddMMyyyy、MMddyyyy) 进行了适当调整,但未成功。我非常感谢你能提供的任何建议。谢谢 克里斯

无代码 9/21/2011 4:27 AM 我不认为 XSL 符合“无代码”解决方案的资格,因为理解 XSL 语言并不适合每个人 ,但它不涉及编程。 除此之外:很好的解决方案,谢谢!

需要更多帮助?

需要更多选项?

了解订阅权益、浏览培训课程、了解如何保护设备等。