拡張レポート・レイアウトの使用

拡張レポート・レイアウトについてさらに学習します。

この項では、拡張レポート・レイアウトに関する次のタスクについて説明します。

バッチ・レポートの作成

1つのPDFファイルに含まれる請求書や発注書などの文書を一括して印刷することは一般的な要件の1つです。このような文書は複数の異なる顧客向けであるため、ドキュメントごとにページ番号をリセットし、ページ合計はドキュメント固有であることが必要です。ヘッダーとフッターにデータのフィールド(顧客名など)を表示する場合も、同様にリセットする必要があります。

Publisherでは、コンテキスト・コマンドを使用してこの要件をサポートしています。このコマンドを使用すると、レポートの要素を特定のセクションに定義できます。セクションが変わると、要素がリセットされます。

次の例では、出力ファイル内のヘッダーとフッター、およびページ番号をリセットする方法を説明します。

次のXMLコードは、複数の請求書を含むレポートです。

...
<LIST_G_INVOICE>
   <G_INVOICE>
      <BILL_CUST_NAME>Vision, Inc. </BILL_CUST_NAME>
      <TRX_NUMBER>2345678</TRX_NUMBER>
      ...
   </G_INVOICE>
   <G_INVOICE>
      <BILL_CUST_NAME>Oracle, Inc. </BILL_CUST_NAME>
      <TRX_NUMBER>2345685</TRX_NUMBER>
      ...
   </G_INVOICE>
   ...
</LIST_G_INVOICE>
...

各G_INVOICE要素には、異なる顧客向けの請求書が含まれている場合があります。Publisherに対して、G_INVOICE要素が出現するたびに新しいセクションを開始するように指示するには、次の構文を使用して、@sectionコマンドをグループの開始のfor-each文に追加します。

<?for-each@section:group name?>

ここで、group_nameは新規セクションを開始する要素の名称です。

たとえば、この例のfor-eachグループ文は次のようになります。

<?for-each@section:G_INVOICE?>

終了の<?end for-each?>タグは変更ありません。

次の図に、バッチ・レポートのサンプル・テンプレートを示します。

ノート:

ヘッダーはコマンドによってリセットされますが、G_INVOICEグループのfor-each宣言はそれまでと同様にレポート本文内にあります。

次の表に、前述の図(バッチ・レポートのサンプル・テンプレートを示す図)のテンプレートのフォーム・フィールドの値を示します。

デフォルト・テキスト入力 フォーム・フィールドのヘルプ・テキスト 説明

for-each G_INVOICE

<?for-each@section:G_INVOICE?>

G_INVOICEグループを開始し、要素をセクションとして定義します。G_INVOICEが出現するたびに、新規セクションを開始します。

<?TRX_NUMBER?>

なし

Microsoft Wordでは、ヘッダーでのフォーム・フィールドの使用はサポートされていないため、TRX_NUMBER要素のプレースホルダ構文はテンプレートに直接配置します。

end G_INVOICE

<?end for-each?>

G_INVOICEグループを終了します。

これで、G_INVOICE要素が新たに出現するたびに、新規セクションが開始します。ページ番号が再び開始され、ヘッダーまたはフッターの情報がデータから抽出されると、同様にリセットされます。

データが見つからない状況の処理

Publisherコマンドのfor-eachまたはfor-each-groupで@sectionを使用し(たとえば: <?for-each@section:ELEMENT_NAME?>)、入力データ・ファイルにデータがない場合、空または無効のPDF出力ドキュメントが、そのfor-eachループに対して生成される可能性があります。これが発生するのを防ぐには、RTFテンプレートを編集します。

データが見つからない状況を処理するには:
  1. RTFテンプレートの終わりに、セクション区切りを追加します。
  2. 最後のページ(新しい項のページ)で、コマンド<?if@section:not(ELEMENT_NAME)?>No Data Found<?end if?>を追加します

    ここで、ELEMENT_NAMEは、for-each@sectionループで使用しているのと同じデータ要素です。

    これで、ELEMENT_NAMEにデータが存在しない場合は、No Data Foundというテキストとともに有効なPDFが生成されます。

ピボット・テーブルの挿入

ピボット・テーブルの列は、データに依存します。

設計時点では、レポートされる列の数や適切な列ヘッダーを把握できません。さらに、列が次のページに分割される場合は、後続のページで繰り返される行ラベル列の定義を可能にする必要があります。次の例では、これらの機能をサポートする単純なピボット・テーブル・レポートの設計方法を説明します。ピボット・テーブルの挿入を参照してください。

この例では、次のXMLサンプルを使用します。

