"SharePoint Designer " にカテゴリー登録されている29 投稿

[SPDワークフロー] プロパティ変更をトリガにするには

ワークフローではファイルを別のユーザーが更新したら、またはあるプロパティ値が変更されたらメールを送信するなどの機能が必要になることがあります。これをSharePoint Designer 2007で行い、特定のプロパティ変更をトリガにワークフローを開始するにはちょっと工夫が必要です。

理由は、変更前の情報と変更後の情報をSharePoint Designer では認識してくれないからです。ということは、変更前の情報をどこかに持たせて、変更後の情報と比較してやれば、トリガにできるということになりますね?

こうしたフローを実装するには次のように行います。

[1st Step]

  1. 特定のフィールドの以前の値を格納する列(たとえば、beforeとします)を作成する
  2. SharePoint Designer でワークフローを作成する(詳細は2nd Stepで)

[2nd Step]

  1. ワークフローの起動オプションを「アイテム変更時に自動的にワークフローを開始するよう」に設定する
  2. 1つめの条件とアクションを次のように構成する
    "before列が空の場合に、トリガにしたい既存の列の値を格納する"
  3. 2つめの条件とアクションを次のように構成する
    "既存の列の値とbefore列の値が一致する場合はワークフローを中止する"
  4. 3つめは使用したいアクションのみを構成する

上記のステップは、次のURLにあるストリーミング コンテンツ(英語)で手順が確認できます。

[参考] http://office.microsoft.com/en-us/sharepointdesigner/HA102564191033.aspx (英語)

※上記URLは、Officeオンラインです。Office オンラインは基本的に英語の文書がありその対となる日本語文書がそろっているのですが、実際には日本語よりも英語のほうが情報が充実していまるようです。時には、英語で文献を探すことをお勧めします。またブログでも、日本語にはなっていないもので、役立ちそうなものは取り上げるようにしたいと思います。confident


アイテム保存の[OK] ボタンクリック時の入力フィールド検証

SharePoint Designer 2007を使用してリストやライブラリのNewForm.aspx(アイテムの新規作成)やEditForm.aspx(アイテムのプロパティ編集)を編集し、カスタムのJavaScriptを実装することで日付などの入力フィールドの妥当性の検証が可能です。たとえば、開始日と終了日の2つのフィールドがあったとして、終了日が開始日より前の日付となっているような場合、SharePoint Server 2007ではエラーとして扱ってくれません。そこで、JavaScript を実装して2つのフィールド値の比較をしてエラーを検出するようにします。この時、「PreSaveAction」という名前の関数を定義すると、[OK]ボタンクリック時の既定の処理を制御できます。実際には、このPreSaveAction関数はSharePointが既定で持っている関数であり、これを上書きして既定の動作を少し変えてやります。

参考までに、"開始日"と"終了日"という名前の2つの"日付と時刻(日付のみ)"のフィールドがあることを前提としたサンプルコードを記載しておきます。

PreSaveAction 関数を上書きするコードサンプル

function PreSaveAction()
{
     var startDate=getTagFromIdentifierAndTitle("input","DateTimeFieldDate","開始日");
     var endDate=getTagFromIdentifierAndTitle("input","DateTimeFieldDate","終了日");

  var date1Array=startDate.value.split("/");
  var date1=new Date(date1Array[0],date1Array[1]-1,date1Array[2]);
  var date2Array=endDate.value.split("/");
  var date2=new Date(date2Array[0],date2Array[1]-1,date2Array[2]);

    if (date1>date2)
    {
         alert("日付の指定が正しくありません");
         return false;
    }//if
    return true;
} //function

//SharePointのフィールドを取得するための関数
function getTagFromIdentifierAndTitle(tagName,identifier,title)
{
var len=identifier.length;
var tags=document.getElementByTagName(tagName);

  for(var i=0;i<tags.length;i++)
  {
     var tempString=tags[i].id;
     if(tags[i].title==title&&(identifier==""||tempString.indexOf(identifier)==tempString.length-len))
     {
           return tags[i];
      }//if
      return null;
  }//for
}//function


SharePoint の 日付選択コントロールにスタイルが適用されない

前回の投稿では、SharePoint Designer 2007 を使用してカスタム作成ページにSharePoint の 日付選択コントロールを追加して利用する例をご紹介しました。

しかし、この日付選択コントロールは既定では SharePoint のスタイルが適用されずレイアウトが崩れてしまいます。

この場合の解決方法は次の通りです。

  1. SharePoint ハイブ(%programfiles%\common files\microsoft shared\web server extensions\12\)内のtemplates\layoutsにある "iframe.aspx" をメモ帳などで開く
  2. <Head>タグの直後に次のタグを追加する。
    <link rel="stylesheet" type="text/css"href="/_layouts/1041/styles/datepicker.css"/>
    ※ 2008.3.28 修正しました。ディレクトリ指定をうっかり "1033" と記載しておりました。 "1041" の間違いでした。

以上、Tips でした。


【参考】
http://blog.richfinn.net/2006/12/10/SharePointDateTimeControlDoesNotRenderStyles.aspx


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

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

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

さて、このようなフィルタを比較的手軽に行うにはどうしたらいいかが問題です。カスタムビューでのフィルタでは固定値になります。そんなときにうってつけなのがこちらのブログで何度もご紹介している "データビュー" です。 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 (英語)

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


SharePoint Designer 2007 で default.master のコピーを削除できない

MOSS の UI を変更するために、SharePoint Designer 2007 を使用してカスタムのマスタページを作成するとき、default.master を直接カスタマイズしたものを再び「サイト定義にリセット」すると default.master のコピーが作成されます。もしくは、単純に default.master をコピーして名前を変更して利用している場合もあると思います。

このように default.master のコピーを作成したあと、コピーが不要になったからといざ削除しようとすると次のようなエラーメッセージが表示され削除できません。

Oldmasterpagedeleteerror

実際にはどこにも参照しているページがないのにも関わらず、このようなメッセージがでます。とはいえ、不要なファイルは削除したいです。正式な方法ではないでしょうが、てっとり早く削除する方法を記しておきます。

操作は単純です。master となっている拡張子を削除し、ファイル名だけにします。この状態だと削除できてしまいます。

UI カスタマイズをする際のちょっとした裏ワザ(?) でした。