本稿は、連載『5分でわかるActiveReports帳票(2007年度版)』(渡辺俊史・宮本奈紗 著)の増補改訂版です。
対象読者
- Visual Basic.NETまたはVisual C#を使ってプログラムを作ったことのある方
- 帳票作成ツールに興味のある方
必要な環境
-
Visual Studio 2008 SP1/2010/2012のいずれかでプログラムが作れる環境
(Express EditionではActiveReportsをインストールできません)
本記事のサンプルコードは、C#/Visual Basic 2012で記述しています。
ページレポート:Tableデータ領域
ページレポートの「データ領域」(第2回参照)には、List、BandedList、Table、Matrixなどがあります。前回はListを使用しましたが、今回はTableを使用してみましょう。
データソースとデータセットの追加
プロジェクトにページレポートを追加して、データソース、データセットを追加します。詳しい手順については第2回を参考にしてください。
第2回と同じように、製品に付属するAccessファイルのNwind.mdbに接続します。「種類」は「Microsoft OleDb Provider」、「接続設定」の「OLE DBプロバイダ」には「Microsoft Jet.OLEDB.4.0」を指定します。
データセットに使用するクエリは以下のようにします。このクエリは、製品名・種類名・製品毎の売上金額を得るものであり、Nwind.mdb内にある「Sales by Category」クエリと同じSQL文です。
SELECT DISTINCTROW Categories.CategoryID, Categories.CategoryName, Products.ProductName, Sum([Order Details Extended].ExtendedPrice) AS ProductSales FROM Categories INNER JOIN (Products INNER JOIN (Orders INNER JOIN [Order Details Extended] ON Orders.OrderID = [Order Details Extended].OrderID) ON Products.ProductID = [Order Details Extended].ProductID) ON Categories.CategoryID = Products.CategoryID WHERE (((Orders.OrderDate) Between #1/1/1995# And #12/31/1995#)) GROUP BY Categories.CategoryID, Categories.CategoryName, Products.ProductName ORDER BY Products.ProductName;
Tableの配置
Tableをページレポートに配置します。ツールボックスの「ActiveReports 7ページ」タブから「Table」を選んで、ドラッグ&ドロップします。次に、「FixedSize」と「Size」プロパティに適切な値を設定してページ上の大きさを決めます。こうした設定はListと同様なので第2回をご参照ください。
Tableは、デフォルトでは3行3列の表となっています。
列(縦方向)については、追加して4列以上に増やすことができます。また、削除して2列や1列で使用することも可能です。
一方、横方向の3行はそれぞれ役割が異なります。デフォルトで定義されている3行のうち、一番上の行は「テーブルのヘッダ」、2行目は「テーブルの詳細」、一番下の行は「テーブルのフッタ」です。
一番重要なのは「テーブルの詳細」です。セクションレポートにおけるDetailセクションに当たるものです。通常はこの行がデータを表示する行になります。
また、「グループヘッダ」「グループフッタ」の行も追加することができますが、これについては後述します。
テーブルの詳細へのフィールドの設定
テーブルの一個一個のセルには、デフォルトではTextBoxコントロールが配置されています。TextBoxコントロールの代わりにBarcodeコントロールやImageコントロールなどの別のレポートコントロール(ただしデータ領域コントロールを除く)を配置することも可能です。
このため、デザイン作業中に、「Table自体のプロパティを設定したいのに、Table上のセルに配置されているTextBoxコントロールをクリックしてしまい、TextBoxコントロールのプロパティの方を設定してしまう」ということがありがちです。Table自体のプロパティを設定したい時には、FixedSizeプロパティを設定した時に現れる斜線部分か、セルを選択した時にTableの外側に表示されるタブ部分(アイコンなどが表示されている部分)の一番左上のマスをクリックしてください。
テーブルの詳細行にデータを表示させてみましょう。マウスをテーブル詳細行のセルの上に動かすと、「フィールド選択装飾」アイコンがセルの右端のあたりに表示されます。そこをクリックすると、使用できるフィールドの一覧が表示されます。表示したいフィールドを選んでクリックしてください。
また、レポートエクスプローラのデータセットを展開し、出力したいフィールドをTableのセル上にドラッグ&ドロップすることによっても設定が可能です。この操作はListと同様です。
このようにしてTableの詳細行にフィールドを設定すると、その直上にある「テーブルのヘッダ」行にフィールド名が自動的に設定されます。つまり、フィールド名を自動的に見出しとして設定します。
もし、見出しを別の文字列に変更したい場合は、そのセルをクリックしてから、TextBoxコントロールの「Value」プロパティを変更するか、セルをダブルクリックしてデザイン画面から直接入力してください。
この段階でプレビューしても立派な表になっていますが、もう少し見栄えを良くしてみましょう。
Tableは各要素が整列しているので、罫線を引くことも簡単です。セルをクリックして、プロパティのBorderStyleを「Solid」にすれば、セル(TextBoxコントロール)の回りに罫線が表示されます。ドラッグで複数のセルを一括選択しておいてから、BorderStyleプロパティをまとめて設定することもできます。
Tableのヘッダ行は、デフォルトではレポートの最初に1回しか表示されません。毎ページ表示されるように変更してみます。
Tableのヘッダ行の行タブ(行アイコンがある場所)をクリックします。プロパティウィンドウに行名が「TableRow1」と表示されたら、「行」のプロパティが編集できるようになっています。この中の「RepeatOnNewPage」プロパティをTrueに設定すると、テーブルヘッダ行が毎ページ先頭に表示されるようになります。セクションレポートで言えばグループヘッダのRepeatStyleプロパティをOnPageにしたのと同様な動作になります。
また、Tableのフッタ行も使用してみましょう。フッタ行の3列目のセルをクリックし、TextBoxコントロールのValueプロパティに「ページ終わり」と記述します。
なお、フッタ行もヘッダ行と同様にデフォルトではTableの最後に1回しか表示されないので、RepeatOnNewPageプロパティをTrueに設定しておきます。
以上のように設定したレポートを実行すると、上辺に見出しが表示され、下辺に「ページ終わり」と表示されるレポートが表示されます。
式
単純なレポートの場合、比較的簡単なデザイン作業で実現することができました。ただし、実際のレポートにはいろいろな要望が存在します。例えば上記レポートについて、「売上金額を千円単位で表示したい」という要望が出てくるかもしれません。SQL文を工夫することで実現することも可能ですが、さらに複雑な要望になるとSQL文だけで対処するのは難しくなります。
フィールドを設定した詳細行のデザイン画面を見ると、=[CategoryName]とか=[ProductSales]のように、イコールと角カッコでフィールド名が挟まれたものが表示されています。このような記述をページレポートでは「式」と言います。
デザイン画面上に表示されている文字列は、そのTextBoxコントロールのValueプロパティの値です。なお、デザイン画面上では=[ProductSales]と表示されておりますが、プロパティウィンドウには=Fields!ProductSales.Valueと表示されます。これは、デザイン画面上では短縮形で表示されているためです。
短縮形 | =[ProductSales] |
---|---|
基本形 | =Fields!ProductSales.Value |
ページレポートの式は、Visual Basic.NET類似の構文で記述される一種のスクリプトです。式を使用することで、データを加工して表示することや、より高度なレイアウトを実現できるようになります。
式の記述
式の記述方法を見てみましょう。詳細行のTextBoxコントロールを選択した状態で、プロパティウィンドウのValueプロパティを選択します。すると右端にボタンが表示されますのでクリックしてください。ドロップダウンリストが表示されます。
リストの一番上に表示されている「〈式…〉」を選択すると、式エディタダイアログが表示されます。
式エディタでは、短縮形ではなく基本形で式を表示/編集します。
式の先頭に付いているイコールは「式として評価する」ための記号なので、固定文字列を表示させる場合以外は常に必要です。
例えば「=Fields!ProductSales.Value」という式は、「ProductSales」という名前のフィールドから得られる値を出力するということを表しています。このフィールドの値を1000で割った時の値を得たい場合には、以下のような式を設定します。
=Fields!ProductSales.Value /1000
さらに、末尾に「千円」とつけたい場合には、&で文字列連結を行い、以下のように設定します。
=Fields!ProductSales.Value /1000 & "千円"
これで、「ProductSales(売上金額)」が千円単位で表示されるようになります。
式で使える関数など
式で使える関数、演算子、フィールドは多数あります。詳しくは、製品ヘルプの[概念]-[ページレポートの概念]-[式]をご覧ください。ここでは代表的なものをいくつか紹介します。
演算子
通常の四則演算や、Visual Basicで一般的な演算子は使用可能です。上記の例では除算の「/」と連結の「&」を使っています。
日付・時刻
現在の日付時刻を取得するためのフィールドが、以下の形で用意されています。
=Globals!ExecutionTime
また、Microsoft.VisualBasic.DateAndTimeのメソッドが使えるので、例えば西暦年だけを抽出したい場合は以下のようにします。
=Year(Globals!ExecutionTime)
これはデータソースからの値に適用することも可能です。例えばDateTime型のフィールド「DateFieldX」に対してYearメソッドを適用する場合、以下のような式になります。
=Year(Fields!DateFieldX.Value)
ページ番号・総ページ数
現在のページ、総ページを取得するフィールドが用意されています。
現在のページ:=Globals!PageNumber 総ページ:=Globals!TotalPages
プログラムフロー
Microsoft.VisualBasic.InteractionクラスのIIFメソッドが使えます。(C#の三項演算子「?:」に類似します)。例えば、FieldAが偶数か奇数かによってデータを取得するフィールドをFieldBとFieldCで切り替える場合、以下のような式になります。
=IIF(Fields!FieldA.Value mod 2 = 0, Fields!FieldB.Value , Fields!FieldC.Value )
ページレポートのスクリプト
式だけで高度な制御を行うことが可能ですが、より複雑な処理を実装する場合や、同じ処理を複数の箇所で使用したい場合、メンテナンス性に問題が生じる場合があります。このように複数の箇所で使用する複雑な処理は、「スクリプト」タブの中に関数として定義しておき、それを参照することができます。
ページレポートのデザイン画面には、「スクリプト」タブがあります。これを開いてVisual Basicの構文でスクリプトを記述します。
例えば、先程の「千円単位で表示する」という処理を関数として定義する場合、以下のようになります。
Public Function To1000Yen(value As Integer) As String Dim v As Single = value / 1000 Return v & "千円" End Function
この関数を呼び出す場合も式を使います。具体的には「=Code.〈メソッド名〉」と記述します。例えば、以下のようになります。
=Code.To1000Yen(Fields!ProductSales.Value)
上記の式では、関数「To1000Yen」の引数に、処理する値を与えるフィールドを設定しています。
式はTextBoxコントロールのValueプロパティだけでなく、他のさまざまなプロパティでも使用できます(ただしExpressionInfo型のプロパティに限ります)。
例えば、明細などで一行おきに別の背景色を設定したい場合、BackGroundColorプロパティに式を設定することで実現できます。
Tableの詳細行にあるTextBoxコントロールのBackGroundColorプロパティに、以下の値を設定すると、背景色を一行おきに変化させることができます。
=iif(RowNumber(Nothing) Mod 2, "PaleGreen", "White")
ぜひ試してみてください。
Tableでのグループ化
Tableでは、データのグループ化を行うことが可能です。
左端の行タブを右クリックし、「グループの挿入」を選択します。グループヘッダ行とフッタ行がTableに追加されます。
上から、テーブルヘッダ、グループヘッダ、詳細、グループフッタ、テーブルフッタです。
グループを追加すると、Tableグループダイアログが出てきます。ここで、グループのキーとするフィールドを式で指定します。ここでは、CategoryIDフィールドを指定します。
Tableにグループヘッダとフッタが追加され、CategoryIDの値によってグループ分けされるようになりました。なお、Tableグループダイアログは、Table全体の設定ダイアログから呼び出すことも可能です。
グループヘッダ・フッタのレイアウト
グループヘッダ・フッタに配置できるものは「グループを通じて変化しないもの」か「グループ全体の集計値」です。
上記の例では、グループのキーとなっているCategoryIDがグループで変化しないフィールドです。この場合、CategoryIDごとのカテゴリー名を格納しているCategoryNameもそのグループを通じて変化しないので、グループヘッダにCategoryNameを表示させることが可能です。
グループフッタ上の左端のTextBoxコントロール上にマウスカーソルをあわせ、表示される選択装飾アイコンから「CategoryName」を選択すると、以下のような式がValueプロパティに設定されます。
=First(Fields!CategoryName.Value)
詳細行でCategoryNameを選択したときは「=Fields!CategoryName.Value」と設定されますが、グループヘッダ上でアイコンから選択すると、グループの最初のデータを得る「First」関数が自動的に付きます。グループ化された複数のレコードの内、どのレコードをグループヘッダ上に表示するか、明確に設定するためです。
グループの集計
次に、グループで集計を取ってみましょう。グループフッタ上の右端のTextBoxコントロール上にマウスカーソルをあわせ、表示される選択装飾アイコンから「ProductSales」を選択すると、以下のような式がValueプロパティに設定されます。
=Sum(Fields!ProductSales.Value)
今度は、値の合計を得る集計関数である「Sum」関数が自動的に付きました。これで、グループごとの「ProductSales」の合計が表示されるようになります。
このようにグループヘッダ/フッタ上で選択装飾アイコンからフィールドを選択すると、自動的に集計関数が付加されます。付加される関数は、数値型なら合計を表す「Sum」、それ以外なら最初の項目を表す「First」です。
グループ化とデータの並び順
ここまでの説明で作成した、グループ化していない単純なレポートとグループ化されたレポートをご覧ください。
グループ化されたレポートは、CategoryIDでグループ化されており、CategoryIDの順番で出力されています。しかしながら、これらのレポートのデータソースとして設定しているSQL文は、グループ化していない単純なレポートと同じものです。
セクションレポートでグループ化する場合、データを抽出するSQL文にORDER BY句を設定するなどして、あらかじめグループ化したい順番にデータを整列させておく必要がありました。
それに対して、ページレポートでグループ化する場合、レポート側の機能で自動的にデータのグループ化を行います。データソースをあらかじめ整列させておく必要はありません。
グループのソート
また、値に従って並べ替え(ソート)が可能です。Tableのプロパティ設定ダイアログを開き、「グループ」の項目から「並べ替え」のタブを開きます。
「並べ替え」のための式を追加するパネルがあります(複数設定可能)。ここに、並べ替えの基準となる数値(番号や日付など)となる式を設定すれば、グループ単位で自動的に並べ替えが行われます。ここではCategoryIDフィールドを設定してみます。実行させるとCategoryIDの数値が小さい順にグループが並びます。なお、並び順を「降順」に設定して数値が大きい順に並ばせることも可能です。
グループのフィルタ
式を使ってフィルタリングし、特定の条件を満たすデータのみ出力することも可能です。Tableのプロパティ設定ダイアログを開き、「グループ」の項目から、「フィルタ」のタブを開きます。
例えば「CategoryID=3のデータは表示しない。それ以外のデータは表示する」という要件を満たしたい場合、以下のように設定します。
- 緑の+ボタンを押して、フィルタ式を追加する。
- 式欄にCategoryIDを設定する。
- 演算子欄に「NotEqual」を設定する。
- 値欄に「3」を設定する。
これで「CategoryID=3のデータは表示しない(CategoryIDが3と等しくないデータのみ表示する)」フィルタが設定されます。このレポートを実行するとCategoryID=3のデータはTableに表示されません。
Tableのレイアウトについて
最後に、Tableのレイアウトについていくつか説明します。
行の追加
Tableはデフォルトではテーブルヘッダ、詳細、テーブルフッタの3行が定義されています。また、グループを追加するとさらにグループヘッダ、グループフッタの各行が追加されます(複数のグループをネスト(入れ子)することも可能です)。
詳細行が1行だけだと、1レコードを複数行として表示したい場合には不便です。具体的には、1レコード中の異なる2つのフィールドを2行に分けて表示したいなどの要件が考えられます。このような場合Tableの行を追加することができます。行タブを右クリックして、「上に行を挿入」か「下に行を挿入」を選択します。すると、同じ種類の行(詳細行なら詳細行、グループヘッダ行ならグループヘッダ行)を複数行にすることができます。
セルの結合
横方向のセル同士は、セルの結合が可能です。横方向にセルをドラッグで選択し、右クリックします。セルの結合、および結合したセルの分割が可能です。
なお、縦方向にセルを結合させることは、同じ種類の行であってもできません。
Containerコントロール
より柔軟なレイアウトにしたい時には、Containerコントロールを使用してください。
Containerコントロールは他のコントロールを貼り付けるコントロールで、WindowsフォームのPanelコントロールに似た働きをします。これをTableのセルに配置すると、その上に自由にTextBoxなどのコントロールを配置することができます。
まとめ
今回はページレポートのTableを使用したグループ化の方法や「式」の使い方を紹介しました。
次回はセクションレポートに戻って、コードを使用してレポートを制御する方法を紹介します。