前のセクションのすべての例で使用した C1OlapPage コントロールは、すべての必要な UI を含み、コードをほとんどまたはまったく必要としません。このセクションで作成する OLAP アプリケーションでは、C1OlapPage を使用しません。代わりに、C1OlapGrid、C1OlapChart、およびいくつかの標準 .NET コントロールを使用して、完全なカスタム UI を作成します。
このアプリケーションの完全なソースコードは、C1Olap でインストールされる "CustomUI" のサンプルに含まれています。
次の図は、アプリケーションをデザインビュー内に示しています。
パネルがフォームの上端にドッキングされており、アプリケーションのタイトルを示しています。垂直方向のツールストリップコントロールがフォームの右側にドッキングされており、3つのボタンのグループを備えています。上端のグループでは、定義済みの3つのビュー、営業担当者別、製品別、国別の売上高から1つを選択できます。次のグループでは、データに対して製品価格に基づいてフィルタ(高価、中程度、安価)を適用できます。最後のボタンは、レポート作成機能を備えています。
フォームの残りの領域のうち、左側には C1OlapGrid、右側には C1OlapChart を示す分割コンテナが存在します。これらは、現在選択されているビューを表示するコントロールです。
フォームは、レポートの生成に使用する C1OlapPrintDocument コンポーネントも含みます。このコンポーネントは、フォームの下のトレイ領域だけに表示され、上の図には表示されません。C1OlapPrintDocument は、設計時に設定されたその OlapGrid プロパティと OlapChart プロパティにより、ページ上の OLAP コントロールに接続されます。
さらに、フォームには C1OlapPanel コントロールがあります。これは、Visible プロパティが false に設定されているため、ユーザーはコントロールを見ることができません。この不可視のコントロールは、グリッドとチャートのデータソースとして使用され、また、データのフィルタ処理と要約を処理します。グリッドとグラフの両方で、その DataSource プロパティが C1OlapPanel に設定されています。
すべてのコントロールが揃ったら、それらをすべて結合するコードを追加して、アプリケーションを動作させます。
最初に、データを取得し、C1OlapPanel に割り当てます。
コード |
コードのコピー
|
---|---|
private void Form1_Load(object sender, EventArgs e) { // データを読み込みます var da = new OleDbDataAdapter("select * from Invoices", GetConnectionString()); var dt = new DataTable(); da.Fill(dt); // アプリケーションを動作させる C1OlapPanel にデータを割り当てます this.c1OlapPanel1.DataSource = dt; // どの製品も SalesPerson ビューで開始します _btnSalesperson.PerformClick(); _btnAllPrices.PerformClick(); } |
コードは、DataAdapter を使用して NorthWind データベースからデータを取得し、結果の DataTable を C1OlapPanel.DataSource プロパティに割り当てます。次にコードは、PerformClick メソッドを使用して、2つのボタンのクリックをシミュレーションし、現在のビューとフィルタを初期化します。
現在のビューを選択するボタンのイベントハンドラは、次のようになります。
コード |
コードのコピー
|
---|---|
void _btnSalesperson_Click(object sender, EventArgs e) { CheckButton(sender); BuildView("Salesperson"); } void _btnProduct_Click(object sender, EventArgs e) { CheckButton(sender); BuildView("ProductName"); } void _btnCountry_Click(object sender, EventArgs e) { CheckButton(sender); BuildView("Country"); } |
すべてのハンドラは、下記に示す BuildView ヘルパーメソッドを使用します。
コード |
コードのコピー
|
---|---|
// ボタンがクリックされた後にビューをリビルドします void BuildView(string fieldName) { // olap エンジンを取得します var olap = c1OlapPanel1.OlapEngine; // 完了するまで更新を停止します olap.BeginUpdate(); // 注文日付の書式を設定して、年別にグループ化します var f = olap.Fields["OrderDate"]; f.Format = "yyyy"; // すべてのフィールドをクリアします olap.RowFields.Clear(); olap.ColumnFields.Clear(); olap.ValueFields.Clear(); // ビューを構築します olap.ColumnFields.Add("OrderDate"); olap.RowFields.Add(fieldName); olap.ValueFields.Add("ExtendedPrice"); // 更新を復元します olap.EndUpdate(); } |
BuildView メソッドは、C1OlapPanel によって提供される C1OlapEngine オブジェクトへの参照を取得し、直ちに BeginUpdate メソッドを呼び出して、新しいビューが完全に定義されるまで更新を停止します。これは、パフォーマンスの向上のために実行されます。
次に、コードで[OrderDate]フィールドの書式を "yyyy" に設定して売上高を年ごとにグループ化し、エンジンの RowFields、ColumnFields、および ValueFields コレクションをクリアし、さらに表示するフィールドを追加することによってビューを再構築します。呼び出し元によって渡される "fieldName" パラメータには、この例のビューの間で変化するフィールドの名前のみが含まれます。
これがすべて完了すると、コードが EndUpdate を呼び出して、C1OlapPanel が出力テーブルを更新します。
アプリケーションを実行する前に、フィルタ処理を実装するコードを見ておきましょう。イベントハンドラは次のようになります。
コード |
コードのコピー
|
---|---|
void _btnExpensive_Click(object sender, EventArgs e) { CheckButton(sender); SetPriceFilter("Expensive Products (price > $50)", 50, double.MaxValue); } void _btnModerate_Click(object sender, EventArgs e) { CheckButton(sender); SetPriceFilter("Moderately Priced Products ($20 < price < $50)", 20, 50); } void _btnInexpensive_Click(object sender, EventArgs e) { CheckButton(sender); SetPriceFilter("Inexpensive Products (price < $20)", 0, 20); } void _btnAllProducts_Click(object sender, EventArgs e) { CheckButton(sender); SetPriceFilter("All Products", 0, double.MaxValue); } |
すべてのハンドラは、下記に示す SetPriceFilter ヘルパーメソッドを使用します。
コード |
コードのコピー
|
---|---|
// フィルタを製品価格に適用します void SetPriceFilter(string footerText, double min, double max) { // olap エンジンを取得します var olap = c1OlapPanel1.OlapEngine; // 完了するまで更新を停止します olap.BeginUpdate(); // ビュー内の単価フィールドがアクティブであることを確認します var field = olap.Fields["UnitPrice"]; olap.FilterFields.Add(field); // 条件が適用されるフィルタをカスタマイズします var filter = field.Filter; filter.Clear(); filter.Condition1.Operator = C1.Olap.ConditionOperator.GreaterThanOrEqualTo; filter.Condition1.Parameter = min; filter.Condition2.Operator = C1.Olap.ConditionOperator.LessThanOrEqualTo; filter.Condition2.Parameter = max; // 更新を復元します olap.EndUpdate(); // レポートのフッターを設定します c1OlapPrintDocument1.FooterText = footerText; } |
前のように、コードが C1OlapEngine に対する参照を取得して、直ちに BeginUpdate を呼び出します。
次に、データのフィルタ処理に使用される[UnitPrice]フィールドに対する参照を取得します。[UnitPrice]フィールドがエンジンの FilterFields コレクションに追加され、フィルタが現在のビューに適用されます。
この細部の処理は重要です。フィールドがどのビューコレクション(RowFields、ValueFields、FilterFields)にも含まれない場合、そのフィールドがビューに含まれることはなくなり、また、その Filter プロパティによる一切の影響を受けなくなります。
コードは、ビューに含まれる必要のある値の範囲を指定する2つの条件を設定することにより、[UnitPrice]フィールドの Filter プロパティの設定に進みます。範囲は、"min" パラメータと "max" パラメータによって定義されます。条件を使用する代わりに、包める値のリストを提供することもできます。通常、数値を扱う場合には条件の方が便利であり、文字列値や列挙ではリストの方が便利です。
最後にコードは、EndUpdate を呼び出し、C1OlapPrintDocument の FooterText プロパティを設定します。これにより、フッターが任意のレポートで自動的に表示されるようになります。
上記のメソッドは、以下に示す CheckButton と呼ぶ別のヘルパーを使用します。
コード |
コードのコピー
|
---|---|
// どのボタンが押されたかを示します void CheckButton(object pressedButton) { var btn = pressedButton as ToolStripButton; btn.Checked = true; var items = btn.Owner.Items; var index = items.IndexOf(btn); for (int i = index + 1; i < items.Count; i++) { if (!(items[i] is ToolStripButton)) break; ((ToolStripButton)items[i]).Checked = false; } for (int i = index - 1; i > 0 && !(items[i] is ToolStripSeparator); i--) { if (!(items[i] is ToolStripButton)) break; ((ToolStripButton)items[i]).Checked = false; } } |
このメソッドにより、ツールストリップのボタンがラジオボタンのように動作します。ボタンの1つをオンにすると、同じグループの他のすべてのボタンがオフになります。
これで、アプリケーションを使用する準備がほぼ整いました。ここで次のように実行して、アプリケーションのさまざまなビューやフィルタ処理機能をテストできます。
このビューでは、すべての製品の売上高が年別および国別にグループ化して表示されます。300,000 ドル弱の値がチャートにどのように表示されているか注目してください。
[$$$ 高額]ボタンをクリックすると、フィルタが適用されて、直ちにビューが変化します。今度は、80,000 ドル弱の値がチャートにどのように表示されているか注目してください。高額の値が売上高の3分の1を占めています。
アプリケーションを構成するコードのうち最後に残っているのは、レポート作成です。ユーザーは、あらかじめ OlapGrid からデータをコピーしておき、それを Excel に貼り付け、結果を印刷または保存することができます。これをもっと簡単に行うために、アプリケーション内から直接 PDF ファイルを印刷または作成できるようにします。
これを行うには、クリックを処理するためのコードを[レポート]ボタンに追加します。このコードは非常にシンプルです。
void _btnReport_Click(object sender, EventArgs e)
{
using (var dlg = new C1.Win.Olap.C1OlapPrintPreviewDialog())
{
dlg.Document = c1OlapPrintDocument1;
dlg.StartPosition = FormStartPosition.Manual;
dlg.Bounds = this.Bounds;
dlg.ShowDialog(this);
}
}
.NET で印刷を実行したことがある場合、これは見慣れたコードです。これは、最初に C1OlapPrintPreviewDialog のインスタンス化を行います。標準の PrintPreviewDialog に似たクラスですが、PDF へのエクスポート機能などの拡張機能をいくつか備えています。
コードでは、ダイアログボックスの Document プロパティを設定し、その位置を初期化し、ダイアログボックスを表示します。アプリケーションを実行し、[レポート]ボタンをクリックすると、次のようなダイアログボックスが表示されます。
このダイアログボックスから、ユーザーは、ページレイアウトを変更したり、ドキュメントを PDF に印刷またはエクスポートしたりできます。