Infopath2003 を利用して、階層型(カスケード)分類選択を実現する

先日、「SharePointでダイナミックな分類選択を可能にする」というエントリを書きましたが、業界的には(?)、この私が言うところの「ダイナミック分類」は「カスケード」って言うんですね。

この「カスケード」は SharePoint に欠けている機能の最たるものだと私は考えています。
っていうかユーザから凄い要望されるんですよ…。
ノーツでは普通に出来ましたからね。

上のソリューションも、二階層までしか出来ません。

しかし、一般的には「大分類→中分類→小分類」の三階層じゃないですかね?
更に、実運用を考えれば、分類は一般ユーザが、自分でメンテナンスできることが望ましい訳です。
分類変更の度にシステム部門に依頼されたのでは、正直しんどいです。

そこで、SharePoint と Infopath2003 で、カスケードを実現してみたいと思います。
なお、Infopath2007 でないのは、単純にウチの会社が Office2003 環境だからです。


まず最初に、分類を定義したマスタが必要です。
そしてこのマスタは、ユーザが簡単にメンテできるものである必要があります。
そこで、このマスタも Infopath フォームで作ることにしました。

実際にフォームを作成する前に、XML でスキーマを用意します。
とは言っても、そんな大したものではありません。




これでだけです(笑)
テキストファイルにコピペして、拡張子を .xml で保存してください。

次に、infopath2003 を起動して、新しい空白のフォームテンプレートを作成します。
[XML ドキュメントまたは..]をクリック。
上のファイルを読み込みます。

「メイン データ ソースに別の…」→[いいえ]を選択して[完了]
「選択された .xml の構造が…さらに…」→[いいえ]

フォームテンプレートが作成されます。
データソースはこんな風になっている筈です。

ところで。最初から infopath でデータソースを作ればいいのでは─と思われるかもしれません。
しかし、infpath には、なんというか独特な癖がありまして。
Infopath で定義されたスキーマは「汚い」んですよね。
例えるなら、HomepageBuilder の GUI から作成した HTML のソースが、手でタグを打ったものと比較して余計な部分が多いような、そんな感じです。
これが、後で不都合になるので、プレーンな XML スキーマを読み込ませています。

スキーマは定義されましたが、このままでは1行のデータしか入力できません。
データソースの Category を右クリック→[プロパティ]→[繰り返し]をチェックします。

次は、ユーザが分類情報を登録できるよう、フォームにコントロールを追加します。
[コントロールの挿入]→[繰り返しテーブル]をドラッグ&ドロップ。
グループ Category を選択して[次へ]。
CategoryL CategoryM CategoryS を「表示する列」に追加して[完了]。

テーブルが作成されました。

ただ、このままではユーザに判りにくいので、見出し CategoryL CategoryM CategoryS をそれぞれ、大分類 中分類 小分類 に変更しておきます。

一応、これでテンプレートは完成です。
あとは見栄えを良くしたり、操作説明を追記しておくなりすると良いと思います。

このフォームを、SharePoint のフォームライブラリに発行します。
ライブラリはどのサイトにあっても構いませんが、このテンプレートから作成した XML ファイルの情報をマスタとして利用しますので、サイトコレクションのルート直下あたりが良いかもしれません。

このフォームライブラリを開き、[新規]をクリック。
マスタになる情報を入力していきます。
ここでは、以下のように入力しました。

このファイルを、適当な名前をつけて、フォームライブラリに保存します。
保存したら、そのファイルの URL を取得しておきます。

さて、今度はそのマスタ情報を利用するフォームを作成します(ここからが本番)
新しい空白のフォームテンプレートを作成します。

まず、マスタへのデータ接続を作成します。
[ツール][データ接続][追加]
「データの受信」を選択して[次へ]
「XML ドキュメント」を選択して[次へ]
上で取得した URL を入力して[次へ]

データ接続の名前は、ここでは CascadeCategoryXML としておきます。
「フォームを開くとき自動的に…」にチェックを入れて[完了]。
警告ダイアログ「選択されたファイルは、フォームに含まれていないため…」が表示されますが、無視して[いいえ]
[閉じる]をクリック。

データソースを開き「マイフィールド」を右クリックして[追加]。
[グループ]を追加します。
名称は、ここでは「大中小分類」としておきます。
さらに、その下に、テキストフィールド「大分類」「中分類」「小分類」を追加します。

