MESCIUS SPREAD for Windows Forms 17.0J サンプルコード集
独自の数式を設定する(既存クラスの継承)

MESCIUS SPREAD for Windows Forms 17.0J サンプルコード集 > 数式 > 独自の数式を設定する(既存クラスの継承)

SPREADからは数多くの組み込み関数が提供されているため、通常はこれらの利用によってほとんどの機能を実現できます。

しかしながら、提供されている関数以外の処理を実装したい場合にはFunctionInfoクラス(FarPoint.CalcEngine名前空間)を継承したサブクラスを作成することで、独自のカスタム関数を作成することも可能です。(カスタム関数の引数としてセル範囲を渡した場合は、Evaluateメソッドの引数args()にもセル範囲が渡されます)

本サンプルでは、独自に作成したカスタム関数(MySumFunction)にセル範囲を指定することで、範囲内の全ての値を足し込んだ結果を返す例を紹介します。

【実行例】

カスタム関数


 private void Form1_Load(object sender, System.EventArgs e)
 {

   fpSpread1.ActiveSheet.RowCount = 4;
   fpSpread1.ActiveSheet.ColumnCount = 4;
   fpSpread1.ActiveSheet.DefaultStyle.CellType = new FarPoint.Win.Spread.CellType.NumberCellType();
   fpSpread1.ActiveSheet.HorizontalGridLine = new FarPoint.Win.Spread.GridLine(FarPoint.Win.Spread.GridLineType.None);
   fpSpread1.ActiveSheet.VerticalGridLine = new FarPoint.Win.Spread.GridLine(FarPoint.Win.Spread.GridLineType.None);
   fpSpread1.ActiveSheet.Cells[0, 0, 2, 2].BackColor = Color.LightPink;
   fpSpread1.ActiveSheet.Cells[3, 3].BackColor = Color.LemonChiffon;
   fpSpread1.ActiveSheet.Cells[3, 3].Border = new FarPoint.Win.LineBorder(Color.Blue, 2);

   fpSpread1.ActiveSheet.SetValue(0, 0, 10);
   fpSpread1.ActiveSheet.SetValue(1, 0, 20);
   fpSpread1.ActiveSheet.SetValue(2, 0, 30);
   fpSpread1.ActiveSheet.SetValue(0, 1, 40);
   fpSpread1.ActiveSheet.SetValue(1, 1, 50);
   fpSpread1.ActiveSheet.SetValue(2, 1, 60);
   fpSpread1.ActiveSheet.SetValue(0, 2, 70);
   fpSpread1.ActiveSheet.SetValue(1, 2, 80);
   fpSpread1.ActiveSheet.SetValue(2, 2, 90);

   FarPoint.Win.Spread.Model.ICustomFunctionSupport fs = (FarPoint.Win.Spread.Model.ICustomFunctionSupport)fpSpread1.ActiveSheet.Models.Data;
   FarPoint.CalcEngine.FunctionInfo f = fs.GetCustomFunction("MySumFunction");

   if (f == null)
   {
      //作成したカスタム関数を追加します
      fs.AddCustomFunction(new MySumFunction());
   }
   else
   {
      fs.RemoveCustomFunction("MySumFunction");
   }

   //セルに関数を設定します
   fpSpread1.ActiveSheet.SetFormula(3, 3, "MySumFunction(A1:C3)");

 }
 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

   FpSpread1.ActiveSheet.RowCount = 4
   FpSpread1.ActiveSheet.ColumnCount = 4
   FpSpread1.ActiveSheet.DefaultStyle.CellType = New FarPoint.Win.Spread.CellType.NumberCellType
   FpSpread1.ActiveSheet.HorizontalGridLine = New FarPoint.Win.Spread.GridLine(FarPoint.Win.Spread.GridLineType.None)
   FpSpread1.ActiveSheet.VerticalGridLine = New FarPoint.Win.Spread.GridLine(FarPoint.Win.Spread.GridLineType.None)
   FpSpread1.ActiveSheet.Cells(0, 0, 2, 2).BackColor = Color.LightPink
   FpSpread1.ActiveSheet.Cells(3, 3).BackColor = Color.LemonChiffon
   FpSpread1.ActiveSheet.Cells(3, 3).Border = New FarPoint.Win.LineBorder(Color.Blue, 2)

   FpSpread1.ActiveSheet.SetValue(0, 0, 10)
   FpSpread1.ActiveSheet.SetValue(1, 0, 20)
   FpSpread1.ActiveSheet.SetValue(2, 0, 30)
   FpSpread1.ActiveSheet.SetValue(0, 1, 40)
   FpSpread1.ActiveSheet.SetValue(1, 1, 50)
   FpSpread1.ActiveSheet.SetValue(2, 1, 60)
   FpSpread1.ActiveSheet.SetValue(0, 2, 70)
   FpSpread1.ActiveSheet.SetValue(1, 2, 80)
   FpSpread1.ActiveSheet.SetValue(2, 2, 90)

   Dim fs As FarPoint.Win.Spread.Model.ICustomFunctionSupport = FpSpread1.ActiveSheet.Models.Data
   Dim f As FarPoint.CalcEngine.FunctionInfo = fs.GetCustomFunction("MySumFunction")

   If f Is Nothing Then
      '作成したカスタム関数を追加します
      fs.AddCustomFunction(New MySumFunction)
   Else
      fs.RemoveCustomFunction("MySumFunction")
   End If

   'セルに関数を設定します
   FpSpread1.ActiveSheet.SetFormula(3, 3, "MySumFunction(A1:C3)")

 End Sub