<ROWSET>
  <RESULTS>
    <INDUSTRY>Motor Vehicle Dealers</INDUSTRY>
    <YEAR>2005</YEAR>
    <QUARTER>Q1</QUARTER>
    <SALES>1000</SALES>
 </RESULTS>
  <RESULTS>
    <INDUSTRY>Motor Vehicle Dealers</INDUSTRY>
    <YEAR>2005</YEAR>
    <QUARTER>Q2</QUARTER>
    <SALES>2000</SALES>
  </RESULTS>
  <RESULTS>
    <INDUSTRY>Motor Vehicle Dealers</INDUSTRY>
    <YEAR>2004</YEAR>
    <QUARTER>Q1</QUARTER>
    <SALES>3000</SALES>
  </RESULTS>
  <RESULTS>
    <INDUSTRY>Motor Vehicle Dealers</INDUSTRY>
    <YEAR>2004</YEAR>
    <QUARTER>Q2</QUARTER>
    <SALES>3000</SALES>
  </RESULTS>
  <RESULTS>
    <INDUSTRY>Motor Vehicle Dealers</INDUSTRY>
    <YEAR>2003</YEAR>
     ...
  </RRESULTS>
  <RESULTS>
    <INDUSTRY>Home Furnishings</INDUSTRY>
     ...
  </RESULTS>
  <RESULTS>
    <INDUSTRY>Electronics</INDUSTRY>
     ...
  </RESULTS>
  <RESULTS>
    <INDUSTRY>Food and Beverage</INDUSTRY>
     ...
  </RESULTS>
            
</ROWSET>

このXMLコードから、次の図に示すように、各業種、および各年度の売上合計が表示されるレポートが生成されます。

次の図に、前述の図に示されているレポートを生成するためのテンプレートを示します。

前述の図に示されたテンプレートのフォーム・フィールドには、次の表に示す値が設定されます。

デフォルト・テキスト入力 フォーム・フィールドのヘルプ・テキスト 説明

header column

<?horizontal-break-table:1?>

最初の列を、表の途中で改ページした場合に繰返し表示するヘッダーとして定義します。改ページ時に繰り返す列の定義を参照してください。

for:

<?for-each-group@column:RESULTS;YEAR?>

再グループ化構文(XMLデータの再グループ化を参照)を使用してデータをYEAR別にグループ化し、@columnコンテキスト・コマンドを使用して各グループ(YEAR)の表列を作成します。コンテキスト・コマンドを使用した命令の配置の制御を参照してください。

YEAR

<?YEAR?>

YEAR要素のプレースホルダ。

end

<?end for-each-group?>

for-each-groupループを終了します。

for:

<?for-each-group:RESULTS;INDUSTRY?>

グループを開始して、INDUSTRYごとに表の行を作成します。

INDUSTRY

<?INDUSTRY?>

INDUSTRY要素のプレースホルダ。

for:

<?for-each-group@cell:current-group();YEAR?>

再グループ化構文(XMLデータの再グループ化を参照)を使用してデータをYEAR別にグループ化し、@cellコンテキスト・コマンドを使用して各グループ(YEAR)の表セルを作成します。

sum(Sales)

