MESCIUS SPREAD for Windows Forms 17.0J > 開発者ガイド > 数式 > カスタム関数の作成 |
使用頻度の高い処理が、組み込み関数として存在しない場合、あるいは、複数の組み込み関数を組み合わせて1つの関数にしたい場合、カスタム関数を作成する方法があります。カスタム関数は、組み込み関数と同様に呼び出すことができます。
カスタム関数に、組み込み関数と同じ名前を付けることもできます。その場合、カスタム関数が組み込み関数よりも優先されます。カスタム関数は評価時に動的にリンクされます。カスタム関数が同じ名前を使用し、また数式が解析される前に追加される場合、アプリケーションは既存の組み込み関数を再定義できます。
数式が関数のMinArgsプロパティとMaxArgsプロパティで指定された範囲外のパラメータ数のカスタム関数を呼び出そうとすると、その関数のEvaluateメソッドはスキップされ、#VALUE!エラー値が結果として使用されます。
また、数式がエラー値(#NUM!、#VALUE!、#REF!など)のパラメータを使用したカスタム関数を呼び出して、IReadonlyPrimitiveValueインターフェースのGetErrorメソッドがそのパラメータに対してFalseを返した場合、FunctionクラスのEvaluateメソッドはスキップされ、エラー値が結果として使用されます。
Evaluateメソッドは指定された引数を基にカスタム関数を評価し、評価された値を結果に割り当てます。
最初はカスタム関数を作成します。この例では、税を評価し、スプレッドシート内の指定されたセルに数値を返すTaxValue関数を作成します。
次のコードはTaxValueカスタム関数を定義します。
C# |
コードのコピー
|
---|---|
using GrapeCity.CalcEngine; public class TaxValueFunction : GrapeCity.CalcEngine.Function { public TaxValueFunction() : base("TAXVALUE", 1, 2, FunctionAttributes.SingleCell | FunctionAttributes.Number) { } protected override void Evaluate(IArguments arguments, IValue result) { IEvaluationContext context = arguments.EvaluationContext; double num = arguments[0].GetNumber(context); double taxrate = arguments.Count > 1 ? arguments[1].GetNumber() : 0.15; result.SetValue(null, num - (num * taxrate)); } } |
次のコードはカスタム関数を登録します。
C# |
コードのコピー
|
---|---|
fpSpread1.AddCustomFunction(new TaxValueFunction());
|
次のコードは数式内でカスタム関数を実装します。
C# |
コードのコピー
|
---|---|
fpSpread1.ActiveSheet.Cells[1,1].Formula = "TAXVALUE(A1)";
|
以下の2つの方法でカスタム関数で引数を指定できます。
デフォルトでは、パラメータは値により渡されます(単一のセルを使用している場合)。単一の空白セルはnull値(Visual BasicではNothing)として渡されます。空白ではない単一セルは、ボックス化されたプリミティブ(double、boolean、stringなど)として渡されます。
セル範囲を使用している場合、パラメータは参照により渡されます。
カスタム関数をパラメータ付きで動作させるには、派生クラス内から Functionクラスのメソッドとプロパティを使用します。
IReferenceSourceインターフェースのGetValueメソッドおよびIPrimitiveValueインターフェースのSetValueメソッドを使用して、参照先のセルに対して、値を取得または設定できます。GetValueメソッドおよびSetValueメソッドの行および列のインデックスは、参照範囲の行・列から開始します。
次のサンプルコードでは、指定したセル範囲から、指定した値未満のセル数をカウントする関数を作成します。
C# |
コードのコピー
|
---|---|
class CountIfLessThanFunction : GrapeCity.CalcEngine.Function { public CountIfLessThanFunction() : base("COUNTIFLESSTHAN", 2, 2, GrapeCity.CalcEngine.FunctionAttributes.Number) { } protected override void Evaluate(IArguments arguments, IValue result) { IValue range = arguments[0]; if (range.ValueType != GrapeCity.CalcEngine.ValueType.Reference && range.ValueType != GrapeCity.CalcEngine.ValueType.AdjustableReference) { arguments.EvaluationContext.Error = CalcError.Value; result.SetValue(CalcError.Value); } else { IEvaluationContext evaluationContext = arguments.EvaluationContext; double criteria = arguments[1].GetNumber(evaluationContext); IReferenceSource referenceSource = range.GetReferenceSource(evaluationContext); RangeReference rangeRef = range.GetReference(evaluationContext, 0); int count = 0; for (int c = rangeRef.Column; c <= rangeRef.Column2; c++) { for (int r = rangeRef.Row; r <= rangeRef.Row2; r++) { referenceSource.GetValue(evaluationContext, r, c, result); double cellValue = result.GetNumber(evaluationContext); if (cellValue < criteria) { count++; } } } result.SetValue(evaluationContext, count); } } } |
次のコードでは、カスタム関数を登録し、その関数をセルに実装します。
C# |
コードのコピー
|
---|---|
// カスタム関数を登録し、数式内に実装します。 fpSpread1.AddCustomFunction(new CountIfLessThanFunction()); fpSpread1.ActiveSheet.Cells[0, 0].Formula = "COUNTIFLESSTHAN(A2:A4,100)"; // 上記数式が参照している範囲に値を設定します。 fpSpread1.ActiveSheet.Cells[1, 0].Value = 110; fpSpread1.ActiveSheet.Cells[2, 0].Value = 90; fpSpread1.ActiveSheet.Cells[3, 0].Value = 200; |