Previous month:
2008年1 月
Next month:
2008年3 月

2008年2 月 からの 18 記事

通知メールのカスタマイズ (1.13種類のテンプレート)

前回は通知機能について紹介しましたが、今回は通知されるメールのカスタマイズについて取り上げたいと思います。これも少し長くなりそうなので、連続ものにします。

通知メールはHTML形式で定型文書となっているため、「少し文面を変更したい」とか「テキスト形式でないと社内では利用できない」といったカスタマイズが必要となることが少なくないようです。

通知メールのカスタマイズは可能です。しかし、複雑なXMLデータを編集することになるためカスタマイズはそれほど容易ではないということだけ念頭に入れておいてください。なお、カスタマイズの詳細は「Microsoft SharePoint Developer Documentation Team Blog (英語)」に記載されています。早い話、これを熟読すればよいのですが、今のところ英語の情報のみですし難解な部分もあるため、私自身の実験結果を踏まえ、この中からかいつまんで説明をしてみたいと思います。

通知メールの形式は "alerttemplates.xml" に定義されています。このファイルは次の場所にあります。

  • ShaerPoint ハイブ\TEMPLATES\XML
    ※SharePoint ハイブは通常、"c:\Program Files\Common Files\Microsoft Shared\web server extensions\12

次の図は、alerttemplates.xml を IE で開いてみてたところです(<AlterTemplate>タグごとに折りたたみ表示にしています)。
Alerttemplate1

このファイルの中には次の13種類の通知のテンプレートが定義されています。

テンプレート名説明
SPAlertTemplateType.GenericList 最初に定義されている通知メールのテンプレートです。他のイベントの種類に一致するものがない場合に使用されます。
SPAlertTemplateType.DocumentLibrary ドキュメントライブラリ内での変更を通知
SPAlertTemplateType.Survey アンケート内の変更を通知
SPAlertTemplateType.Links リンク内の変更を通知
SPAlertTemplateType.Announcements お知らせ内の変更を通知
SPAlertTemplateType.Contacts 連絡先内の変更を通知
SPAlertTemplateType.Events イベント内の変更を通知
SPAlertTemplateType.Tasks タスク内の変更を通知
SPAlertTemplateType.DiscussionBoard ディスカッション掲示板内の変更を通知
SPAlertTemplateType.PictureLibrary 画像ライブラリ内の変更を通知
SPAlertTemplateType.XMLForm フォームライブラリ内の変更を通知
SPAlertTemplateType.DataConnectionLibrary データ接続ライブラリ内の変更を通知
SPAlertTemplateType.AssigedtoNotification タスクリストや案件管理リストへ割り当てられた通知

こうした通知テンプレートは構成データベースに格納され、Webアプリケーション単位で使用できるようになっています。

このうち、ワークフローなどでも利用されるため利用頻度の多いであろう「タスクリスト」を例にとり、カスタマイズ方法を説明していこうと思います。

次回は、テンプレートの基本フォーマットを確認します。


通知機能について

SharePoint には通知機能があり、新しいアイテムの投稿や変更があった場合などにメールで知らせてくれます。

通知されるタイミング

通知のタイミングは次の3つがあります。

  • すぐに通知する
  • 日に一度通知する
  • 週に一度通知する

このうち"すぐに通知する" は、"すぐに" と言いつつ既定では5分のインターバルがあります。通知のタイマージョブは5分間隔で実行されます(ワークフローテンプレートを利用した際のメール通知も同様です)。パフォーマンスの面からこうした仕様になっているようです。

このインターバルはstsadm.exe を使って変更できます。とはいえ、間隔が短ければ短いほどデータベースの呼び出し回数が増えることになるため、パフォーマンスが低下する可能性があります。たとえば、MSDNの「Joel Oleson's Blog SharePoint Land 」ブログの中で Joel Oleson さんは、パフォーマンスを最重要視するのであれば30分間隔にすることを勧めています。つまり、インターバルを変更する必要がある場合は、パフォーマンスを考慮しつつ、組織の事情に合わせて最善のタイミングへとチューニングする必要があります。

