本稿はActiveReportsの旧バージョンを用いた内容となっています。最新版に基づいた記事は連載の目次「5分でわかるActiveReports帳票」をご参照ください。
はじめに
ActiveReports for .NET(以下ActiveReports)は、Visual Studioと統合された使いやすいレポートデザイナや高機能なレポートビューワ、多彩な出力形態をサポートする帳票作成コンポーネントです。今回は、Professional Editionで提供されているDesignerコントロールを利用して、レポートファイル(.rpxファイル)を編集するアプリケーション(ランタイムデザイナ)を作成する方法について紹介します。
過去の連載記事
- 第1回:5分でわかるActiveReports帳票-らくらく始める帳票作成
- 第2回:5分でわかるActiveReports帳票-集計処理と改ページ
- 第3回:5分でわかるActiveReports帳票-改ページ制御と多段組レイアウト
- 第4回:5分でわかるActiveReports帳票-罫線・折り返しとプレビュー・印刷
- 第5回:5分でわかるActiveReports帳票-さまざまなデータソースの利用とデータのグラフ表示
対象読者
- C#またはVisual Basicでプログラムを作ったことのある方
- 帳票作成ツールに興味のある方
必要な環境
開発ツール
- Visual Studio 2008
- Visual Studio 2005(※Windows Vistaで開発する場合はVisual Studio 2005 Service Pack 1 Update for Windows Vistaの適用が必要です)
- Visual Studio .NET 2003
Express EditionではActiveReportsをインストールできません。
開発言語
本記事のサンプルコードはC# 2.0/Visual Basic 2005で記述しています。
ランタイムデザイナとは
ActiveReportsのProfessional Editionでは、Visual Studioでの帳票開発と同じ感覚でレポートファイル(rpxファイル)を編集するためのコントロール類が提供されています。ランタイムデザイナとは、これらのコントロールを利用して作成された、配布可能なデザイナアプリケーションのことです。開発したランタイムデザイナをエンドユーザーに配布することで、ユーザーはレポートファイルを自分で編集できるようになります。
なお、ランタイムデザイナ機能はProfessional Editionのみの機能ですが、Standard Editionでもトライアル版としてランタイムデザイナの機能を使うことができます。
最終的な完成イメージ
今回作成するランタイムデザイナについて説明します。
Visual Studioのレポートデザイナと同じように、左側にはにツールボックス、中央にレポートデザイナ、右側にレポートエクスプローラとプロパティグリッドを配置しています。レポートファイルのオープンや保存などはメニューバーから実行します。
ランタイムデザイナは大きく分けて以下の4つのパーツに分かれています。
デザイナのパーツ
- デザイナ部分(DataDynamics.ActiveReports.Design.Designerコントロール)
- レポートエクスプローラ部分(DataDynamics.ActiveReports.Design.ReportExplorerコントロール)
- プロパティグリッド部分(System.Windows.Forms.PropertyGridコントロール)
- ツールボックス部分(DataDynamics.ActiveReports.Design.Toolbox.Toolboxコントロール)
これらのコントロールをフォームに配置し、プロパティの設定によって相互に関連づけるだけで簡単にランタイムデザイナを作成できます。
コンテナ(フォーム)を組み立てる
それではさっそく、ランタイムデザイナの作成に入りましょう。まずVisual Studioで空のソリューションを作成してください。ソリューションを作成したらそれを右クリックして、[追加]-[新しいプロジェクト]の順に選択し、「新しいプロジェクトの追加」ダイアログを表示させます。ここで、プロジェクトテンプレートは「Windows フォーム アプリケーション」を選択してください。プロジェクトを作成すると、Visual StudioのデザイナにデフォルトのFormコントロールが表示されるので、ここにPanelコントロールとSplitterコントロールを配置していきます。
まず最初は、左側のツールバーを配置するエリアを作成します。フォームへPanelコントロールをドロップし、DockプロパティをLeftに設定してください。それから、フォームへSplitterコントロールをドロップし、Panelコントロールと同じようにDockプロパティをLeftに設定してください。
次に右側の、レポートエクスプローラとプロパティグリッドを表示するエリアを作成します。左側のエリアを作ったときと同じように、PanelコントロールとSplitterコントロールをフォームへドロップして、それぞれのDockプロパティを今度はRightに設定してください。
右側のエリアはさらに上下2つに分かれているので、ここにPanelコントロールとSplitterコントロールをもう1つ追加します。DockプロパティはTopに設定します。
図はここまでの作業で配置した各PanelコントロールのBackColorプロパティを変更して、コントロールの境界がわかるようにしたものです。一度、このプロジェクトをデバッグ実行して、Panelの各領域の境界がドラッグ&ドロップで変更可能かどうか確認してみてください。
コントロールを配置する
フォームへの配置とプロパティの設定
フォームの土台部分の準備ができたら、次はコントロールをフォームに配置していきます。ツールボックスにActiveReportsのコントロールが追加されていない場合は、第1回の記事を参考に、コントロールを追加してください。

