作成者: Justin Joyce、LANtek
注
この記事は、SharePoint のエンド ユーザーを対象とする Get the Point ブログ (英語) で 4 年間にわたって集めた投稿の一部です。
概要:コードを使用しないカスタム エージング レポート
SharePoint サイトでよく要求される機能部分の 1 つは、タスクまたはリスト アイテムのいずれかのエージング レポートです。 つまり、リスト アイテムの最終更新日以降どれだけの日数または月数が経過したかということです。
この問題は表面的には非常に単純に見えます。 結局、アイテムの作成日および修正日があり、イベント レシーバーを介してアイテムに特定の変更が行われたときそのカスタム日付を格納する機能があります。 Excel のような数式を含めて情報に対して動作させることができる、計算列があります。 これは、非常に簡単な問題のように見えます。 日付フィールドを選択し、計算列を作成し、[DateField] – [Today] に似た数式の計算を行うことです。 でも、そんなに簡単にはいきません。 この "単純な" タスクを試したことがある人なら誰でも知っているように、計算列で [Today] のようなものを使用しようとすると問題が発生します。 集計列の数式ボックスに [今日] を挿入しようとすると、次のようなエラー メッセージが表示されます。
なぜですか? それは、集計列の計算方法に関係しています。
簡単な数式を例として見てみましょう。
= IF( [Column1]<=[Column2], "OK", "Not OK")
これは、Column1 が Column2 以下の場合は OK と表示し、それ以外の場合は Not OK と表示するということです。 これは、集計列のごく一般的な基本的な数式であり、次の列を含むリスト アイテムについての基本的な前提をとります。 Column1 と Column2 の値は、リスト アイテムで Update イベントなしでは変更できません。
そうです、集計列は、計算する情報がアイテム自体に含まれていることを前提としているため、リストが更新 (または作成) されたときにのみ再計算されます。 これにより、アイテムのフィールドとは無関係に変化するもの (今日の日付など) を使用しようとすると、問題が発生します。
私は、計算列がこのように機能すると決定した会議には参加していませんでしたが、知識に基づいた推測をしなければならない場合は、パフォーマンスのためにこのように機能すると仮定します。 数千項目のリストがあり、それぞれに「ライブ」更新が必要な計算列が含まれているとします。 つまり、何らかのメカニズム (タイマー ジョブなど) は、その計算列を含む各アイテムを頻繁に反復処理し、その値を更新する必要があります。 大規模なデプロイでは、このジョブが常に実行され、物事が変更される可能性があるため、これはパフォーマンスの点で非常に負担がかかる可能性があります。 それは私の推測ですが、考えてみるとかなり理にかなっています。
最初に Today という名前の列を作成し、それを数式に追加し、次いで削除して、Today の値を受け入れるように SharePoint をだます同様のソリューションの提案がいくつかあります。 これらはすべて問題ありませんが、計算列が更新されることについて私が説明したことを思い出してください。 この値は、アイテムの更新時にしか変更されず、これはつまり、値 (特に日にちにの計算) がすぐに不正になることを意味します。
他の人が巧妙なJavaScriptを使用して値をページに書き込んでいるのを見たことがあります。 これでも機能しますが、私は使用しないで済むのであればクライアント スクリプトは使用しない方がよいと考えています。
実装:
それではどうすればよいのでしょうか。 集計列は、Today のようないわゆる "揮発性" 関数では問題外です。 計算列、タイマー ジョブ、スケジュール済みの処理などのカスタム コードを開発して、この計算を行う必要のあるすべてのアイテムを完全に更新させることも可能です。 その場合、前のパラグラフで触れたパフォーマンスの問題にまた戻ってきてしまい、加え、これは問題のサイト、リスト、列に固有なものとなってしまうため、もろいソリューションでもあります。 これらの 2 つの懸念に加え、私などのようなコードを作成できるオタクを見つけてきて、このソリューションを開発してくれるよう説得する必要もあります。 しかし、別の簡単な方法もあります。
サイトにフィールドを作成しページを編集する権限があり、XSLT とビューの作成に関する知識が少しある場合、リスト ビューに含めることができる XSL テンプレートを組み合わせて、ページの要求があるたびに値をきちんと計算させることができます。 このシナリオでは、パフォーマンスに関する懸念が解消され、ソリューションを使用してカスタム コードを開発および展開する必要はありません。
完璧です。 では、これはどのようにすればよいのでしょうか。
- ソースとして動作するフィールドを作成または選択します。 これは Date 型である必要があります。
- 計算する値のプレースホルダーの役割を果たすフィールドを作成します。
- これらの 2 つのフィールドをコンテンツ タイプに追加し、そのコンテンツ タイプをリストに追加します。
- ソースとプレースホルダー列の両方を含むそのリストのビューを作成します。
- XSL テンプレートをスタイル ライブラリにアップロードします。
- UI を使用してリスト ビュー Web パーツの "XSL リンク" プロパティを設定します。
- 成功です。
ユース ケースの例を見て、実装方法を見てみましょう。 お客様は、特定のリスト アイテムがそのステータスで放置されている時間を示すメイン リストのビューを望んでいました。 このリストには、アイテム タイプから派生し、リストに追加されたカスタム サイト コンテンツ タイプが含まれていました。 リスト アイテムの状態フィールドが変更されるたびにキャプチャされ、その日付を "状態変更日" という列に保存するイベント レシーバーが既に存在していました。 この配線はすべて必須ではなく、任意の日付フィールドで実行できます (たまたまこれが実装ですが、自由に実験してください)。 最低限必要なのは、計算を保持するためのソースの日付フィールドとプレースホルダー フィールドです (これについては次の段落で詳しく説明します)をリストに追加しますが、サイト上の他の場所でこのソリューションを再利用する場合は、サイト列とサイト コンテンツ タイプを使用することをお勧めします。
そのため、今日の日付に対する計算に使用できるソース日付があります。 これで、計算値のコンテナーとして使用できるカスタム サイト列を作成できます。 この場合、集計列は新規フォームやアイテムの編集フォームで変更できないため、計算列を使用することを選択しましたが、ユーザーがこの列に任意の値を入力することを望まないため、ビューでの表示用に選択できます。 ビューに表示されないなど理由がわからなくなる可能性があります。
これでサイト列があるので、リストで使用するコンテンツ タイプに追加できます。 次に、XSLT で後でカスタマイズするビューを作成する必要があります。 ソース日付列と計算値のプレースホルダーとして機能する新しい計算列を含む標準のビューは必ず作成してください。
これでカスタム エイジング レポートをサポートするために必要なすべての準備が整いました。 あとは、XSL テンプレートを作成し、サイトのスタイル ライブラリにアップロードし、リスト ビューにリンクするだけです。 使用する XSL テンプレートは、SharePoint で生成されるビューを生成するいくつかの標準のマークアップと、その一部をオーバーライドして希望する値を計算してくれる独自のカスタム マークアップを含むことになります。
私がこのソリューションに使用している実際の計算を行うための XSL テンプレートは、MSDN フォーラムの "swirch" によって快く提供されてくれました。
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" が続きます。 これらは、計算を作成してビューに表示する 3 つのテンプレートです。 この記事で前に指定したものとは異なるフィールド名を使う予定の場合は、これらのテンプレートを調べ、他の名前への参照をすべて置き換える必要があります。 このためには、表示名ではなく、フィールドの INTERNAL 名を使用する必要があることに注意してください。
テンプレートの準備が整ったことを確認したら、スタイルライブラリに移動し、「XSL スタイルシート」フォルダーにアップロードし、ファイルへのリンクをコピーします。 これにより、後で楽に変更したり、お好みでサイトの別の部分に追加することができます。
次いで、リストに移動し、この記事で既に作成したビューを選択します。 [サイトのアクション] メニューから [ページの編集] をクリックします。
ページでリスト ビュー Web パーツを探し、右上隅の小さい下向き矢印をクリックして、Web パーツ メニューを開きます。 このメニューから [Web パーツの編集] を選択します。
これにより、ブラウザー ウィンドウの右側に Web パーツのメニューが開きます。
[その他] セクションの [+] をクリックし、[XSL リンク] プロパティを見つけます。
前にコピーしたスタイル ライブラリ内の XSL ファイルへのリンクを貼り付けます (相対または絶対リンクが可能です)。
[OK] をクリックして変更を保存し、ページ上部の [ページ] リボンの [編集の停止] ボタンをクリックします。
すべてが正しく設定されている場合は、[状態日数] 列に番号が表示されます。
最後に、さまざまな日付のいくつかのテスト データがどのように示されるかの例を次に示します。
概要:
このようにすれば、コードを実装せずに、きちんとフォーマットされた、堅固で、よりよく機能する SharePoint の完全なエージング レポートを作成することができます。 これには、ここでのユース ケース以外に可能なアプリケーションがいくつかあります。 この種類のレポートのもう 1 つの一般的なシナリオとして、タスクが作成されてからの経過時間を一目で確認できるように、タスクをタスク リストに添付することです。
最新機能をご利用ください。
--Justin
Justin Joyce、LANtek
コメント
ステップが見つからない
10/8/2012 3:51 AM
わかりました、私は手順に従いましたが、何かが欠けているはずです-XSLはどの日付を使用するか、またはどのフィールドにそれ以降の日を追加するかをどのように知ることができますか?ステップを間違えたときは嫌いです。
ノーコード、同意!
8/30/2012 12:12 PM
私も同意します - これは実際には「ノーコード」とは見なされないと思います。
興味深いことに、SharePointのいくつかの失敗により、私は今日...もう一度やらせることができないので、どのように、なぜかはわかりませんが、そのものはまだそこにあり、機能しています。
"状態日数" 集計列の数式
2012 年 5 月 2 日、午前 7:39
Justin - "状態日数" の集計サイト列 (プレースホルダー列) に使用した数式は何ですか? "=today" でしたか?
SharePoint 2007
12/2/2011 11:29 AM
現在、私はこのソリューションをSharePoint 2007に適用しようとはしていませんが、私はそれを調べています。 残念ながら、UI の Web パーツに XslLink プロパティが表示されません。
素晴らしい投稿
2011 年 11 月 30 日、午前 9:53
こんにちは、
素晴らしい投稿。
SharePoint 2007 を使用しています。
上記のようなその他のセクションはありません。
SP2007 を構成するための手順はありますか。
ありがとうございます。
Re: コードなしのソリューション: SharePoint リスト アイテムの最終更新日以降の日数の表示
10/11/2011 8:24 AM
こんにちは、Chris。
すばらしい発見!
今日の後半にあなたが投稿した内容を見て、このソリューションをもう少し堅牢にできるかどうか見てみましょう。
投稿を気に入ってくれてたこと、またヨーロッパの日付形式のソリューションを見つけてくれたことをとてもうれしく思っています。 :)
-Justin
ヨーロッパの日付形式のソリューション
2011 年 10 月 11 日、午前 6:45
こんにちは、ジャスティン。
参考までに、このページで前に述べた問題の解決策を見つけました。
https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/
ヨーロッパの日付形式
2011 年 10 月 7 日午前 3:59
ジャスティンさん、こんにちは。
これは本当に良い解決策です、ありがとう、そしてまさに私がこの2日間探してきたようなものです! しかし、私はそれについて少し問題を抱えており、あなたが私を助けてくれることを望んでいました。
「DateDiff」関数の最後の行の変数を切り替えることで、何かが起こるまでの日数を計算するように、コードを少し変更しました。
<xsl:value-of select="$JulianToday - $JulianStartDate"></xsl:value-of>
しかし、私は半分の時間しか違いを正しく結びつけることができません。 したがって、たとえばこの日付(dd / MM / yyyyのフォーマット)では、
30/12/2011
正しく計算されますが、この日付 (同じ形式) の場合
12/10/2011
2011 年 10 月 12 日ではなく、2011 年 12 月 10 日であるかのように計算されます。
次のように、 "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)"/>
これにより、2回目のデートでは問題が修正されましたが、1回目のデートでは間違っていました。
また、ヨーロッパLCIDを使用するようにFormatDateTime呼び出しを変更し、FormatDateTimeの最後のパラメータ(ddMMyyyy、MMddyyyyなど)にさまざまな変更を加えて、部分文字列の位置パラメータに適切な調整を加えて試みましたが、成功しませんでした。
アドバイスをいただければ幸いです。
よろしくお願いいたします。
Chris
No-Code
2011 年 9 月 21 日、午前 4:27
XSL 言語を理解することはすべての人に適しているわけではないため、XSL が「ノーコード」ソリューションとして適格であるとは思いませんが、プログラミングは含まれません。 それに加えて:素晴らしい解決策、ありがとう!