無程式碼解決方案:顯示自上次變更清單項目以來的天數

作者:Justin Joyce,LANtek

注意

本文是為期四年的 Get the Point 部落格文章集的一部分,適用於 SharePoint 終端使用者。

概觀:無程式碼的自訂老化報告

SharePoint 網站經常要求的功能之一是工作或清單項目的老化報告。 換句話說,自從上次修改此清單項目以來已經過多少天/月份?

從表面上看,這似乎是一個非常簡單的請求。 畢竟,我們有創建和修改項目的日期,我們能夠通過事件接收器對項目進行某些更改時存儲自定義日期。 我們有計算欄,可以包含類似 Excel 的公式來處理我們的資訊。 這似乎是一個非常直接的提議。 我們挑選日期欄位、建立計算結果欄,然後執行類似 [DateField] – [Today] 的公式。 啊,不過沒那麼快! 任何嘗試過這個「簡單」任務的人都知道,嘗試在計算欄中使用類似 [Today] 的內容會導致問題。 嘗試在計算欄的公式方塊中插入 [今天] 時,會出現類似以下的錯誤訊息:

錯誤訊息

這是怎麼回事? 嗯,這與計算列的計算方式有關。

讓我們以一個簡單的公式為例:

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

以上說明,如果 Column1 小於或等於 Column2,則顯示 [確定],否則顯示 [不確定]。 這是相當典型的計算資料行基本公式,它會針對包含這些資料行的清單項目進行基本假設: 如果沒有清單項目上的 Update 事件,Column1 和 Column2 的值將無法變更。

沒錯,計算結果欄只有在更新 (或建立清單時才會重新計算) 因為它們假設您正在計算的資訊包含在項目本身中。 當您嘗試使用與項目欄位無關的變更項目時,就會發生問題,例如今天的日期。

現在我沒有參加會議,他們決定這是計算列的運作方式,但是,如果我必須做出有根據的猜測,我會假設它們以這種方式運作是為了效能。 想像一下,假設您有一份包含數千個項目的清單,其中每個項目都包含需要「即時」更新的計算結果欄。 這表示某種機制 (可能是計時器作業) 必須每隔一段時間迭代包含該計算欄的每個項目,並更新其值。 就效能而言,這可能會非常繁重,因為在較大的部署中,此作業可能會不斷執行並變更內容。 這只是我的猜測,但仔細想想,這很有道理。

坊間流傳著類似解決方案的一些建議,涉及透過先建立名為 Today 的欄,然後將其新增至公式,然後將其刪除,誘騙 SharePoint 接受 Today 值。 這些都很好,但請記住我所說的當計算列更新時。 此值只有在項目更新時才會變更,這表示您的值很快就會不正確,尤其是在日計算的情況下。

我見過其他人使用巧妙的 JavaScript 將值寫入頁面。 這也有效,但當可以避免時,我幾乎斷然反對客戶端腳本。

實作:

那該怎麼辦呢? 計算欄對於像 Today 這樣的所謂「變動性」函數來說是不可能的。 我們可以開發一些自定義代碼來為我們處理這個問題,例如計算列、計時器作業或計劃過程來更新需要進行此計算的每個項目。 不過,這讓我們回到了我在上一段中提到的性能問題,而且它是一個脆弱的解決方案,非常特定於所討論的網站/列表/欄。 除了這兩個問題之外,您還必須去找一個像我這樣知道如何編碼並說服他為您開發此解決方案的書呆子。 但有一個更簡單的方法!

如果您有權在您的網站上建立欄位和編輯頁面,並且對 XSLT 和建立視圖有一些知識,您可以組合一個可包含在清單視圖中的 XSL 範本,並在每次請求頁面時忠實地計算您的值。 此案例免除我們對效能的擔憂,而且不需要透過解決方案開發和部署自訂程式碼。