ツールボックスからDesignerコントロールを選択し、フォーム中央の領域にドロップしてください。Designerコントロールの初期サイズはかなり大きいのでドロップすると大部分がはみ出してしまいますが、ここで特にサイズを調整する必要はありません。Designerコントロールをドロップしたら、DockプロパティをFillに設定すると、サイズが自動的に調整され、フォームの中にすっぽりと納まります。
同じように、右上の領域にはReportExplorerコントロールを、右下の領域にはPropertyGridコントロールをそれぞれドロップし、DockプロパティをFillに設定してください。
コントロールを配置したら、次は各コントロールを相互に関連付けていきます。まず、DesignerコントロールのPropertyGridプロパティに、いま追加したPropertyGridコントロール(デフォルトではpropertyGrid1)を設定します。それから、ReportExplorerコントロールのReportDesignerプロパティに、Designerコントロール(デフォルトではdesigner1)を設定します。
Toolboxコントロールを配置する
次は、ランタイムデザイナにコントロールを配置するためのツールボックス部分を作成します。今回は、ツールボックス部分のコントロールとして、ActiveReports付属のサンプルを使用することにします。
ActiveReprtsのインストールフォルダ(通常はC:\Program Files\ActiveReportsNET3)に含まれるSamplesフォルダには、ActiveReportsの機能を活用した、実用的なサンプルが多数収録されています。ここで、Samples\VS2005\CS\Professional\RuntimeDesignerフォルダ(VBの場合はSamples\VS2005\VB\Professional\RuntimeDesignerフォルダになります)にあるToolboxClassLibというフォルダを適当な場所へコピーしてください。
フォルダのコピーが終わったら、Visual Studioでランタイムデザイナを作成しているソリューションを開き、右クリックメニューから[追加]-[既存のプロジェクト]を選んで、ToolboxClassLibフォルダの中にあるToolboxClassLib.csproj(vbproj)を選択します。Visual Studio 2008を使用している方は、ToolboxClassLib_2k8.csproj(vbproj)のほうを選択してください。ソリューションにプロジェクトを追加すると、Visual Studioのツールボックスに「ToolboxClassLib(VS2008の場合はToolboxClassLib_2k8)コンポーネント」というタブが作成され、Toolboxコントロールが利用可能になるので、これをフォーム左側のPanelコントロールへドロップします。
サンプルのToolboxコントロールはプロパティグリッドにDockプロパティが出てこないので、フォームのLoadイベントで値を設定します。Loadイベントでは、DesignerコントロールのToolboxプロパティに、いま追加したToolboxコントロールを指定します。また、ToolboxコントロールのDockプロパティをFillに設定します。
private void Form1_Load(object sender, EventArgs e) { this.designer1.Toolbox = this.toolbox1; this.toolbox1.Dock = DockStyle.Fill; }
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Load Me.Designer1.Toolbox = Me.Toolbox1 Me.Toolbox1.Dock = DockStyle.Fill End Sub
イベントを追加する
MenuStripコントロールを追加する
コントロールの配置が終わったら、次はこのフォームにrpxファイルのオープンや保存、デザイナに配置したコントロールを編集するためのイベント処理を実装していきます。今回はイベントを起動するためのコントロールとして、フォームにMenuStripコントロールを追加します。ランタイムデザイナのフォームにMenuStripコントロールをドロップし、トップレベルのメニュー項目として「File」と「Edit」を追加し、「File」メニューのサブメニューには「Open」「Save As」を、「Edit」メニューのサブメニューには「Undo」「Redo」「Cut」「Copy」「Paste」をそれぞれ追加します。


