Monthly Archives: May 2016

[IM] クロステーブルの作成

INTER-Mediator Ver.5.4-devでは、クロステーブルの作成ができるようになっています。ここでのクロステーブルは、表があって、いちばん上の列と、いちばん左の列がラベルとなっており、そのラベルの交差するセルには、ラベルに関連するデータが表示されるというものです。例えば、いちばん上の列には自社の「支店」が並び、いちばん左の列には年月が並ぶとすると、その交差するセルには、特定の支店の特定の年月の売り上げが見えるというものです。サンプルファイルはSamples/Practice/crosstable.htmlおよびcrosstable.phpにあります。

まず、クロステーブルを作るには、3つの異なるコンテキストを定義します。1つは列見出し(以下のコードではitem)、1つは行見出し(以下のコードではcustomer)、そして交差するセルに設定されるデータのコンテキスト(同じくsalessummary)です。列見出し、行見出しのコンテキストについては通常と変わりありません。また、列か行かの区別も、定義ファイル内では設定しなくても構いません。行列の見出しのコンテキストでは、検索条件や並べ替えフィールドの指定などももちろん可能です。以下の例では、元のデータが多いこともあるので、意図的に絞り込んでいます。交差するセルのコンテキスト「salessummary」では、relationキーの指定を必ず2項目行います。1項目は列見出し、2項目目は行見出しとの関連付けになります。item、customerともに、主キーはidフィールドです。これに対応するsalessumarryコンテキストのフィールドはitem_idとcustomer_idです。すなわち、列見出し、行見出しの対応するレコードとのリレーションシップを利用して、交差するデータの配置を決めています。

 array(
   'name' => 'item',
   'table' => 'dummy',
   'view' => 'item_master',
   'records' => 100000,
   'maxrecords' => 100000,
   'key' => 'id',
   'query' => array(
     array('field' => 'id', 'value' => 25, 'operator' => '>='),
     array('field' => 'id', 'value' => 35, 'operator' => '<='),
 ),
 'sort' => array(array('field' => 'id', 'direction' => 'asc')),
 ),
 array(
   'name' => 'customer',
   'table' => 'dummy',
   'view' => 'customer',
   'records' => 100000,
   'maxrecords' => 100000,
   'key' => 'id',
   'query' => array(
     array('field' => 'id', 'value' => 250, 'operator' => '>='),
     array('field' => 'id', 'value' => 259, 'operator' => '<='),
   ),
   'sort' => array(array('field' => 'id', 'direction' => 'asc')),
 ),
 array(
   'name' => 'salessummary',
   'table' => 'dummy',
   'view' => 'saleslog',
   'records' => 100000,
   'key' => 'id',
   'relation' => array(
     array('foreign-key' => 'item_id', 'join-field' => 'id', 'operator' => '=',),
     array('foreign-key' => 'customer_id', 'join-field' => 'id', 'operator' => '=',),
   ),
 ),

ページファイルのクロステーブルの部分は、2セルずつの2行の表として作ります。それよりも多い場合や少ない場合はダメで、要するに2行2列のテーブルを必ず用意します。そして、エンクロージャーになるtbodyタグのdata-im-control属性を「cross-table」とします。これら4つのセルと2つの行は取り除かれ、初期状態として、TRタグに左上のセルを入れた状態にします。この左上のセル内部は、ページファイル側での定義通りにレイアウトされます。

fig16

 <table>
 <tbody data-im-control="cross-table">
 <tr>
   <th></th>
   <th>
     <div data-im="item@id"></div>
     <div data-im="item@name"></div>
   </th>
 </tr>
 <tr>
   <th>
     <div data-im="customer@id"></div>
     <div data-im="customer@name"></div>
   </th>
   <td>
     <div data-im="salessummary@qty"></div>
     <div data-im="salessummary@total"></div>
   </td>
 </tr>
 </tbody>
 </table>

続いて、1行目のTRタグをエンクロージャーに、そしてページファイルにあった右上のセルをリピーターとして、ページ合成を行います。つまり、このBのセルには、列見出しになるコンテキストの名前と、データベースから得られるフィールド名をdata-im属性として持つターゲットノードを記述しておきます。その結果、データベースアクセスが発生し、この場合はitemテーブルから一部のレコードを取り出して、それらを列見出しとして並べます。

fig17

さらに行見出しの処理になります。今度は、TBODYタグをエンクロージャー、そしてTRタグにページファイルの左下のセルを入れたものをリピーターとして、ページ合成を行います。つまり、行見出しだけをまずは作成します。

fig18

ここまでは、エンクロージャーとリピーターの違いはありますが、通常のページ合成と同じです。クロステーブルでは、ここで、次の図のように、交差する部分のセルに、一旦、ページファイルのテーブルの右下のセルを全て並べます。そして、コンテキストに応じたデータベースアクセスを行い、交差する部分に入るデータがあれば、対応するセルに値を設定します。列見出しあるいは行見出しに登場しないレコードと対応するものは無視されます。

fig19

サンプルの出力結果は以下のようなものです。2つのセルにしかデータは入っていません。なお、ここでの交差するセルに対応したコンテキスト内に、同一のセルに対応するものが複数ある場合には、中途半端にマージされます。コンテキスト内は、例えばSQLのビュー等を使うなどして、1つのセルに対応するレコードは0ないしは1個になるようにしてください。

shot3220