フォームに、ドロップダウン リスト ボックス を配置します。
この時、「自動的に データソースを作成する」チェックは外しておきます。
[ドロップダウン リスト ボックスのバインド]ダイアログで、「大分類」を選択します。

同じ操作を2回繰り返して、それぞれ「中分類」「小分類」にバインドします。

[大分類]ドロップダウンボックスをダブルクリックします。
[リスト ボックス項目]で、「データ接続の値を…」を選択。
[データ接続]で「CascadeCategoryXML」を選択。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで、「CategoryL」を選択。
[OK]×2

[中分類]ドロップダウンボックスをダブルクリックします。
[リスト ボックス項目]で、「データ接続の値を…」を選択。
[データ接続]で「CascadeCategoryXML」を選択。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで、「CategoryM」を選択。
[OK]×2

[小分類]ドロップダウンボックスをダブルクリックします。
[リスト ボックス項目]で、「データ接続の値を…」を選択。
[データ接続]で「CascadeCategoryXML」を選択。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで、「CategoryS」を選択。
[OK]×2

これで、プレビューしてみてください。
大分類、中分類、小分類がドロップダウン式で選択できるようになった筈です。
しかし、まだ分類同士は全く連携(カスケード)していません。
これから、大分類の値に応じて中分類が、中分類の値に応じて小分類が絞り込まれるよう、フィルタを設定します。

[中分類]ドロップダウンボックスをダブルクリックします。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで[フィルタ データ]をクリック。
[フィルタ データ]ダイアログで、[追加]をクリック。
[フィルタ条件の指定]ダイアログで、
左のフィールドには[フィールドまたはグループの選択]から、メイン データソースの「大分類」 を選択。
中央のフィールドには「が次の値に等しい」を選択。
右のフィールドには[フィールドまたはグループの選択]から、CascadeCategoryXML データソースの「CategoryL」を選択。
[OK]×4

これで、大分類で指定した値に応じて、中分類が絞りこまれるようになりました。
同様に、小分類も設定します。

[小分類]ドロップダウンボックスをダブルクリック。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで[フィルタ データ]をクリック。
[フィルタ データ]ダイアログで、[追加]をクリック。
[フィルタ条件の指定]ダイアログで、
左のフィールドには[フィールドまたはグループの選択]から、メイン データソースの「大分類」 を選択。
中央のフィールドには「が次の値に等しい」を選択。
右のフィールドには[フィールドまたはグループの選択]から、CascadeCategoryXML データソースの「CategoryL」を選択。
[AND / OR]をクリック
二行目の左のフィールドには[フィールドまたはグループの選択]から、メイン データソースの「中分類」 を選択。
中央のフィールドには「が次の値に等しい」を選択。
右のフィールドには[フィールドまたはグループの選択]から、CascadeCategoryXML データソースの「CategoryM」を選択。
[OK]×4

これで、中分類で指定した値に応じて、小分類が絞りこまれるようになりました。

しかし、このままでは、まだ不完全です。
大分類も中分類も、ドロップダウンに、重複した選択肢がのべつ表示されてしまっています。
Infopath2007 であれば、こうしたドロップダウンコントロールについて [一意の表示名を持つ項目のみ表示する] オプションで、選択肢をマージすることが出来るのですが、残念ながら Infopath2003 にはその機能がありません。

ここでは、Xpathによるフィルタで、重複をマージします。

[大分類]ドロップダウンボックスをダブルクリック。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで[フィルタ データ]をクリック。
[フィルタ データ]ダイアログで、[追加]をクリック。
[フィルタ条件の指定]ダイアログで、
左のフィールドには[式]を選択。
右のフィールドには not ( . = ../preceding-sibling::Category/@CategoryL) を入力。
[OK]×4

次に、中分類にフィルタをかけます。
大分類と同様な Xpath 式を入力するば良いように思えますが、実際に設定してみると問題が発生します。「大分類1」にも「大分類2」にも、子カテゴリとして「中分類1」「中分類2」が存在します。この状態で、「大分類2」を選択すると、本来、選択肢として表示されるべき「中分類1」「中分類2」どちらも表示されません。
これは、フィルタが「中分類1」「中分類2」が CascadeCategoryXML データソース上の「大分類1」で既に出現している─と判断してしまう為です。

そこで、 Xpath 式に少し変更を加えます。

[中分類]ドロップダウンボックスをダブルクリック。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで[フィルタ データ]をクリック。
[フィルタ データ]ダイアログで、[追加]をクリック。
[フィルタ条件の指定]ダイアログで、
左のフィールドには[式]を選択。
右のフィールドには
not ( . = ../preceding-sibling::Category[@CategoryL = current()/my:大中小分類/my:大分類]/@CategoryM)
を入力。
[OK]×4

