独自の数式

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

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

このサンプルでは、独自に作成したカスタム関数(MySumFunction)にセル範囲を指定することで、 範囲内の全ての値を足し込んだ結果を返します。
 製品ID製品分類製品名第1Q第2Q第3Q第4Q総合計
110001乳製品酪農ミルク5,5005,0004,5006,000 
220001清涼飲料水いよかんドリンク1,0003,0002,7002,700 
320002清涼飲料水ぶどうジュース3,0003,5004,8004,800 
420003清涼飲料水マンゴードリンク2,0001,0005001,050 
530001ビール激辛ビール5,5008,0008,50010,000 
630002ビールモルトビール3,0003,5002,7804,000 
720004清涼飲料水ぶどうの街500300200700 
830003ビールオリエントの村8,0009,5009,5809,000 
940002焼酎吟醸 ほめごろし6,0007,0009,0009,500 
1040003焼酎大吟醸 オリエント1,0005,0006,0005,000 
1140005焼酎麦焼酎 ちこちこ1,0001,5001,2001,258 
1210002乳製品酪農ミルク(低脂肪)501202380456189,107

ソースコード

別ウィンドウで表示
using System;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;

public partial class customformula : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // クライアントイベントの設定
        string js = "var spid='" + FpSpread1.ClientID + "';";
    js += "    var spread = document.getElementById(spid);" + "\r\n";
    js += "    if(document.all)" + "\r\n";
    js += "    {" + "\r\n";
    js += "      spread.onEditStopped = es;" + "\r\n";
    js += "    }" + "\r\n";
    js += "    else" + "\r\n";
    js += "    {" + "\r\n";
    js += "      spread.addEventListener(\"EditStopped\", es, false);" + "\r\n";
    js += "    }" + "\r\n";

        ClientScript.RegisterStartupScript(this.GetType(), "onStartUpScript", js, true);

        if (IsPostBack) return;

        // セル型の自動設定を無効化
        FpSpread1.ActiveSheetView.DataAutoCellTypes = false;

        // データ連結
        DataSet ds = new DataSet();
        ds.ReadXml(MapPath("../App_Data/datanum2.xml"));
        FpSpread1.DataSource = ds;
        
        // SPREAD初期化
        InitSpread(FpSpread1.Sheets[0]);
    }

    private void InitSpread(FarPoint.Web.Spread.SheetView sheet)
    {
        // SPREAD設定
        sheet.FpSpread.CommandBar.Visible = false;
        sheet.FpSpread.CssClass = "spreadStyle";
        sheet.FpSpread.UseClipboard = false;

        // フォントサイズの設定
        sheet.DefaultStyle.Font.Size = FontUnit.Parse("80%");
        sheet.ColumnHeader.DefaultStyle.Font.Size = FontUnit.Parse("80%");
        sheet.RowHeader.DefaultStyle.Font.Size = FontUnit.Parse("80%");
        sheet.SheetCorner.DefaultStyle.Font.Size = FontUnit.Parse("80%");

        // シート設定
        sheet.PageSize = sheet.RowCount;

        // 総合計列追加
        sheet.AddColumns(7, 1);
        sheet.ColumnHeader.Cells[0, 7].Text = "総合計";

        // 列幅の設定
        sheet.Columns[0].Width = 45;
        sheet.Columns[1].Width = 85;
        sheet.Columns[2].Width = 135;
        sheet.Columns[3].Width = 65;
        sheet.Columns[4].Width = 65;
        sheet.Columns[5].Width = 65;
        sheet.Columns[6].Width = 65;
        sheet.Columns[7].Width = 78;

        // 縦方向の揃え位置を中央に設定
        sheet.DefaultStyle.VerticalAlign = VerticalAlign.Middle;

        // 各列のセル型を設定
        FarPoint.Web.Spread.GeneralCellType gnr = new FarPoint.Web.Spread.GeneralCellType();
        gnr.FormatString = "#,##0";
        sheet.Columns[3, 7].CellType = gnr;
        sheet.Columns[3, 7].HorizontalAlign = HorizontalAlign.Right;
        sheet.Columns[0, 2].Locked = true;

        // クライアントで値が変更された場合、数式に反映
        FpSpread1.ClientAutoCalculation = true;

        // 作成したカスタム関数を追加
        FarPoint.Web.Spread.Model.DefaultSheetDataModel model 
            = FpSpread1.ActiveSheetView.DataModel as FarPoint.Web.Spread.Model.DefaultSheetDataModel;
        model.AddCustomFunction(new MySumFunction());

        // セルに関数を設定
        sheet.SetFormula(sheet.RowCount - 1, 7, "MySumFunction(D1:G" + Convert.ToString(sheet.RowCount) + ")");
        sheet.Cells[sheet.RowCount - 1, 7].BackColor = System.Drawing.Color.Salmon;
    }   
}

[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; }
}

