VB6とかを使っていた時には、Professional版以上にCrystal Reportsが付いて来たが、これはあまり使い勝手が良くないという事で、ActiveReportsなどを別途用意して使用している話が多かった。
Visual Studioとしては、印刷そのものにエディションによる違いは無く、コーディングする事で行う事ができる。しかし、レポート出力についてはStandard Editionのレポート機能は簡易版で、Professinal版以上でCrystal Reportsが提供されているのだとか。
その為か、Standard Editionのレポート機能の使い方を詳しく書いたものが簡単に見つからない。一応オンラインのMSDNページには説明があるみたいだが、妙に判り難い。これはCrystal Reportsと同じモノと思って良いのだろうか?
しかし、使った事は無いが、なんだかどこかで見た事がある・・・と思ったら、SQL ServerのReporting Servicesと同じじゃないか。
Reporting Servicesのローカル版といったところだろうか、これは。MSDNを良く見ると「Microsoft レポート」の説明があった。
まあ、レポート関係は殆ど業務でしか使わない為かサードパーティ製品にしても公開されている情報は少ない。ActiveReportsなんかは良く使われているようなのに、書籍とかを見かけた事が無い。
仕事で使うならわざわざ簡易版を使う事なく使い勝手の良いサードパーティ製品を使うと思われるので、余計に簡易版の使い方などはドキュメント化されないのだろう。
しかし、せっかくStandard Editionにもレポートが付いているので、これを使ってみない手はない。
Standard EditionではExpress版と違って、「新しい項目の追加」で選択できるテンプレートの中に「レポート」と「レポートウィザード」があるので、これをプロジェクトに追加する。
「レポートウィザード」は↓データセットの作成を行うウィザードが立ち上がるが、「レポート」はデータセット無しでデザイナーが立ち上がる。
ウィザードに従えば、データソースとしてデータベースを選択し、基本のデータセットとして選択テーブルの定義が出来上がる。
データセットの抽出条件を変更したい場合などは、別途データセットの構成を変更する事になる。
ここでは機能を試して行きたいので、ウィザードを使わず、「レポート」で進めて行く。
「レポートウィザード」では、選択を進めて行くとデザインの雛形も出来上がるが、「レポート」ではデザイナーに白紙があるだけ↓なので、簡単な表形式のレポートを作成する為、ツールボックスのレポートアイテムから「テーブル」をドロップする。
テーブルは、デフォルトで繰り返しデータの先頭に項目名などを表示するヘッダー部分と、データそのものを表示する詳細部分、最後に合計などを表示するフッター部分の3つが3列分表示される。列数は、表示する内容に応じて追加・削除できる。
出力の指定は、テーブルのプロパティで表示したい内容を持つデータセットを選択すれば、後は必要な項目を選択して並べて行くだけ。
デザインは、ここまででとりあえず置いておいて、レポートのデータソースとする為、手元にあるデータベースの適当なテーブルから一覧を抽出するデータセットを作成する。
データソースの新規作成を選択して、ウィザードを表示する。データベースしか用意していないので「データベース」を選択する。
「新しい接続」を選択する。
データソースを選択する。
今回は、Microsoftがサンプルで配布していたNorthwindのMDBファイルを使うので、Accessのデータベースファイルを選択する。
ファイルを指定して、とりあえず全てのテーブルを選択する。
Visual Studio内にリレーション情報も含めて定義が出来上がる。
個々のテーブルのデータ抽出内容は、基本的に無条件で一覧を抽出するような構成になっているので、データセットとして使用する目的に沿うように、テーブル単位のプロパティから構成を変更する必要があるかもしれない。
条件の変更は、SQLを直接変更しても良いし、クエリビルダを使っても良い。今回は、IDに対応する名称を取得する為、ProductsテーブルのデータセットにCategoriesの内容をJOINした。
データセットの準備ができたので、デザインに戻り、左側のデータソースの中から表示したい項目を「詳細」行の任意の列にドロップする。
フォントや表示位置、フォント/背景色などはプロパティから変更できる。
レイアウトは適当に決められるが、そのままでは表示して確認する事ができない。
そこで、新しいフォームを追加して、レポートビューワーコントロールをフォームに貼り付けて、デザインしたレポートと関連付ける。
適当なフォームにビューワーを配置して、
ビューワーの右上にある設定マークから作成済みのレポートを選択する。
特にコードを書かなくても、これで実行すればフォーム上でプレビューする事ができるようになる。
とりあえず、レポートビューワーに表示できれば、ビューワーの機能を使って表示の切り替えや印刷出力ができる。
デフォルトでは表示されていないが、レポートにはページごとにヘッダー/フッターを出力する事もできる。
レポートを選択した時にメニューバーに表示される「レポート」メニューから、「ページ ヘッダー」「ページ フッター」を選択すると各々の領域がレポートに追加される。
レポートアイテムからテキストボックスなどを配置して、タイトルなどを設定する。ページ番号や印刷日付などは<式>から変数などを使用して表示させる事ができる。
ページヘッダーにタイトル、ページフッターにページ番号、偶数行に背景色を指定してビューワーで表示してみた。
レポートの代表的な使い方は、こんなモノだろうか?
グループごとにまとめたい場合は、レポートのプロパティで「グループの挿入」を選択し、「グループ化の条件」欄にキーとなる項目を指定する。
Categoryをキーにしてグループ化し、グループ名行に背景色を指定してみた。
これだけできれば、けっこう使えそうな感じではある。
レポートアイテムには、コンテナとして使える四角形などが用意されているので、コンテナの中に複数のアイテムを載せてテーブルなどと組み合わせれば、1行表現以外の表現方法を取る事もできる。また、別途画像を用意しておけば、画像を使用する事もできる。
今回は、「レポート」メニューの「埋め込み画像」から画像を登録して使用してみた。
各グループの最後にコンテナの四角形を表示し、レポートの最後にイメージとテキストを重ね合わせて配置。
画像アイテムには、埋め込み画像を指定したが、他にも外部ファイルや、データベースに保存されたイメージなどを使用できるように書いてある。
そのまま表示させると、こんな感じ。グループごとに四角形が表示され、最後にイメージと文字を表示。
これで、行形式以外の詳細データも出力できるようになった。
グラフも同じ要領でグループごとに挿入する事ができる。
グラフアイテムをテーブルにドロップし、表示する内容はデータソースから項目をドロップすれば設定終了。
各CategoryごとにProductとそのUnitPriceをグラフにしてみた。
グラフの種類は結構多い。機能も簡易版という感じではない。
さて、レポートものであれば、備えているであろう便利機能のサブレポートがこれにも用意されている。
ちょっと面倒だが、GUIベースで設定するか、コードベースで設定するかで、また変わってくるんだろう。
Category内のProductごとにOrder Detailsの内容を一覧してみる。(グラフの時と同じで表示内容に意味は無い。単に適当なデータが欲しかっただけ)
サブレポートアイテムをテーブルの繰り返し位置にドロップし、別途作成しておいたレポートの名前を指定する。
サブレポートとして使用するテーブルは別途作成しておく。単独で実行テストもしておく。
親レポートからパラメータを受け取るので、その為のパラメータを「レポートパラメータ」で作成する。
子レポートの内容はOrder Detailsテーブルの内容を表示するので、データセットをOrder Detailsのモノにセットする。
子レポートは、親レポートから渡されたProductIDに一致するモノだけを表示するので、フィルタとしてProductIDとパラメータが一致する場合という条件を追加する。
親レポートに戻って、サブレポートアイテムのプロパティで使用するサブレポートの名前を指定する。
親レポートが子レポートに渡すパラメータとして、子レポートで定義したパラメータに親レポートのProductIDをセットするように設定を追加。
これで準備完了、と思いきやビューワーでサブレポートがエラーになる。
検索してみると、マイクロソフトのサイトのVisual Studio 2005部分に同様なエラーになるパターンが載っていた。
ビューワーでサブレポートを表示するには、サブレポートのイベントハンドラーをコードで書いてやらないといけないんだそうだ。多分、2008でも同じだろう。
マイクロソフトのサンプルの通り、ビューワーを呼び出すフォームにイベントハンドラーの記述を追加。
this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(SubreportProcessingEventHandler); this.reportViewer1.RefreshReport();参照とハンドラー自体も追加。
using Microsoft.Reporting.WinForms;void SubreportProcessingEventHandler(object sender, SubreportProcessingEventArgs e) { e.DataSources.Add(new ReportDataSource("Nwind2KDataSet_Order_Details", this.Nwind2KDataSet.Order_Details)); }で、サブレポートが出力されるようになった。
ビューワーでサブレポートを表示する時は、TableAdapterのデータ読み込み処理が自動で追加されていない時があるので、イベントハンドラーと合わせてソースを見ておく必要がある。
まあ、全体的に自動で追加されるような定義は要注意。思ったようにはなっていない場合がある。(特に削除とか、取り消しとかした場合)
細かいデザイン調整が絡むと結構悩みそうだが、いろいろ小細工はできそうな感じはある。
バーコード出力ができないのだけは残念。
ActiveReportsと比べると、レポート物独自の考え方はあるにしても、ActiveReportsの方がもっと判りやすい気がする。慣れの問題かもしれないが・・・。
しかし、コードをあまり触らずにここまで出来れば、非常に便利。(自動生成された部分とか中身を気にすると、ちょっと怖いが・・・)
関連ページ -> Visual Studio 2008 Standard EditionのWebBrowserコントロール