[構文例]
stsadm.exe -o setproperty -propertyname job-immediate-alerts -url URL -propertyvalue "every n minutes between 0 and 59"
(※propertyname は pn 、propertyvalue は pv でも可)

例) stsadm.exe -o setproperty -pn job-immediate-alerts -url http://moss2007/sites/top -pv "every 10 minutes"

このコマンドについては、おりば~ずさんのブログでも言及されていましたのでこちらも参考になります。http://sharepoint.orivers.jp/blogs/orivers/archive/2007/01/25/63.aspx

※なお、以前、コマンドを実行しても通知の頻度が変更されないことがあったのですが、 "Windows SharePoint Services Timer " を再起動するときちんと反映されるようになりました。このサービスは、Windwos Server 2003 「管理ツール」の「サービス」管理コンソールもしくは net stop/start コマンドを使用して再起動できます。ご参考まで。

イベントの記録

通知設定後はアイテムの変更などの記録があってはじめて通知メールが生成されるはずですが、それはいったいどこに記録されているのでしょうか? その情報はコンテンツDBの内部にあります。

通知ではコンテンツDB内の "EventCache" テーブル、 "EventLog" テーブル、"EventBatches"テーブルが使用されています。

関連しそうなストアドプロシージャを調べてみると "proc_AddEventToCache", "proc_AddEventToCacheForDeleteRestore","proc_DeleteEventLog","proc_GetEventDataAndSubscriptionFilters" などがありました。

変更情報はまず EventCache テーブルに書き込まれ蓄積されていきます。そしてタイマージョブのタイミングで 通知が生成される際に EventCacheテーブル、EventLog テーブルと EventBatches テーブルが更新されます。

既定では変更ログは15日間残るようになっています。ですから、EventCacheテーブルなど見ても、今日の日付からさかのぼって15日間しかデータがないことが確認できます。期限の切れたログエントリがある場合は毎日実行されるタイマージョブが削除します。なお、この15日間という期間は、Webアプリケーション単位で変更可能です。