<?sum(current-group()//SALES)?>

現行グループ(YEAR)の売上を合計します。

end

<?end for-each-group?>

for-each-group文を終了します。

end

<?end for-each-group?>

for-each-group文を終了します。

表の列の数を決定するために@columnコンテキストを使用するのは、最初の行のみであることに注意してください。残りの行はすべて、@cellコンテキストを使用して列の表セルを作成する必要がありますコンテキスト・コマンドを使用した命令の配置の制御を参照してください。

動的データ列の構築

動的データ列の作成機能は、RTFテンプレートの強力な機能の1つです。この機能を使用すると、データによって必要な列の数が変化する場合に、表を正しくレンダリングするテンプレートを設計できます。

たとえば、特定範囲内のテスト・スコアの列を表示するテンプレートを設計するとします。ただし、レポート対象のデータを表示する範囲の数は不明です。この場合は、動的データ列を定義すると、実行時に適切な数の列に分割できます。

次のタグを使用して、データの正しいレンダリングに必要な動的書式設定を設定します。

  • 動的列ヘッダー

    <?split-column-header:group element name?>

    このタグを使用して、表の列ヘッダーを分割するグループを定義できます。

  • 動的列<?split-column-data:group element name?>

    このタグを使用して、表の列データを分割するグループを定義できます。

  • 動的列幅

    <?split-column-width:name?>または

    <?split-column-width:@width?>

    いずれかのタグを使用して、XMLデータに幅が記述されている際の列の幅を定義します。幅は、次のいずれかの方法で記述できます。

    • XML要素に幅の値が格納されます。この場合は、構文<?split-column-width:name?>を使用します。nameは、幅の値が含まれるXML要素のタグ名です。

    • 要素がsplit-column-headerタグで定義されている場合は、width属性を挿入し、構文<?split-column-width:@width?>を使用して、この属性の値を使用します。

  • 動的列幅の単位値(ポイント単位)<?split-column-width-unit:value?>

    このタグを使用して列幅の乗数を定義します。文字セルで列幅が定義されている場合、適切な乗数値を使用して列を適正な幅(ポイント)でレンダリングする必要があります。たとえば、表で10ポイントのcourierフォントを使用している場合、6の乗数を使用します。これは、10ポイントのcourierフォントで表示される文字の近似の幅です。乗数が定義されていない場合、列の幅は、表の全幅の割合として計算されます。次の表に、列幅の計算を示します。

    幅の定義 列1 (Width = 10) 列2 (Width = 12) 列3 (Width = 14)

    乗数なし - %Width

    10/10+12+14*100 28%

    %Width = 33%

    %Width =39%

    乗数 = 6 - width

    60ポイント

    72ポイント

    84ポイント

改ページ時に繰り返す列の定義

表の列が横に広がり複数のページにまたがる場合、ページごとに繰り返す行見出し列の数を定義できます。

次の構文を使用して、繰り返す列数を指定します。

<?horizontal-break-table:number?>

ここで、numberは繰り返す列の数(左から始めます)です。

ノート:

この機能はPDF出力に対してのみサポートされます。

動的データ列の例

学校のテストについて、スコア範囲を表示するためのテンプレートが必要であるとします。論理的には、次の表に示すようにレポートを配置します。

テスト・スコア テスト・スコア範囲1 テスト・スコア範囲2 テスト・スコア範囲3 ...テスト・スコア範囲n

テスト・カテゴリ

範囲1の生徒数

範囲2の生徒数

範囲3の生徒数

範囲nの生徒数

しかし、レポートに表示されるテスト・スコア範囲の数は不明です。テスト・スコア範囲列の数は、データに応じて動的に設定されます。

次のXMLデータは、テスト・スコアを記述したものです。要素<TestScoreRange>の出現回数によって、必要な列の数が決まります。この例の場合は、0-20、21-40、41-60、61-80および81-100の5つの列があります。各列には、数量要素(<NumOfStudents>)および列幅属性(<TestScore width="15">)があります。

<?xml version="1.0" encoding="utf-8"?>
 <TestScoreTable>
  <TestScores>
    <TestCategory>Mathematics</TestCategory>
    <TestScore width ="15">
    <TestScoreRange>0-20</TestScoreRange>
    <NumofStudents>30</NumofStudents>
 </TestScore>
    <TestScore width ="20">
    <TestScoreRange>21-40</TestScoreRange>
    <NumofStudents>45</NumofStudents>
 </TestScore>
   <TestScore width ="15">
    <TestScoreRange>41-60</TestScoreRange>
    <NumofStudents>50</NumofStudents>
 </TestScore>
    <TestScore width ="20">
    <TestScoreRange>61-80</TestScoreRange>
    <NumofStudents>102</NumofStudents>
 </TestScore> 
    <TestScore width ="15"> 
    <TestScoreRange>81-100</TestScoreRange>
   <NumofStudents>22</NumofStudents>
 </TestScore>
 </TestScores> 
  <TestScoreTable> 

フォーム・フィールドで動的列タグを使用して、次の図に示すような2列の表を設定します。最初の列のTest Scoreは静的な列です。2番目の列のColumn Header and Splittingは動的な列です。実行時に、この列はデータに応じて分割され、列ごとにヘッダーが適切に移入されます。次の表に、各フィールドのデフォルト・テキスト入力およびフォーム・フィールドのヘルプ入力を示します。

デフォルト・テキスト入力 フォーム・フィールドのヘルプ・テキスト入力

Group:TestScores

<?for-each:TestScores?>

テスト・カテゴリ

<?TestCategory?>

列ヘッダーと分割

<?split-column-header:TestScore?> <?split-column-width:@width?> <?TestScoreRange?>%

Content and Splitting

<?split-column-data:TestScore?> <?NumofStudents?>

end:TestScores

<?end for-each?>

  • Test Scoreは、ボイラープレート列ヘッダーです。

  • Test Category<TestCategory>データ要素(この例ではMathematics)のプレースホルダで、列ヘッダーにもなります。

  • 2番目の列は、動的に分割される列です。指定した幅がデータの列数で除算されます。この例では、データ列数は5です。

  • 2番目の列には、動的な範囲データが含まれます。列の幅は、分割された列の幅に応じて分割されます。この例には単位値タグ(<?split-column-width-unit:value?>)が含まれていないため、列はパーセントを基準にして分割されます。必要に応じてデータが折り返されます。

    タグ(<?split-column-width-unit:value?>)が含まれている場合、列は特定の幅(ポイント単位)になります。列幅の合計がページに割り当てられた領域より広い場合、その表は次のページに分割されます。

    horizontal-break-tableタグを使用すると、後続のページで繰り返す列の数を指定できます。たとえば、値を1に設定すると、Test Score列が後続のページで繰り返され、最初のページに収まらなかった残りの列とともに表示されます。

このテンプレートをレンダリングすると、次の図のような出力が得られます。