太棒了。 那麼我們該怎麼做呢?

  1. 建立或選取要做為來源的欄位。 必須是日期類型。
  2. 建立我們的欄位,做為正在計算之值的預留位置。
  3. 將這兩個欄位新增至內容類型,並將該內容類型新增至清單。
  4. 建立該清單的檢視,其中包含來源和預留位置欄。
  5. 將 XSL 範本上傳至樣式庫。
  6. 透過 UI 設定清單檢視網頁組件的「XSL 連結」屬性。
  7. 成功!

讓我們探索一個範例用例並逐步完成實作。 我們的客戶想要查看他們的主列表,以告訴他們特定列表項目在其狀態下放置了多長時間。 此清單包含從項目類型衍生並新增至清單的自訂網站內容類型。 已經有事件接收器可以擷取清單項目上的每次狀態欄位變更的時間,並將該日期儲存到名為「狀態變更日期」的欄位中。 所有這些佈線都不是必需的,可以使用任何日期字段完成 (碰巧這是我們的實現,但請隨意嘗試) 。 您最起碼需要的是來源日期欄位和佔位符欄位,以保存您的計算 (下一個段落中的更多內容,) 新增至您的清單中,儘管我建議您使用網站欄和網站內容類型,以防您希望在網站上的其他地方重複使用此解決方案。

因此,我們有了來源日期,可以在今天的日期進行計算時使用該日期。 現在,我們可以建立自訂網站欄,來做為計算值的容器。 在這種情況下,我選擇使用計算欄,因為它無法在新表單或編輯項目表單上更改,但可以選擇以在視圖中顯示,因為我們不希望用戶在此表行中輸入任意值。 為什麼它沒有顯示在視圖等中可能會令人困惑。

現在我們有了網站欄,我們可以將其添加到我們將在列表中使用的內容類型中。 接下來,我們需要建立稍後將使用 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”模板,後面接著“FieldRef_printTableCell_EcbAllowed.Days_x0020_At_x0020_Status”。 這是我們的三個模板,它們將在我們的視圖中進行和顯示我們的計算。 如果您要使用的欄位名稱不同於本文稍早指定的欄位名稱,您必須瀏覽這些範本,並取代其他名稱的任何參照。 請記住,為此,您需要使用欄位的內部名稱,而不是顯示名稱。

一旦您對範本準備就緒感到滿意,請導航到您的樣式庫並將其上傳到「XSL 樣式表」資料夾下,然後向下複製檔案連結。 這將使我們以後可以輕鬆地對其進行更改,或根據需要將其添加到網站的不同部分。

接下來,請前往您的清單,然後選取您在本文稍早建立的檢視。 從 [網站動作] 功能表中,按一下 [編輯頁面]。

[網站動作] 功能表上的 [編輯頁面] 命令

在頁面上尋找您的清單檢視網頁組件,然後按一下右上角向下的小箭號,開啟網頁組件功能表。 從此功能表選取 [編輯網頁組件]。

在 [網頁組件] 功能表上編輯 [網頁組件] 命令

這會在瀏覽器視窗右側開啟網頁組件的功能表。

[網頁組件] 功能表

按一下 [其他] 區段的 +,然後找出 [XSL 連結] 屬性。

[網頁組件] 功能表上的 XSL 連結屬性

將先前複製的 XSL 檔案連結貼入樣式庫中的 XSL 檔案 (這可以是相對或絕對連結) 。

貼入的 XSL 檔案連結

按一下 [確定] 儲存您的變更,然後按一下頁面頂端 [頁面] 功能區上的 [停止編輯] 按鈕。

[頁面] 索引標籤上的 [停止編輯] 按鈕

如果一切都正確設定,您現在應該會在 [狀態天數] 欄中看到數字。

顯示數量的 [狀態天數] 欄

最後,這是不同日期的一些測試數據的樣子:

顯示測試資料的年限報表

摘要:

這就是在 SharePoint 中建立老化報告的格式良好、強健且效能更好的方式。 除了我們在這裡探索的一個用例之外,它還有很多潛在的應用。 這類報表的另一個常見案例是將報表附加至工作清單,以便您一目了然地看到自建立工作以來已經過多少時間。

