2008年3月24日 (月)

特定の期間でフィルタを設定する : データビューとクエリ文字列

ドキュメント ライブラリなどのファイルにメタデータ(プロパティ)を持たせることができるのは周知のことと思います。

たとえば、契約書などを保存する際に契約満了日などのプロパティを持たせておくと管理がしやすそうです。しかし、折角こうしたプロパティを持たせたのであれば、ユーザーが自由に期間を指定して特定のファイルだけを表示させたいところです。

さて、このようなフィルタを比較的手軽に行うにはどうしたらいいかが問題です。カスタムビューでのフィルタでは固定値になります。そんなときにうってつけなのがこちらのブログで何度もご紹介している "データビュー" です。 SharePoint Designer 2007 を使用すると既定のリストビューを データビューに変更できます。データビューに変換すると、フィルタが設定できるようになりますが、このフィルタに "クエリ文字列" が利用できます。

そこで次のようなソリューションを考えました。既定のリストビューをデータビューに変換し、クエリ文字列で期間を指定できるようにする。これで決まりです! あとはコントロールなどを配置してうまいこと JavaScript を組み込んでやればかなり使い勝手がよくなります。

次の図は 日付コントロールなどを挿入してスタイルシートを適用して見栄えを整えてWeb パーツでも挿入したような見た目にしていますが、実際には JavaScript のコードしか書いていません。

[図.期間指定でフィルタを設定する]
Dataviewadvancedfilter
Dataviewadvancedfilter2

作業概要

  • データビューに変換しフィルタを設定する
  • クエリ文字列を渡すためのコントロールやスクリプトを用意する

用意したライブラリ

ドキュメントライブラリを用意し、そこに "契約満了日" というプロパティを持たせています。

データビューに変換しフィルタを設定する

データビューの変更方法は既出の記事でご紹介していますので、詳しくは以下を参考にしてください。

  1. リストの view.aspx 内のリストビューを XSLT データビューに変換します。
  2. データビューの部分を右クリックし "コモン コントロール タスクの表示" をクリックします。
  3. "フィルタ" をクリックします。
  4. フィルタ条件として、フィールド名: "契約満了日" 、条件式: "次の値以上" 、値: "新しいパラメータの作成" を指定します。
  5. パラメータの作成画面で、パラメータ ソース: "クエリ文字列"、クエリ文字列変数: start というエントリを作成します。同様に、パラメータ ソース: "クエリ文字列"、クエリ文字列変数: end というエントリを作成します。
    Dataviewfilterquerystring1
  6. [OK] をクリックします。
  7. 一つ目の条件の値が "[start]" になっていることを確認します。
  8. 再びフィルタ条件として、フィールド名: "契約満了日" 、条件式: "次の値以下" 、値: "[end]" を追加します。

    Dataviewfilterquerystring2

  9. [OK] をクリックします。

※ソースコードを確認するとわかりますが、フィルタを設定すると、DataSource 内の select 属性にフィルタ内容が CAML として生成されます。CAMLは SharePoint 用のクエリ言語のようなものです。ここに書かれている条件を元にデータを取得してきます。

以上で 「リストのURL/view.aspx?start=開始日&end=終了日」と指定することで、フィルタが適用できるようになります。

クエリ文字列を渡すためのコントロールやスクリプトを用意する

データビューコントロールのタグの直前に次のようなコードを挿入します。今回は日付をコントロールを利用して指定できるよう、SharePointDateTimeControl を挿入しています。

+++++++++++++++++++++++

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<!-- 以下にコードを追加-->
<br/><p></p>
<table style="font-family:'MS UI Gothic'" class="ms-quickLaunch" align="center">
<tr class="ms-quicklaunchheader"><td colspan="5" align="left">契約満了日でフィルタする</td></tr>
<tr>
<td>
<SharePoint:DateTimeControl runat=server id="DateTimeControl_Start"
DateOnly="true" ToolTip="検索を開始する日付"/>
</td>
<td>から</td>
<td>
<SharePoint:DateTimeControl runat=server id="DateTimeControl_End"
DateOnly="true"  EnableViewState="true"/>

</td><td>まで</td><td>

