はじめに
1つのプログラム内に2種類のスプレッドシートを配置して、データをドラッグ&ドロップでコピーするような使い方ができると、ぐっとスプレッドシートの用途の幅も広がるのではないでしょうか。そこで、SPREAD for.NET 2.5J Windows Forms EditionのfpSpreadコンポーネントで、ドラッグ&ドロップによるデータの移動が可能なアプリケーションを作成してみました。
このアプリケーションでは、フォームの中に上下にfpSpreadコンポーネントを配置します。上のfpSpreadコンポーネントに健康診断の血圧測定の数値を入力すると、fpSpreadコンポーネントのセルの条件付き書式設定機能を利用して、リミットを越えているかどうかをすぐに色によって判定します。
リミットを越えた人のデータは、fpSpreadコンポーネントのデータのドラッグ&ドロップ機能を利用して、下のスプレッドシートにコピーすることができます。
対象読者
Visual Basic 2005またはVisual C#2005を使ってプログラムを作ったことのある人。
必要な環境
Visual Basic 2005またはVisual C#2005、Visual Studio 2005でプログラムが作れる環境。
プログラム実行時の注意事項
本稿の実行ファイル(バイナリファイル)を動かすには、zipファイルに同梱してある以下のファイルが必要になります。
- FarPoint.Win.SpreadJ.dll(本体アセンブリ)
- FarPoint.Win.dll(共通アセンブリ)
- Farpoint.CalcEngine.dll(表計算エンジンDLL)
これらのファイルを、実行プログラムと同じフォルダに格納します。また、.NET Framework 2.0から追加されたクラスやメンバを使用しているので、.NET Framework 2.0がインストールされていることが必須条件です。
コンポーネントのインストール
はじめてSPREAD for.NET 2.5J Windows Forms Editionを使用する方は、プロジェクトにSPREAD for.NET 2.5J Windows Forms Editionをインストールする必要があります。インストーラは、グレープシティのWebページからダウンロードできますので、ここからダウンロードしてインストールしてください。
製品ページ左側の[ダウンロード]-[トライアル版]をクリックし、ダウンロード方法([FTP]または[HTTP])を選択すればインストールできます。ファイルはLZH形式で圧縮されています。
有償のコンポーネントですが、プロダクトキーを入力せずにインストールすることで、トライアル版として使用できます。制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。
コントロールの追加
SPREAD for.NET 2.5J Windows Forms Editionをインストールしたら、ツールボックスに専用のタブを作成し、SPREAD for.NET 2.5J Windows Forms Editionのコンポーネントを追加します。追加するコンポーネントは、「.NET Frameworkコンポーネント」の「名前空間」が「FarPoint.Win.Spread」で始まる名前空間のコンポーネント「FpSpread」です。
GUIの作成
GUIは簡単な設定です。fpSpreadコンポーネントを上下に2つ配置し、Labelコントロールで見出しをつけます。上のfpSpreadコンポーネントには、SPREADデザイナで列見出しとデータの入力をしておきます。
セルの条件付き書式機能を設定する
セルの条件付き書式機能は、数値データに対して有効な機能で、セルに入力される値によって、セルの背景色や枠線、文字のサイズ・色などセルの書式を自動的に変えることができる機能です。
SetConditionalFormatメソッドで数値を判定する
この機能をコードから設定する場合は、SetConditionalFormatメソッドを使用します。メソッドの書式は次のようになっています。
Function SetConditionalFormat( _ ByVal row As Integer, _ ByVal column As Integer, _ ByVal style As NamedStyle, _ ByVal op As ComparisonOperator, _ ByVal condition As Expression _ ) As Boolean
引数row
、column
には、書式を設定したいセル番地を行列番号で指定します。style
には、設定するセルの書式をNamedStyleオブジェクトとして指定します。op
にはセルデータと次のcondition
を比較するための演算子を「ComparisonOperator列挙型」のメンバで指定します。例えば、セル「1、2」の値が「1」から「59」までの間であれば、「styleCold」という名前付き書式を設定する場合は、次のように記述します。
SetConditionalFormat(1, 2, styleCold, _ FarPoint.Win.Spread.ComparisonOperator.Between, "1", "59")
SetConditionalFormat(1, 2, styleCold, FarPoint.Win.Spread.ComparisonOperator.Between, "1", "59");
比較条件に使う数値は、""で括って文字列として設定します。
この「ComparisonOperator列挙型」の演算子を使うことで、いろいろな条件で数値データを違う書式でセルに表示させることができます。
NamedStyleオブジェクトで書式を設定する
実際にセルの書式を設定するのは、NamedStyleオブジェクトをコンストラクタで作成して行います。
NamedStyleクラスには、書式に関するメンバプロパティが用意されており、このプロパティで書式を設定し、作成したNamedStyleオブジェクトへの参照を、SetConditionalFormat
メソッドの引数に指定します。
例えば、セルの背景を青色に変える書式を作成するには、次のようにNamedStyleオブジェクトをコンストラクタで作成し、BackColorプロパティを変更します。
Dim styleCold As New FarPoint.Win.Spread.NamedStyle() styleCold.BackColor = Color.Blue
FarPoint.Win.Spread.NamedStyle styleCold
= new FarPoint.Win.Spread.NamedStyle();
styleCold.BackColor = Color.Blue;
このプログラムでは、1つのセルに3つの書式を設定します。これは、低いほうの血圧が「1-59」「60-90」「91以上」、高いほうの血圧が「1-109」「110-130」「131以上」の3パターンに区分けし、それぞれ通常値であればセルの背景色がシアンに、血圧が低ければセルの背景色を青色に、高ければ赤色に変更するようにします。
ドラッグ&ドロップの準備
そして、2つのfpSpreadコンポーネントがドラッグ&ドロップでデータを操作できるように、上のfpSpreadコンポーネントでは「AllowDragDrop」プロパティを、下のfpSpreadコンポーネントでは「AllowDrop」プロパティをTrueに設定します。
FpSpread1.AllowDragDrop = True FpSpread2.AllowDrop = True
fpSpread1.AllowDragDrop = true; fpSpread2.AllowDrop = true;
そして、ここまでのコードを、フォームのLoadイベントハンドラに作成します。
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim styleCold As New FarPoint.Win.Spread.NamedStyle() Dim styleCool As New FarPoint.Win.Spread.NamedStyle() Dim styleHot As New FarPoint.Win.Spread.NamedStyle() styleCold.BackColor = Color.Blue styleCold.ForeColor = Color.White styleCool.BackColor = Color.Cyan styleHot.BackColor = Color.Red Dim i As Integer For i = 1 To FpSpread1.ActiveSheet.RowCount - 1 FpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleCold, _ FarPoint.Win.Spread.ComparisonOperator.Between, "1", "59") FpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleCool, _ FarPoint.Win.Spread.ComparisonOperator.Between, "60", "90") FpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleHot, _ FarPoint.Win.Spread.ComparisonOperator.GreaterThan, "91") Next For i = 1 To FpSpread1.ActiveSheet.RowCount - 1 FpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleCold, _ FarPoint.Win.Spread.ComparisonOperator.Between, "1", "109") FpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleCool, _ FarPoint.Win.Spread.ComparisonOperator.Between, "110", "130") FpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleHot, _ FarPoint.Win.Spread.ComparisonOperator.GreaterThan, "131") Next FpSpread1.AllowDragDrop = True FpSpread2.AllowDrop = True End Sub
private void Form1_Load(object sender, EventArgs e) { FarPoint.Win.Spread.NamedStyle styleCold = new FarPoint.Win.Spread.NamedStyle(); FarPoint.Win.Spread.NamedStyle styleCool = new FarPoint.Win.Spread.NamedStyle(); FarPoint.Win.Spread.NamedStyle styleHot = new FarPoint.Win.Spread.NamedStyle(); styleCold.BackColor = Color.Blue; styleCold.ForeColor = Color.White; styleCool.BackColor = Color.Cyan; styleHot.BackColor = Color.Red; int i; for(i=1; i<=fpSpread1.ActiveSheet.RowCount-1;i++){ fpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleCold, FarPoint.Win.Spread.ComparisonOperator.Between, "1", "59"); fpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleCool, FarPoint.Win.Spread.ComparisonOperator.Between, "60", "90"); fpSpread1.ActiveSheet.SetConditionalFormat(i, 2, styleHot, FarPoint.Win.Spread.ComparisonOperator.GreaterThan, "91"); } for(i=1;i<=fpSpread1.ActiveSheet.RowCount-1;i++){ fpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleCold, FarPoint.Win.Spread.ComparisonOperator.Between, "1", "109"); fpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleCool, FarPoint.Win.Spread.ComparisonOperator.Between, "110", "130"); fpSpread1.ActiveSheet.SetConditionalFormat(i, 3, styleHot, FarPoint.Win.Spread.ComparisonOperator.GreaterThan, "131"); } fpSpread1.AllowDragDrop = true; fpSpread2.AllowDrop = true; }
メンバ | 説明 |
IsTrue | 数式がTrueかどうかを判定します。 |
IsFalse | 数式がFalseかどうかを判定します。 |
Between | セル値が2つのパラメータ値の間にあるかどうかを判定します。 |
NotBetween | セル値が2つのパラメータ値の間にないかどうかを判定します。 |
EqualTo | セル値がパラメータ値と等しいかどうかを判定します。 |
NotEqualTo | セル値がパラメータ値と等しくないかどうかを判定します。 |
GreaterThan | セル値がパラメータ値より大きいかどうかを判定します。 |
LessThan | セル値がパラメータ値より小さいかどうかを判定します。 |
GreaterThanOrEqualTo | セル値がパラメータ値以上かどうかを判定します。 |
LessThanOrEqualTo | セル値がパラメータ値以下かどうかを判定します。 |
データのドラッグ処理 1
次に、データのドラッグ&ドロップの処理を組み立てます。
上のfpSpreadコンポーネントはドラッグ元の、下のfpSpreadコンポーネントはドロップを受け取る処理を組み立てることになります。
ドラッグ&ドロップ処理の作成
fpSpreadコンポーネントでドラッグ&ドロップ機能を利用するには、次のような処理を組み立てる必要があります。
1.同一fpSpreadコンポーネント内のやりとり
同一fpSpreadコンポーネント内でのデータのドラッグ&ドロップを実行するには、「MouseDown」イベントハンドラでドラッグ&ドロップ操作の効果を設定し、「MouseUp」イベントハンドラで選択されているセル範囲からデータを取得します。
2.2つのfpSpreadコンポーネントでのやりとり
2つのfpSpreadコンポーネント間でデータのドラッグ&ドロップ処理を作成するには、ドラッグ側のfpSpreadコンポーネントで1番と同じ処理を作成し、ドロップ側のfpSpreadコンポーネントでドロップするセル範囲を取得します。そこに取得したデータを転送し、その選択範囲をSheetオブジェクトに追加します。
ドラッグ元の処理-MouseDownイベント
まずは、データをドラッグ&ドロップする上のfpSpreadコンポーネントの処理を作成します。使用するイベントは2つで、「MouseDown」イベントでドラッグ&ドロップでデータをコピーするのか、移動するのかというドラッグ&ドロップ操作の効果を設定します。そして、「MouseUp」イベントで選択されたセル範囲からセルデータを取得します。
このプログラムでは、選択したセル範囲をマウスの左ボタンでドラッグしたときは同じシート内でのドラッグで、右ボタンでドラッグしたときはさらにfpSpreadコンポーネント間の移動を行えるようにします。
そこで、MouseDownイベントハンドラでは押されたボタンが右ボタンのときに、コピーまたは移動が行えるように、fpSpreadクラスのDoDragDrop
メソッドでドラッグ&ドロップ操作の効果を設定します。このメソッドは.NET FrameworkのSystem.Windows.Formsから継承されているメソッドで、引数にDragDropEffects列挙体のメンバを指定します。
Private Sub FpSpread1_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles FpSpread1.MouseDown If e.Button = Windows.Forms.MouseButtons.Right Then Try FpSpread1.DoDragDrop(msg, _ DragDropEffects.Copy Or DragDropEffects.Move) Catch Exception As Exception End Try End If End Sub
private void fpSpread1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { try { fpSpread1.DoDragDrop(msg, DragDropEffects.Copy | DragDropEffects.Move); } catch (Exception) { } } }
メンバ名 | 説明 |
All | データがコピーされ、ドラッグソースから削除され、ドロップターゲットでスクロールされます。 |
Copy | データはドロップターゲットにコピーされます。 |
Link | ドラッグソースのデータはドロップターゲットにリンクされます。 |
Move | ドラッグソースのデータはドロップターゲットに移動されます。 |
None | ドロップターゲットはデータを受け付けません。 |
Scroll | ドロップターゲットでスクロールが開始されようとしているか、または現在スクロールが行われています。 |
ドラッグ元の処理-MouseUpイベント
MouseUpイベントハンドラでは、選択されているセル範囲を取得し、その中のデータを取り出します。
選択されているセル範囲の取得は、GetSelection
メソッドを使用します。メソッドを実行すると、セル範囲をCellRangeオブジェクトで返してきますので、これを変数に格納しておきます。
そして、GetClip
メソッドでセル範囲内のデータを取り出します。メソッドの書式は次のとおりです。
Function GetClip( _ ByVal row As Integer, _ ByVal column As Integer, _ ByVal rowCount As Integer, _ ByVal columnCount As Integer _ ) As String
row
、column
にはセル範囲の左上の行列番号を、rowcount
、columncount
にはそれぞれセル範囲の行列数を指定します。
メソッドを実行すると、セル範囲内の書式付データをString型で返してきますので、これを変数に格納しておきます。
Private Sub FpSpread1_MouseUp(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles FpSpread1.MouseUp Try SelectRange = FpSpread1.ActiveSheet.GetSelection(0) msg = FpSpread1.ActiveSheet.GetClip(SelectRange.Row, _ SelectRange.Column, _ SelectRange.RowCount, _ SelectRange.ColumnCount) Catch Exception As Exception MessageBox.Show("選択されたセルがありません。") Exit Sub End Try End Sub
private void fpSpread1_MouseUp(object sender, MouseEventArgs e) { try { selectrange = fpSpread1.ActiveSheet.GetSelection(0); msg = fpSpread1.ActiveSheet.GetClip(selectrange.Row, selectrange.Column, selectrange.RowCount, selectrange.ColumnCount); } catch (Exception) { MessageBox.Show("選択されたセルがありません。"); return; } }
データのドラッグ処理 2
ドロップ側の処理-DragEnterイベント
今度は、ドロップ側の処理を作成します。まずは、下側のfpSpreadコンポーネントに、ドラッグ&ドロップ操作の効果を設定します。ドロップでデータを受け取る側ですから、DragEnterイベントハンドラで処理をします。
GetDataPresent
メソッドで、ドロップするデータがあるかどうかを判断し、データがあればイベントハンドラの引数eのEffectプロパティに「DragDropEffects.Move」を設定します。
Private Sub FpSpread2_(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles FpSpread2.DragEnter If e.Data.GetDataPresent(DataFormats.Text) Then e.Effect = DragDropEffects.Move End If End Sub
private void fpSpread2_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.Text)) { e.Effect = DragDropEffects.Move; } }
ドロップ側の処理-DragDropイベント
次に、DragDropイベントハンドラでは、ドロップしたときの処理を実行します。
まず、ドロップ先のセル範囲を、GetSelection
メソッドで取得します。というのも、ドラッグ&ドロップされてきたときは、ドラッグしてきたセル範囲がドロップ側のfpSpreadコンポーネントにも反映されるようになっています。そして、SetClip
メソッドを使ってそのセル範囲に、変数msgに格納していたデータを設定します。
また、ドラッグ元のfpSpreadコンポーネントのセル範囲を、RemoveSelection
メソッドで解除します。
Private Sub FpSpread2_DragDrop(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles FpSpread2.DragDrop Dim sel As FarPoint.Win.Spread.Model.CellRange sel = FpSpread2.ActiveSheet.GetSelection(0) FpSpread2.ActiveSheet.SetClip(sel.Row, _ sel.Column, sel.RowCount, sel.ColumnCount, msg) FpSpread1.ActiveSheet.RemoveSelection(SelectRange.Row, _ SelectRange.Column, _ SelectRange.RowCount, _ SelectRange.ColumnCount) End Sub
private void fpSpread2_DragDrop(object sender, DragEventArgs e) { FarPoint.Win.Spread.Model.CellRange sel = fpSpread2.ActiveSheet.GetSelection(0); if (sel != null) fpSpread2.ActiveSheet.SetClip(sel.Row, sel.Column, sel.RowCount, sel.ColumnCount, msg); fpSpread1.ActiveSheet.RemoveSelection(selectrange.Row, selectrange.Column, selectrange.RowCount, selectrange.ColumnCount); }
ドロップ側の処理-DragOverイベント
このアプリケーションでは、ドロップ先のスプレッドシートにデータを設定する処理を、このDragOverイベントハンドラで行います。
1.選択範囲の取得
まず、ドロップする場所のマウスポインタの位置を把握します。これは、PointToClient
メソッドを使用します。
そして、その位置からセルの位置と選択範囲を取得します。これは、GetCellFromPixel
メソッドを使用します。これで、ドロップ先のセル範囲をCellRangeオブジェクトとして取得できました。
p = FpSpread2.PointToClient(New Point(e.X, e.Y))
range = FpSpread2.GetCellFromPixel(0, 0, p.X, p.Y)
Point p = fpSpread2.PointToClient(new Point(e.X, e.Y));
FarPoint.Win.Spread.Model.CellRange range
= fpSpread2.GetCellFromPixel(0, 0, p.X, p.Y);
2.ドロップ
次に、ドロップ側のfpSpreadコンポーネントに、現在選択されているセルがある場合は、一度これをRemoveSelection
メソッドで解除します。そして、ActiveSheet
メソッドを使用し、ドロップするセル範囲を選択範囲として追加します。これで、ドロップ処理が完成します。
この処理のコード全文は次のようになります。
Private Sub FpSpread2_DragOver(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles FpSpread2.DragOver Dim rowcnt, colcnt As Integer Dim p As Point Dim range As FarPoint.Win.Spread.Model.CellRange Dim sel As FarPoint.Win.Spread.Model.CellRange rowcnt = SelectRange.RowCount colcnt = SelectRange.ColumnCount ' クライアント座標を算出します。 p = FpSpread2.PointToClient(New Point(e.X, e.Y)) ' 指定したポイントから CellRange オブジェクトを取得します。 range = FpSpread2.GetCellFromPixel(0, 0, p.X, p.Y) ' 行数及び列数のあるときは If range.ColumnCount <> -1 And range.RowCount <> -1 Then ' 現在選択しているセル範囲のあるときは sel = FpSpread2.ActiveSheet.GetSelection(0) If Not (sel Is Nothing) Then ' 現在のセル範囲の選択状態を解除します。 FpSpread2.ActiveSheet.RemoveSelection(sel.Row, _ sel.Column, sel.RowCount, sel.ColumnCount) End If ' 指定したセル範囲を選択範囲に追加します。 FpSpread2.ActiveSheet.AddSelection(range.Row, _ range.Column, rowcnt, colcnt) End If End Sub
private void fpSpread2_DragOver(object sender, DragEventArgs e) { int rowcnt = selectrange.RowCount; int colcnt = selectrange.ColumnCount; // クライアント座標を算出します。 Point p = fpSpread2.PointToClient(new Point(e.X, e.Y)); // 指定したポイントからCellRange オブジェクトを取得します。 FarPoint.Win.Spread.Model.CellRange range = fpSpread2.GetCellFromPixel(0, 0, p.X, p.Y); // 行数及び列数の無いときは関数を抜けます。 if (range.ColumnCount == -1 && range.RowCount == -1) return; // 現在選択しているセル範囲を取得します。 FarPoint.Win.Spread.Model.CellRange sel = fpSpread2.ActiveSheet.GetSelection(0); if (sel != null) // 現在のセル範囲の選択状態を解除します。 fpSpread2.ActiveSheet.RemoveSelection(sel.Row, sel.Column, sel.RowCount, sel.ColumnCount); // 指定したセル範囲を選択範囲に追加します。 fpSpread2.ActiveSheet.AddSelection(range.Row, range.Column, rowcnt, colcnt); }
まとめ
1つのアプリケーション内に2つのスプレッドシートコンポーネントを組み込んで、ドラッグ&ドロップでデータを処理するプログラムを作成してみました。こうすると、fpSpreadコンポーネントを表計算コンポーネントとして使用するのではなく、Gridコントロールのような使い方でデータの処理に利用できます。
紹介したように、ドラッグ&ドロップ機能もサポートしており、特定の業務処理に特化したアプリケーションを作成するときなどに威力を発揮するのではないでしょうか。