変更ログの保持期間の変更

  1. 「SharePoint サーバーの全体管理」の「アプリケーション構成の管理」を開きます。
  2. [SharePoint Web アプリケーション構成の管理]セクションにある[Webアプリケーションの全般設定」をクリックします。
  3. [Web アプリケーション]セクションで設定を変更したい Web アプリケーションを指定します。
  4. [変更ログ]セクションで保持期間を変更します。

    Changelog


参考:
Joel Oleson's Blog SharePoint Land (英語)
Microsoft SharePoint Developer Documentation Team Blog (英語)


MSDN バーチャルラボ

すでにご存じの方も多いと思いますがマイクロソフトさんのサイトで、「MSDN バーチャルラボ」という自習教材(無償)がありさまざまなマイクロソフト社製品を学習できます。もちろん、SharePoint Server 2007 も学習できます。

この MSDNバーチャルラボに近日、「開発者のための Microsoft Office SharePoint Server 2007 自習書 (ソリューション開発編)」という新しいコースが UP されました。

■MSDN バーチャルラボ
http://www.microsoft.com/japan/msdn/virtuallabs/sharepoint.mspx

所属会社であるクリエ・イルミネートにて実施している同一名のコース内容を自習できます(90分間限定ですが)。

■株式会社クリエ・イルミネート
http://www.crie-illuminate.jp/training/courselist02.aspx

もちろん、講師から直接説明を聞きたいとか、じかに話をしたいという方はぜひ有償コースもご受講くださいませ。

以上、ご参考まで。


[操作]メニューから特定のメニューを非表示にする

[操作]メニューから、エンドユーザーに利用させたくない、もしくは利用することがないメニューを非表示にしたいというニーズをよく耳にします。

なんとか実現させたいと思うのですが、これがなかなか頭を悩ませる話なのです。新しいメニューを追加することは、カスタムのフィーチャを定義してやることで割と簡単に実現できます。しかし、既存のメニューを非表示にすることは難しい。MSDNなどを見るとフィーチャ定義によってメニューの非表示が可能だと書いてはあるのですが、既存メニューの非表示を試すと動いてくれません。これについては 海外のサイトもさんざん確認してみましたが、皆さんことごとく「うまく動かない」とコメントしています。ということで、現実的にフィーチャで対応するのは難しそうです。

Web で関連情報を調べてみると 2つのアプローチが現実的に利用できそうです。一つは、ToolbarActionsMenu のテンプレートを編集する方法であり、もうひとつはJavaScript による HTML DOM 操作によるカスタマイズ方法です。

具体的な目標を定めたほうがわかりやすいと思いますので、今回は "Windows エクスプローラで開く" 機能を非表示してみます。実は、意外と多くご質問いただくのが、ドキュメント ライブラリ上でWindows エクスプローラで開く"機能を使わせないようするにはどうしたらよいかというものです。

※なお、これを実現するには「エクスプローラ ビュー」の削除もお忘れなく。

サーバーファーム内の全サイト コレクションに対して一括設定する

こちらは、DefaultTemplate.ascx を編集する方法です。

  1. SharePoint ハイブ 内の\TEMPLATE\CONTROLTEMPLATES フォルダ内の defaultTemplate.ascxをバックアップ用にコピーし、CONTROLTEMPLATES フォルダとは別のフォルダに保存しておきます。
  2. defaultTemplate.ascx をメモ帳またはSharePoint Designer 2007 などで開きます。なお、SharePoint Designer 2007 で開いた場合はデザインビューは使用できないため、コードビューに切り替えておいてください。
  3. 次のタグを削除し、上書き保存します("OpenInExplorer" で検索するとすぐに見つかります)。※このタグの部分がエクスプローラビュー表示を生成しています。

    <SharePoint:MenuItemTemplate
        ID="OpenInExplorer"
        Text="<%$Resources:wss,ToolBarMenuItemOpenInExplorer%>"
        Description="<%$Resources:wss,ToolBarMenuItemOpenInExplorerDescription%>"
        PermissionsString="UseClientIntegration"
        PermissionContext="CurrentList"
        MenuGroupId="200"
        Sequence="300"
        UseShortId="true"
        runat="server"/>
  4. IISを再起動します。

※3.のタグが含まれる <SharePoint:RenderingTemplate ID="ToolbarActionsMenu" runat="server">からタグ内にツールバーに表示されるメニューが定義されています。

サイト単位やリスト単位で設定する

JavaScript で HTML DOM を操作する方法です。まず、操作ターゲットとなるタグを見極めます。任意のドキュメントライブラリの「すべてのドキュメント」ビューを表示して、任意の場所を右クリックし [ソースの表示] をクリックし、生成されるコードを確認します。たとえば今回のように 'Windows エクスプローラで開く' 部分は、私の環境では次のようなコードが出力されていることがわかります。

****************************
<ie:menuitem id="zz22_OpenInExplorer" type="option" onMenuClick="NavigateHttpFolder('http:\u002f\u002fmoss2007\u002fsites\u002ftop\u002fSiteDirectory\u002fsoumu\u002fShared Documents', '_blank');" hidden="!(SupportsNavigateHttpFolder())" text="Windows エクスプローラで開く" description="ファイルをこのライブラリにドラッグ アンド ドロップしてください。" menuGroupId="200"></ie:menuitem>
***************************
あとは、この情報を元にロジックを構成するだけです。

【リスト(ドキュメント ライブラリ)単位での設定】

特定のビュー ファイル (たとえば、AllItems.aspx) の<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server">タグ内にスクリプトを記述します。

【サイト単位での設定】

カスタムのマスタページを作成し、スクリプトを記述します。※ここでは、サイトコレクションで発行インフラストラクチャ機能が有効になっていることを前提とします。

カスタムのマスタページの作成

  1. SharePoint Designer 2007 でサイトコレクションのトップレベルサイトを開きます。
  2. [フォルダ一覧] から"_catalogs"-"masterpage(マスタページギャラリー)" を開きます。
  3. default.master のコピーを同一フォルダ内に作成し、任意のファイル名に変更します。たとえば "myDefault.master" とします。
  4. body タグの終了タグの直前あたりにスクリプトを記述します。

カスタムのマスタページの適用

  1. 設定を適用したいサイトの [サイトの設定] - [外観] セクションの [マスタページ]からシステムマスタページの方を、カスタムのマスタページ (myDefault.master) に変更します。

***使用するスクリプト例****

<script type="text/javascript">
<!--
_spBodyOnLoadFunctionNames.push('hideOpenInExplorer');
function hideOpenInExplorer()
{
//エクスプローラで開くメニューを非表示
removeTags('_OpenInExplorer');
}
function removeTags(menuId){

var tags=document.getElementsByTagName('ie:menuitem');
if(tags==null){return;}
for (i=0;i<tags.length;i++)
{
var id=tags[i].id;
var searchTagId=id.substring(id.indexOf('_'),id.length);

if(searchTagId==menuId)
{
  tags[i].parentNode.removeChild(tags[i]);
  return;
   }

}//for
}//function
//-->
</script>
*****************************************************

removeTags関数の引数にメニューIDを指定します。各メニューのIDは以下の通りです。

  • Windows エクスプローラで開く→_OpenInExplorer
  • データシートで編集→_EditInGridButton
  • Outlook に接続→_OfflineButton
  • スプレッドシートにエクスポート→_ExportToSpreadsheet

[図.既定の4つのメニューを非表示にしたところ]

Hideactionmenu


参考: Blog de Jérémie Clabaut (ak MinSou)(英語)


タイトル列の非表示 (JavaScript を用いるアプローチ)

以前の記事で、タイトル列の非表示を例にあげ、SharePoint Designer 2007 のユーザー設定のリストフォームを利用する方法をご紹介しました。http://shanqiai.weblogs.jp/sharepoint_technical_note/2007/12/newformaspx_edi_d88b.html

便利な機能ではあるのですが、使い方によっては不具合も多く見られるようです。たとえば、2929さんが何度かコメントされていますがテンプレート化して利用する際にエラーが表示されるなどです。

そこで、タイトル列を非表示にする別のアプローチを探っていたのですが、JavaScript を使って HTML DOM を操作するアプローチが現実的である場合があるように思います。もちろん、ブラウザ依存の部分を考えなければならず、本来はそうした差異を吸収してくれるのがASP.NETのコントロールであったりするわけですが、ある意味逆転の発想です。

参考までに、以下に任意のリストで「タイトル列を非表示にする」スクリプトコードの例を記述しておきます。

*****************************************

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<!-- 以下に、JavaScript を追加-->

<script type="text/javascript">
<!--
_spBodyOnLoadFunctionNames.push("hideTitle");

function hideTitle()
{

var targetTag=getTagFromIdenfifierAndTitle('input','TextField','タイトル');

while(targetTag.parentNode!=null)
{
  tag=tag.parentNode;
  if(tag.tagName=='TR')
  {
   tag.style.display='none';
   return;
  }
}

}//function

function getTagFromIdentifierAndTitle(tagName, identifier, title) {
  var len = identifier.length;
  var tags = document.getElementsByTagName(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
  }//for

  return null;
}//function

//-->
</script>

****************************************

上記のコードでは、"タイトル" と書かれているノードの親となる "TR" 要素を取得し、スタイル属性に "display:none" を指定しています。これで、テーブル内のタイトル行が非表示になるわけです。

このように JavaScript から DOM を操作するアプローチはロジックを考えるのが少々面倒なところはありますが、既存のWebパーツの邪魔をせずに必要なタグを修正したり、追加できるのでそれなりに使える場面は多いように思います。

開発者の方でも意外と JavaScript でコーディングする機会は少ないかも知れませんが、MOSS のエンジニアはJavaScript による DOM 操作の基本は押さえておきたいですね。


参考: SharePoint Designer 2007 Team Blog (英語)