さらに、小分類にもフィルタをかけます。

[小分類]ドロップダウンボックスをダブルクリック。
[エントリ]フィールドの右にあるアイコン(Xpathの選択)をクリック。
[フィールドまたはグループの選択]ダイアログで[フィルタ データ]をクリック。
[フィルタ データ]ダイアログで、[追加]をクリック。
[フィルタ条件の指定]ダイアログで、
左のフィールドには[式]を選択。

右のフィールドには
not ( . = ../preceding-sibling::Category[@CategoryL = current()/my:大中小分類/my:大分類 and @CategoryM = current()/my:大中小分類/my:中分類]/@CategoryS)
を入力。
[OK]×4

実のところ、「各分類の値が必ず一意であること」を保障できるなら、こんな面倒なフィルタを定義する必要はないのです。
しかしユーザに運用を任せる以上、重複する値が設定されることは考慮しておいたほうがいいですよね。

最後に、あとひとつ修正すべき点があります。
この状態では、大分類→中分類→小分類 と、順番に選択している限り問題はありません。
しかし、あとから分類を設定し直した際、無効な(本来選択できない筈の)値が残ってしまいます。

そこで、動作規則を利用して、上位の分類に変更があった場合に、下位をクリアするようにします。

[大分類] ドロップダウンボックスをダブルクリック。
[動作規則]をクリック。
[追加]をクリック。
動作規則に適当な名前をつけます。ここでは「値クリア」としておきます。
[動作の追加]をクリック。
[動作]ダイアログで、[フィールドの値を設定する]を選択。
[フィールド]フィールドの右にあるアイコンをクリック。
メイン データソースの[中分類]を選択。
[OK]×5

これで、大分類に変更を加えると、中分類がクリアされます。

[中分類] ドロップダウンボックスをダブルクリック。
[動作規則]をクリック。
[追加]をクリック。
動作規則に適当な名前をつけます。ここでは「値クリア」としておきます。
[動作の追加]をクリック。
[動作]ダイアログで、[フィールドの値を設定する]を選択。
[フィールド]フィールドの右にあるアイコンをクリック。
メイン データソースの[小さい分類]を選択。
[OK]×5

これで、中分類を変更すると、小分類がクリアされます。

なお、大分類を変更した際に小分類はクリアしなくていいの?と疑問に思われるかもしれません。
しかし、動作規則は連動して動いてくれます。
大分類を変更→中分類がクリアされる→中分類に変更があったので小分類がクリア、となります。

これで完成です!
─疲れますね(苦笑)

でも、この階層(カスケード)分類は、非常に使える機能だと思います。
今回は、大中小の三段階までしか設定しませんでしたが、応用すれば、もっと深い階層も定義できます。

なお、このエントリは全面的に INFOPAATHdev の Greg Collins さん記述、Kaoru Okumura さん訳の「フラットなデータ ソースからカスケードリストを作成する」を参考にしています。
というか、ほぼまんまパクリです。なぞっただけです(汗)

ただ、原文は英語環境での手順ですので、それを日本語化しました。
加えて、原文では、まず分類を定義したXMLファイルありきで始まりますが、実際の運用シーンを想定し、XML知識の無い一般ユーザでもメンテが出来るように、マスタも Infopath 化したことが私なりの工夫です。

どなたかのお役に立てれば、幸いです。

INFOPATHdev.com

続・SharePoint のリストでカスケード分類っぽいことを実現してみる
SharePoint のリストでカスケード分類っぽいことを実現してみる
Windows SharePoint Services 3.0 のヘルプと使い方>数式と関数
SharePoint2007 で利用できる関数とそのお作法
Infopath2003 を利用して、階層型(カスケード)分類選択を実現する
SharePointでダイナミックな分類選択を可能にする Query Based Lookup Field


Author

中村 和彦(シンプレッソ・コンサルティング株式会社 代表)が「ユーザ視点の SharePoint 情報」を発信します。元大手製造業 SharePoint 運用担当。現SharePoint コンサルタント。お仕事のお問い合わせはこちらまでお願いします。当ブログにおける発信内容は個人に帰属し所属組織の公式発信/見解ではありません。
FB : 中村 和彦
blog: Be・Better!
MS MVP SharePoint 2009/10-2011/9
MS MVP Office 365 2012/10-2014/9