祝您使用愉快!

--賈斯汀

Justin Joyce,LANtek

註解

遺失的步驟
2012 年 10 月 8 日上午 3:51
好的,我按照了步驟操作,但肯定缺少一些東西 - XSL 如何知道要使用哪個日期,或要將自此以後的天數新增到哪個欄位?討厭錯過步驟。

無代碼,同意!
2012/8/30 下午 12:12
我同意 - 我認為這並不算「無代碼」。
有趣的是,通過 SharePoint 的一些搞砸,我有一個使用今天......不確定如何或為什麼,因為我無法讓它再次這樣做,但那個仍然在那裡並且正在工作。

「狀態天數」計算結果欄的公式?
2012/5/2 上午7:39
Justin - 您用於 [狀態天數] 計算網站欄 (預留位置欄) 公式是什麼? 是 “=today”嗎?

SharePoint 2007
2011 年 12 月 2 日上午 11:29
目前,我尚未嘗試將此解決方案套用到 SharePoint 2007,但我正在研究中。 很抱歉,網頁組件上沒有透過 UI 呈現 XslLink 屬性。

很棒的文章
2011 年 11 月 30 日上午 9:53
您好,
很棒的帖子。
我正在使用 SharePoint 2007。
我沒有上面提到的雜項部分。
您有 SP2007 設定的步驟嗎?
感謝您。

回覆:無程式碼解決方案:顯示自上次變更 SharePoint 清單項目以來的天數
2011/10/11 上午 8:24
您好,Chris。
真是發現!
我希望今天晚些時候會看看你發布的內容,看看我是否可以讓這個解決方案更加強大一點。
我很高興您喜歡這篇文章,也很高興您能夠找到歐洲日期格式的解決方案。 :)
-賈斯汀

歐洲日期格式的解決方案
2011/10/11 上午 6:45 PM
您好,Justin,
僅供參考,我找到了解決我之前在本頁提到的問題的解決方案;
https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/

歐洲日期格式
2011/10/7 上午 3:59 PM
您好,賈斯汀,
這是一個非常好的解決方案,謝謝,而且正是我過去兩天一直在尋找的東西! 然而,我對此遇到了一些問題,我希望你能幫助我。
我稍微更改了您的程式碼,以計算在發生某些事情之前的天數,而不是從此之後,透過切換「DateDiff」函數最後一行中的變數;

<xsl:value-of select=“$JulianToday - $JulianStartDate”></xsl:value-of>

然而,我只能讓它在一半的時間內正確地計算差異。 因此,例如,使用此日期 (格式為 dd/MM/yyyy) ;

30/12/2011

計算是正確的,但此日期 (相同的格式)

12/10/2011

其計算方式彷彿是 2011 年 12 月 10 日,而不是 2011 年 10 月 12 日。
我嘗試簡單地切換「JulianStartDate」變數中日值和月值的位置,如下所示;

<xsl:with-param name=“Month” select=“substring (ddwrt:FormatDateTime (string ($StartDate) , 1033, 'yyyyMMdd') ,7,2) ”/>
<xsl:with-param name=“Day” select=“substring (ddwrt:FormatDateTime (string ($StartDate) , 1033, 'yyyyMMdd') ,5,2) ”/>

這糾正了第二次約會的問題,但第一次約會的問題是不正確的!
我還嘗試更改 FormatDateTime 調用以使用歐洲 LCID,並對 FormatDateTime 的最後一個參數進行各種更改 (例如 ddMMyyyyy、MMddyyyy) ,並對子字符串位置參數進行適當調整,但沒有成功。
我將非常感謝您提供的任何建議。
感謝您,
Chris

No-Code
2011/9/21 上午 04:27
我不認為 XSL 符合「無程式碼」解決方案的條件,因為了解 XSL 語言並不適合所有人 - 但它不涉及程式設計。 除此之外:不錯的解決方案,謝謝!