<input type="button" value="フィルタの実行" onclick="return goFilter()" style="background-color:#FFCC00" name="filterButton"/>
</td></tr>
<tr><td colspan="4" style="color:red;font-size:x-small" id="kikan"></td></tr></table>
<p></p>

<!-- ここまで -->
  <WebPartPages:WebPartZone runat="server" FrameType="None" ID="Main" Title="loc:Main">

++++++++++++++++++++++++++++++

あとはスクリプトを組み込むだけです。日付データであることの妥当性検証などは省いていますが、たとえば以下のようなスクリプトを上記に追加してやればよいです。

+++++++++++++++++++++++++++++

<script type="text/javascript">
<!--

//クエリ文字列を取得し、設定した期間を画面上に表示する
_spBodyOnLoadFunctionNames.push("getFilterCondition");

function getFilterCondition(){
var startDate,endDate;
var message;
var values = getQueryString();
if((values["start"]!= null)&&(values["end"]!=null))
{
  startDate=values["start"];
  endDate=values["end"];
  message= startDate + " から " + endDate  + " までの期間でフィルタしています";
}else{
  message="フィルタの条件が指定されていません。条件を指定してください。";
}
document.getElementById("kikan").innerText=message;
}

//クエリ文字列を取得する
function getQueryString(){
var qs = location.search.substring(1, location.search.length);   
var args = qs.split("&");
var vals = new Object();

for (var i=0; i < args.length; i++) {
     var nameVal = args[i].split("=");
  var temp = unescape(nameVal[1]).split('+');
  nameVal[1] = temp.join(' ');
  vals[nameVal[0]] = nameVal[1];

return vals;
}

//ユーザーが指定した範囲をクエリ文字列として渡す
function goFilter()
{
var startDateTag,endDateTag;
var startDate=new Date();
var endDate=new Date();

//SharePointDateTimeControl のオブジェクトを取得
startDateTag=document.getElementById("ctl00$PlaceHolderMain$DateTimeControl_Start$DateTimeControl_StartDate");
endDateTag=document.getElementById("ctl00$PlaceHolderMain$DateTimeControl_End$DateTimeControl_EndDate");

if(startDateTag.value=="")
{
alert('フィルタで使用する開始日を指定してください');
return;
}

if(endDateTag.value=="")
{
alert('フィルタで使用する終了日を指定してください');
return;
}

startDate=startDateTag.value;
endDate=endDateTag.value;

if(startDate>endDate)
{
alert('日付の指定が不正です。正しい範囲を指定してください');
return;
}

startDate=replaceDate(startDate);
endDate=replaceDate(endDate);

window.location="view.aspx?start="+startDate + "&end=" + endDate;
}

//日付は "yyyy-mm-dd" 形式で渡す必要がある
function replaceDate(str)
{
while(str.indexOf("/",0)!=-1)
{
  str=str.replace("/","-");
}
return str;
}
//-->
</script>
+++++++++++++++++++++++++++++++++

以上、SharePoint Designer 2007 のみでのカスタマイズでも、以外にここまでできると便利だなぁと改めて実感した次第です。

実は今回使用した日付コントロールですが、そのまま使用するとカレンダー表示時のレイアウトが崩れます。次回は、その修正方法をご紹介します。


【参考】
Microsoft SharePoint Designer Team Blog (英語)

トラックバック

このページのトラックバックURL: http://bb.lekumo.jp/t/trackback/718613/34255746

特定の期間でフィルタを設定する : データビューとクエリ文字列を参照しているブログ:

コメント

山崎さん
いつも山崎のブログを見て、たくさん勉強します。ありがとう~
今SharePointDesignerについての問題があってから、原因を教えてください。
SharePointリストはデータソースとしてDataFormWebPartを作成します。しかし、リストにフォルダがある場合、フォルダ中にのアイテムがDataFormWebPartに表示されませんでした。どうしてですか

Kitty さん
しばらく、お返事しないで申し訳ありません。ここのところ多忙をきわめているため、ご質問内容の動作を確認する時間がとれません。もう少しお時間をください。何か分かり次第、こちらに返事をしますね。