カスタム関数クラス

 [Serializable()] public class MySumFunction : FarPoint.CalcEngine.FunctionInfo //FunctionInfoクラスを継承したサブクラスを作成します
 {

   public override object Evaluate(object[] args)
   {
      FarPoint.CalcEngine.CalcReference cr;
      double total = 0;

      if (args[0] is FarPoint.CalcEngine.CalcReference)
      {

         //引数args[0]より範囲を取得します
         cr = (FarPoint.CalcEngine.CalcReference)args[0];
         for (int r = cr.Row; r < (cr.Row + cr.RowCount); r++)
         {
            for (int c = cr.Column; c < (cr.Column + cr.ColumnCount); c++)
            {
               //範囲内の値を足し込みます
               total += FarPoint.CalcEngine.CalcConvert.ToDouble(cr.GetValue(r, c));
            }
         }

         //算出結果を返します
         return total;

      }
      else
      {
         return FarPoint.CalcEngine.CalcError.Value;
      }

   }

   public override int MaxArgs { get { return 1; } }

   public override int MinArgs { get { return 1; } }

   public override string Name { get { return "MySumFunction"; } }

   public override bool AcceptsReference (int i) { return true; }

 }
 <Serializable()> Public Class MySumFunction

   'FunctionInfoクラスを継承したサブクラスを作成します
   Inherits FarPoint.CalcEngine.FunctionInfo

   Public Overrides Function Evaluate(ByVal args() As Object) As Object

      Dim cr As FarPoint.CalcEngine.CalcReference
      Dim total As Double = 0

      If TypeOf args(0) Is FarPoint.CalcEngine.CalcReference Then

         '引数args(0)より範囲を取得します
         cr = CType(args(0), FarPoint.CalcEngine.CalcReference)
         For r As Integer = cr.Row To cr.Row + cr.RowCount - 1
            For c As Integer = cr.Column To cr.Column + cr.ColumnCount - 1
               '範囲内の値を足し込みます
               total += FarPoint.CalcEngine.CalcConvert.ToDouble(cr.GetValue(r, c))
            Next
         Next

         '算出結果を返します
         Return total

      Else
         Return FarPoint.CalcEngine.CalcError.Value
      End If

   End Function

   Public Overrides ReadOnly Property MaxArgs() As Integer
      Get
         Return 1
      End Get
   End Property

   Public Overrides ReadOnly Property MinArgs() As Integer
      Get
         Return 1
      End Get
   End Property

   Public Overrides ReadOnly Property Name() As String
      Get
         Return "MySumFunction"
      End Get
   End Property

   Public Overrides Function AcceptsReference(ByVal i As Integer) As Boolean
      Return True
   End Function

 End Class