Partial Public Class customformula
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' クライアントイベントの設定
        Dim js As String = "var spid='" + FpSpread1.ClientID & "';"
        js += "    var spread = document.getElementById(spid);" & vbCr & vbLf
        js += "    if(document.all)" & vbCr & vbLf
        js += "    {" & vbCr & vbLf
        js += "      spread.onEditStopped = es;" & vbCr & vbLf
        js += "    }" & vbCr & vbLf
        js += "    else" & vbCr & vbLf
        js += "    {" & vbCr & vbLf
        js += "      spread.addEventListener(""EditStopped"", es, false);" & vbCr & vbLf
        js += "    }" & vbCr & vbLf

        ClientScript.RegisterStartupScript(Me.GetType(), "onStartUpScript", js, True)

        If IsPostBack Then
            Return
        End If

        ' セル型の自動設定を無効化
        FpSpread1.ActiveSheetView.DataAutoCellTypes = False

        ' データ連結
        Dim ds As New System.Data.DataSet()
        ds.ReadXml(MapPath("../App_Data/datanum2.xml"))
        FpSpread1.DataSource = ds

        ' SPREAD初期化
        InitSpread(FpSpread1.Sheets(0))
    End Sub

    Private Sub InitSpread(ByVal sheet As FarPoint.Web.Spread.SheetView)
        ' SPREAD設定
        sheet.FpSpread.CommandBar.Visible = False
        sheet.FpSpread.CssClass = "spreadStyle"
        sheet.FpSpread.UseClipboard = False

        ' フォントサイズの設定
        sheet.DefaultStyle.Font.Size = FontUnit.Parse("80%")
        sheet.ColumnHeader.DefaultStyle.Font.Size = FontUnit.Parse("80%")
        sheet.RowHeader.DefaultStyle.Font.Size = FontUnit.Parse("80%")
        sheet.SheetCorner.DefaultStyle.Font.Size = FontUnit.Parse("80%")

        ' シート設定
        sheet.PageSize = sheet.RowCount

        ' 総合計列追加
        sheet.AddColumns(7, 1)
        sheet.ColumnHeader.Cells(0, 7).Text = "総合計"

        ' 列幅の設定
        sheet.Columns(0).Width = 45
        sheet.Columns(1).Width = 85
        sheet.Columns(2).Width = 135
        sheet.Columns(3).Width = 65
        sheet.Columns(4).Width = 65
        sheet.Columns(5).Width = 65
        sheet.Columns(6).Width = 65
        sheet.Columns(7).Width = 78

        ' 縦方向の揃え位置を中央に設定
        sheet.DefaultStyle.VerticalAlign = VerticalAlign.Middle

        ' 各列のセル型を設定
        Dim gnr As New FarPoint.Web.Spread.GeneralCellType()
        gnr.FormatString = "#,##0"
        sheet.Columns(3, 7).CellType = gnr
        sheet.Columns(3, 7).HorizontalAlign = HorizontalAlign.Right
        sheet.Columns(0, 2).Locked = True

        ' クライアントで値が変更された場合、数式に反映
        FpSpread1.ClientAutoCalculation = True

        ' 作成したカスタム関数を追加
        Dim model As FarPoint.Web.Spread.Model.DefaultSheetDataModel = TryCast(FpSpread1.ActiveSheetView.DataModel, FarPoint.Web.Spread.Model.DefaultSheetDataModel)
        model.AddCustomFunction(New MySumFunction())

        ' セルに関数を設定
        sheet.SetFormula(sheet.RowCount - 1, 7, "MySumFunction(D1:G" & Convert.ToString(sheet.RowCount) & ")")
        sheet.Cells(sheet.RowCount - 1, 7).BackColor = System.Drawing.Color.Salmon
    End Sub
End Class

<Serializable()> _
Public Class MySumFunction
    Inherits FarPoint.CalcEngine.FunctionInfo
    'FunctionInfoクラスを継承したサブクラスを作成します
    Public Overloads 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 = DirectCast(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 Overloads Overrides ReadOnly Property MaxArgs() As Integer
        Get
            Return 1
        End Get
    End Property

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

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

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

<%@ Page MasterPageFile="~/MasterPage.master" Language="c#" AutoEventWireup="true" 
         Inherits="customformula" CodeFile="customformula.aspx.cs" %>

<%@ Register Assembly="FarPoint.Web.SpreadJ" Namespace="FarPoint.Web.Spread" TagPrefix="FarPoint" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeaderPlaceHolder1" Runat="Server">
<script type="text/javascript">
      function es() {
        var spread = document.getElementById(spid);
        var row = spread.GetActiveRow();
        var col = spread.GetActiveCol();
        if (col == 3 || col == 4 || col == 5 || col == 6) //数値列が編集された時のみ処理を行う
        {
            var td = spread.GetCellByRowCol(row, col);
            var v = spread.GetValue(row, col);
            td.innerHTML = setFormat(v);
        }
    }
    function setFormat(val) {
        //数値を3桁区切りにする
        var v = val;
        var t;
        while (v != (t = v.replace(/^([+-]?\d+)(\d\d\d)/, "$1,$2")))
            v = t;
        return v;
    }
</script>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <farpoint:FpSpread ID="FpSpread1" runat="server">
        <CommandBar BackColor="Control" ButtonFaceColor="Control" ButtonHighlightColor="ControlLightLight"
            ButtonShadowColor="ControlDark" />
        <Sheets>
            <farpoint:SheetView SheetName="Sheet1">
            </farpoint:SheetView>
        </Sheets>
    </farpoint:FpSpread>
</asp:Content>