MenuStripにメニューアイテムを追加して表示名(キャプション)を設定すると、その名前がコントロール名の一部に使われてしまいます。そこで、表示名を最初は英語で入力しておき、後からTextプロパティを日本語に変更する方法がおすすめです。また、ここで表示名に「&[アクセスキーのアルファベット]」のような書式の文字を入れると、アクセスキーを設定できます。この他、好みに合わせてShortCutKeysプロパティを設定することも可能です。


イベントを設定する
MenuStripコントロールを構成したら、次は各メニュー項目にイベントを設定していきます。ここでは、「ファイル」メニューの「開く」に「rpxファイルを開いてDesignerコントロールへ展開する」という処理を実装します。イベント処理を記述する前に、ソースファイルの先頭に以下のusingディレクティブ(Importsステートメント)を追加しておきましょう。
using DataDynamics.ActiveReports; using DataDynamics.ActiveReports.Design; using DataDynamics.ActiveReports.Design.Toolbox;
Imports DataDynamics.ActiveReports Imports DataDynamics.ActiveReports.Design Imports DataDynamics.ActiveReports.Design.Toolbox
ランタイムデザイナで編集しているレポートファイルに対する操作は、DesignerコントロールのExecuteActionメソッドを実行することで実現します。ExecuteActionメソッドでは、DesignerAction列挙体でアクションの種類を指定します。ここでは、「ファイル」メニューの「開く」というメニュー項目をダブルクリックして、Clickイベントを実装します。
private void openToolStripMenuItem_Click(object sender, EventArgs e) { this.designer1.ExecuteAction(DesignerAction.FileOpen); }
Private Sub OpenToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles OpenToolStripMenuItem.Click Me.Designer1.ExecuteAction(DesignerAction.FileOpen) End Sub
同じ要領で、メニューに追加したほかの項目にもイベントを実装していきます。なお、切り取りやコピーなどのように選択中のオブジェクトを操作するタイプのイベントでは、PropertyGridコントロールのSelectedObjectプロパティで対象のオブジェクトが指定されていることを確認しています。
//名前をつけて保存 private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { this.designer1.ExecuteAction(DesignerAction.FileSave); } //元に戻す private void undoToolStripMenuItem_Click(object sender, EventArgs e) { this.designer1.ExecuteAction(DesignerAction.EditUndo); } //やり直し private void redoToolStripMenuItem_Click(object sender, EventArgs e) { this.designer1.ExecuteAction(DesignerAction.EditRedo); } //切り取り private void cutToolStripMenuItem_Click(object sender, EventArgs e) { if (propertyGrid1.SelectedObject != null) { this.designer1.ExecuteAction(DesignerAction.EditCut); } } //コピー private void copyToolStripMenuItem_Click(object sender, EventArgs e) { if (propertyGrid1.SelectedObject != null) { this.designer1.ExecuteAction(DesignerAction.EditCopy); } } //貼り付け private void pasteToolStripMenuItem_Click(object sender, EventArgs e) { this.designer1.ExecuteAction(DesignerAction.EditPaste); }
'名前をつけて保存 Private Sub SaveAsToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles OpenToolStripMenuItem.Click Me.Designer1.ExecuteAction(DesignerAction.FileSave) End Sub '元に戻す Private Sub UndoToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles UndoToolStripMenuItem.Click Me.Designer1.ExecuteAction(DesignerAction.EditUndo) End Sub 'やり直し Private Sub RedoToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles RedoToolStripMenuItem.Click Me.Designer1.ExecuteAction(DesignerAction.EditRedo) End Sub '切り取り Private Sub CutToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles CutToolStripMenuItem.Click If Me.PropertyGrid1.SelectedObject Is Nothing Then Me.Designer1.ExecuteAction(DesignerAction.EditCut) End If End Sub 'コピー Private Sub CopyToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles CopyToolStripMenuItem.Click If Me.PropertyGrid1.SelectedObject Is Nothing Then Me.Designer1.ExecuteAction(DesignerAction.EditCopy) End If End Sub '貼り付け Private Sub PasteToolStripMenuItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) _ Handles PasteToolStripMenuItem.Click Me.Designer1.ExecuteAction(DesignerAction.EditPaste) End Sub
ランタイムデザイナの機能を制限する
Designerコントロールを使うと、フォームにコントロールを貼り付けてメニューにイベントを追加していくだけでも、かなり多機能なランタイムデザイナを作成することができます。反面、このような自由度の高い帳票編集アプリケーションは、エンドユーザーの操作ミスによってレポートファイルを破損してしまう可能性もあり、業務の現場で利用するには強力すぎるかもしれません。ここからは、開発したランタイムデザイナをユーザーの利用環境に合わせて機能を制限していく方法について解説します。
Designerコントロールの機能を制限する
ランタイムデザイナの中心部とも言えるDesignerコントロールの機能を制限するには、コントロールの各種プロパティを設定するのが簡単です。例えば、デザイナ下部に表示されているタブを非表示にするには、ReportTabsVisibleプロパティをFalseに設定します。「スクリプト」タブや「プレビュー」タブなど、個々のタブを非表示にする場合は、EnableScriptingプロパティ、EnablePreviewタブをそれぞれFalseに設定します。
また、Detailセクションのバーに表示されているアイコンをクリックすると、レポートデータソースの接続先情報を編集できますが、ここで定義されているデータベース接続文字列やSQLを誤って変更されると、レポートファイルが起動しなくなってしまいます。接続情報の変更を防ぐためには、このデータソースアイコンを非表示にします。
データソースアイコンを非表示にするには、ShowDataSourceIconプロパティをFalseにします。データソースだけでなく帳票レイアウトそのものをレポートそのものを編集できないようにするには、LockControlsプロパティをTrueにします。
private void Form1_Load(object sender, EventArgs e) { this.designer1.Toolbox = this.toolbox1; this.toolbox1.Dock = DockStyle.Fill; //「スクリプト」タブを非表示にする this.designer1.EnableScripting = false; //「プレビュー」タブを非表示にする this.designer1.EnablePreview = false; //データソースアイコンを非表示にする this.designer1.ShowDataSourceIcon = false; //コントロールをロック(編集不可)にする this.designer1.LockControls = true; }
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Load Me.Designer1.Toolbox = Me.Toolbox1 Me.Toolbox1.Dock = DockStyle.Fill '「スクリプト」タブを非表示にする Me.Designer1.EnableScripting = False '「プレビュー」タブを非表示にする Me.Designer1.EnablePreview = False 'データソースアイコンを非表示にする Me.Designer1.ShowDataSourceIcon = False 'コントロールをロック(編集不可)にする Me.Designer1.LockControls = True End Sub
右クリックメニューを抑制する
Designerコントロールを右クリックして表示されるコンテキストメニューには、グループヘッダやグループフッタを追加する機能が含まれています。レポートファイルにグループが追加されるとレポートのデータ構造や集計単位が大きく変わってしまうため、ここもデータソース同様、設定の難しい箇所と言えます。コンテキストメニューの起動を抑制するには、DesignerコントロールのContextMenuOpenイベントに、「キャンセルする」という処理を追加します。このイベント処理では、ContextMenuOpenArgsオブジェクトのMenuTypeが「Section」であったときにCancelプロパティをtrueに設定することでメニューの起動を中止しています。
private void ar3designer_ContextMenuOpen(object sender, _ ContextMenuOpenArgs e) { if(e.MenuType == ContextMenuTypes.Section) { e.Cancel = true; } }
Private Sub Designer1_ContextMenuOpen(ByVal sender As Object, _ ByVal e As ContextMenuOpenArgs) _ Handles Designer1.ContextMenuOpen If e.MenuType = ContextMenuTypes.Section Then e.Cancel = True End If End Sub
ランタイムデザイナのカスタマイズ方法については、ここで紹介したものの他にも、グレープシティ社のFAQ(よくある質問)ページでも技術情報が公開されています。
- 【ランタイムデザイナ】ツールボックスからレポートアイテムを削除したい、レポートアイテムの名前を変更したい
- 【ランタイムデザイナ】プロパティグリッドに表示されるプロパティを制限したい
- 【ランタイムデザイナ】カスタマイズされたレポートアイテムをレポートに追加したい
おわりに
今回はActiveReportsのレポートファイルを編集するランタイムデザイナアプリケーション作成の手順について解説しました。
次回はLinqなどVisual Studio 2008に対応したActiveReportsの新機能について紹介する予定です。