PowerTools SPREAD for Windows Forms 10.0J > 開発者ガイド > 数式 > カスタム関数の作成 |
使用頻度の高い処理が、組み込み関数として存在しない場合、あるいは、複数の組み込み関数を組み合わせて1つの関数にしたい場合、カスタム関数を作成する方法があります。カスタム関数は、組み込み関数と同様に呼び出すことができます。
カスタム関数に、組み込み関数と同じ名前を付けることもできます。その場合、カスタム関数が組み込み関数よりも優先されます。カスタム関数は評価時に動的にリンクされるので、アプリケーションで、既存のカスタム関数を再定義することもできます。
カスタム関数は、FunctionInfoクラスを継承するクラスとして作成します。次のメンバをオーバーライドします。
メンバ | 説明 |
---|---|
Nameプロパティ | 関数の名前 |
MinArgsプロパティ | 関数に指定できる引数の最小値 |
MaxArgsプロパティ | 関数に指定できる引数の最大値 |
AcceptsErrorメソッド | 関数が指定した引数のエラーを許容するかどうか |
Evaluateメソッド | 関数の処理 |
数式がカスタム関数を呼び出したとき、引数の個数が、関数のMinArgsおよびMaxArgsプロパティで指定した範囲を超えていると、関数のEvaluateメソッドはスキップされ、結果には「#VALUE!」エラー値が使用されます。
また、カスタム関数で指定された引数がエラー値(#NUM!、#VALUE!、#REF!など)で、関数のAcceptsErrorメソッドがこの引数に対してFalseを返す(引数のエラーを許容しない)場合、関数のEvaluateメソッドはスキップされ、結果には、このエラー値が使用されます。
カスタム関数のEvaluateメソッドは、数式が評価される場所(コンテキスト)に関する情報は受け取りません。カスタム関数で、この関数が評価される行および列の情報を必要とする場合、このための引数をカスタム関数に追加します。関数を呼び出すときに、引数に、行および列の座標を設定する必要があります。
以下、3つのサンプルコードは、それぞれ、カスタム関数の実装例を表しています。
次のCUBEカスタム関数は、数値を3乗します。つまり、CUBE(x)はPOWER(x,3)と同等です。
C# |
コードのコピー
|
---|---|
public class CubeFunctionInfo : FarPoint.CalcEngine.FunctionInfo { public override string Name { get { return "CUBE"; } } public override int MinArgs { get { return 1; } } public override int MaxArgs { get { return 1; } } public override object Evaluate(object[] args) { double num = FarPoint.CalcEngine.CalcConvert.ToDouble(args[0]); return num * num * num; } } |
Visual Basic |
コードのコピー
|
---|---|
Public Class CubeFunctionInfo Inherits FarPoint.CalcEngine.FunctionInfo Public Overrides ReadOnly Property Name() As String Get Return "CUBE" End Get End Property Public Overrides ReadOnly Property MinArgs() As Integer Get Return 1 End Get End Property Public Overrides ReadOnly Property MaxArgs() As Integer Get Return 1 End Get End Property Public Overrides Function Evaluate(args As Object()) As Object Dim num As Double = FarPoint.CalcEngine.CalcConvert.ToDouble(args(0)) Return num * num * num End Function End Class |
次のXORカスタム関数は、2つのブール値に対し、排他的論理和演算を実行します。C#における"^"演算子や、VBにおけるXOR演算子と似ています。
C# |
コードのコピー
|
---|---|
public class XorFunctionInfo : FarPoint.CalcEngine.FunctionInfo { public override string Name { get { return "XOR"; } } public override int MinArgs { get { return 2; } } public override int MaxArgs { get { return 2; } } public override object Evaluate(object[] args) { bool arg0 = FarPoint.CalcEngine.CalcConvert.ToBool(args[0]); bool arg1 = FarPoint.CalcEngine.CalcConvert.ToBool(args[1]); return (arg0 || arg1) && (arg0 != arg1); } } |
Visual Basic |
コードのコピー
|
---|---|
Public Class XorFunctionInfo Inherits FarPoint.CalcEngine.FunctionInfo Public Overrides ReadOnly Property Name() As String Get Return "XOR" End Get End Property Public Overrides ReadOnly Property MinArgs() As Integer Get Return 2 End Get End Property Public Overrides ReadOnly Property MaxArgs() As Integer Get Return 2 End Get End Property Public Overrides Function Evaluate(args As Object()) As Object Dim arg0 As Boolean = FarPoint.CalcEngine.CalcConvert.ToBool(args(0)) Dim arg1 As Boolean = FarPoint.CalcEngine.CalcConvert.ToBool(args(1)) Return (arg0 OrElse arg1) AndAlso (arg0 <> arg1) End Function End Class |
次のNULLカスタム関数は定数値nullを返します。これは、FALSE()関数が定数値Falseを返すのと似ています。
C# |
コードのコピー
|
---|---|
public class NullFunctionInfo : FunctionInfo { public override string Name { get { return "NULL"; } } public override int MinArgs { get { return 0; } } public override int MaxArgs { get { return 0; } } public override object Evaluate (object[] args) { return null; } } |
Visual Basic |
コードのコピー
|
---|---|
Public Class NullFunctionInfo Inherits FarPoint.CalcEngine.FunctionInfo Public Overrides ReadOnly Property Name() As String Get Return "NULL" End Get End Property Public Overrides ReadOnly Property MinArgs() As Integer Get Return 0 End Get End Property Public Overrides ReadOnly Property MaxArgs() As Integer Get Return 0 End Get End Property Public Overrides Function Evaluate(args As Object()) As Object Return DBNull.Value End Function End Class |
次のコードは、これらのカスタム関数を登録します。
C# |
コードのコピー
|
---|---|
fpSpread1.ActiveSheet.AddCustomFunction(new CubeFunctionInfo()); fpSpread1.ActiveSheet.AddCustomFunction(new XorFunctionInfo()); fpSpread1.ActiveSheet.AddCustomFunction(new NullFunctionInfo()); |
Visual Basic |
コードのコピー
|
---|---|
FpSpread1.ActiveSheet.AddCustomFunction(New CubeFunctionInfo()) FpSpread1.ActiveSheet.AddCustomFunction(New XorFunctionInfo()) FpSpread1.ActiveSheet.AddCustomFunction(New NullFunctionInfo()) |
次のコードは、これらのカスタム関数を使用する数式を、シートに設定します。
C# |
コードのコピー
|
---|---|
fpSpread1.ActiveSheet.SetFormula(0, 0, "CUBE(5)"); fpSpread1.ActiveSheet.SetFormula(1, 0, "XOR(FALSE,FALSE)"); fpSpread1.ActiveSheet.SetFormula(1, 1, "XOR(TRUE,FALSE)"); fpSpread1.ActiveSheet.SetFormula(1, 2, "XOR(FALSE,TRUE)"); fpSpread1.ActiveSheet.SetFormula(1, 3, "XOR(TRUE,TRUE)"); fpSpread1.ActiveSheet.SetFormula(2, 0, "CHOOSE(1,100,NULL(),300)"); fpSpread1.ActiveSheet.SetFormula(2, 1, "CHOOSE(2,100,NULL(),300)"); fpSpread1.ActiveSheet.SetFormula(2, 2, "CHOOSE(3,100,NULL(),300)"); |
Visual Basic |
コードのコピー
|
---|---|
FpSpread1.ActiveSheet.SetFormula(0, 0, "CUBE(5)") FpSpread1.ActiveSheet.SetFormula(1, 0, "XOR(FALSE,FALSE)") FpSpread1.ActiveSheet.SetFormula(1, 1, "XOR(TRUE,FALSE)") FpSpread1.ActiveSheet.SetFormula(1, 2, "XOR(FALSE,TRUE)") FpSpread1.ActiveSheet.SetFormula(1, 3, "XOR(TRUE,TRUE)") FpSpread1.ActiveSheet.SetFormula(2, 0, "CHOOSE(1,100,NULL(),300)") FpSpread1.ActiveSheet.SetFormula(2, 1, "CHOOSE(2,100,NULL(),300)") FpSpread1.ActiveSheet.SetFormula(2, 2, "CHOOSE(3,100,NULL(),300)") |
既定では、引数は値で渡されます。単一の空白セルはnull値(Visual BasicではNothing)として渡されます。空白ではない単一セルは、ボックス化されたプリミティブ(double、boolean、stringなど)として渡されます。セル範囲はCalcArrayクラスのインスタンスとして渡されます。CalcArrayクラスは、2次元配列の行数および列数を決定するRowCountおよびColumnCountプロパティを備えています。また、配列から1つの値を取得するためのGetValueメソッドを備えています。GetValueメソッドで使用する行および列インデックスは、ゼロから始まります。
引数に、セル参照を渡せるようにするには、FunctionInfoクラスのAcceptsReferenceメソッドをオーバーライドする必要があります。AcceptsReferenceメソッドが、対象の引数に対してTrueを返す場合、単一のセルまたはセル範囲が、CalcReferenceクラスのインスタンスとして渡されます。CalcReferenceクラスは、セル参照の先頭行および列を決定するRowおよびColumnプロパティ、行数および列数を決定するRowCountおよびColumnCountプロパティを備えています。また、セル参照から1つの値を取得するためのGetValueメソッドを備えています。GetValueメソッドで使用する行および列インデックスは、RowおよびColumnプロパティの値から始まります。
次のサンプルコードでは、指定したセル範囲から、指定した値未満のセル数をカウントする関数を作成します。関数の引数に、対象のセル範囲を表すセル参照を渡せるように実装されています。
C# |
コードのコピー
|
---|---|
class CountIfLessThanFunctionInfo : FarPoint.CalcEngine.FunctionInfo { public override string Name { get { return "COUNTIFLESSTHAN"; } } public override int MinArgs { get { return 2; } } public override int MaxArgs { get { return 2; } } public override bool AcceptsReference(int i) { return i == 0; } public override object Evaluate(object[] args) { FarPoint.CalcEngine.CalcReference range = args[0] as FarPoint.CalcEngine.CalcReference; double criteria = FarPoint.CalcEngine.CalcConvert.ToDouble(args[1]); double count = 0.0; if (range == null) return FarPoint.CalcEngine.CalcError.Value; for (int i = range.Row; i < range.Row + range.RowCount; i++) { for (int j = range.Column; j < range.Column + range.ColumnCount; j++) { double cellValue = FarPoint.CalcEngine.CalcConvert.ToDouble(range.GetValue(i, j)); if (cellValue < criteria) count++; } } return count; } } //以下をフォームのコードビハインドに記述します fpSpread1.ActiveSheet.AddCustomFunction(new CountIfLessThanFunctionInfo()); fpSpread1.ActiveSheet.SetClipValue(0, 0, 2, 3, "0\t0\t1\n1\t1\t1"); fpSpread1.ActiveSheet.SetFormula(0, 4, "COUNTIFLESSTHAN(A1:C2, 1)"); |
Visual Basic |
コードのコピー
|
---|---|
Class CountIfLessThanFunctionInfo Inherits FarPoint.CalcEngine.FunctionInfo Public Overrides ReadOnly Property Name() As String Get Return "COUNTIFLESSTHAN" End Get End Property Public Overrides ReadOnly Property MinArgs() As Integer Get Return 2 End Get End Property Public Overrides ReadOnly Property MaxArgs() As Integer Get Return 2 End Get End Property Public Overrides Function AcceptsReference(i As Integer) As Boolean Return i = 0 End Function Public Overrides Function Evaluate(args As Object()) As Object Dim range As FarPoint.CalcEngine.CalcReference = TryCast(args(0), FarPoint.CalcEngine.CalcReference) Dim criteria As Double = FarPoint.CalcEngine.CalcConvert.ToDouble(args(1)) Dim count As Double = 0.0 If range Is Nothing Then Return FarPoint.CalcEngine.CalcError.Value End If For i As Integer = range.Row To range.Row + (range.RowCount - 1) For j As Integer = range.Column To range.Column + (range.ColumnCount - 1) Dim cellValue As Double = FarPoint.CalcEngine.CalcConvert.ToDouble(range.GetValue(i, j)) If cellValue < criteria Then count += 1 End If Next Next Return count End Function End Class '以下をフォームのコードビハインドに記述します FpSpread1.ActiveSheet.AddCustomFunction(New CountIfLessThanFunctionInfo()) FpSpread1.ActiveSheet.SetClipValue(0, 0, 2, 3, "0" & vbTab & "0" & vbTab & "1" & vbLf & "1" & vbTab & "1" & vbTab & "1") FpSpread1.ActiveSheet.SetFormula(0, 4, "COUNTIFLESSTHAN(A1:C2, 1)") |