using System;
using SpreadsheetGear;
 
namespace ConsoleApplication
{
    /// <summary>
    /// Demonstrate a custom function which sums the range of cells or values passed to it.
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // Create a new empty workbook.
            IWorkbookSet workbookSet = Factory.GetWorkbookSet();
            
            // Add the custom function to the workbook set. 
            workbookSet.Add(MySum.MySumSingleton);
 
            // Add a workbook to the workbook set.
            IWorkbook workbook = workbookSet.Workbooks.Add();
        
            // Get the first sheet and it's cells
            SpreadsheetGear.IWorksheet worksheet = workbook.Worksheets[0]; 
            SpreadsheetGear.IRange cells = worksheet.Cells;
        
            // Assign values and formulas to cells.
            cells["A1"].Value = 1; 
            // The OFFSET(...) function enables creation of a range equal to 
            // the number of rows which have values in column A and one column.
            cells["B1"].Formula = "=MYSUM(OFFSET(A1,0,0,COUNT(A:A),1))";
 
            Console.WriteLine("Result calculated from MYSUM  =  " + cells["B1"].Value + " (should be 1).");
 
            // Add another value to column A.
            cells["A2"].Value = 2;
 
            Console.WriteLine("Result calculated from MYSUM  =  " + cells["B1"].Value + " (should be 3).");
        }
    }
    
    // A simple SUM custom function. 
    public class MySum : SpreadsheetGear.CustomFunctions.Function 
    { 
        // Set to the one and only instance of MySum. 
        public static readonly MySum MySumSingleton = new MySum(); 
  
        // Sum the numbers in a range or array. 
        public override void Evaluate( 
            SpreadsheetGear.CustomFunctions.IArguments arguments, 
            SpreadsheetGear.CustomFunctions.IValue result) 
        { 
            // Verify that there are two arguments. 
            if (arguments.Count == 1)
            {
                int rowCount;
                int colCount;
                arguments.GetArrayDimensions(0, out rowCount, out colCount);
                double[,] numbers = new double[rowCount, colCount];
                for (int row = 0; row < rowCount; row++)
                {
                    for (int col = 0; col < colCount; col++)
                    {
                        SpreadsheetGear.CustomFunctions.IValue value = arguments.GetArrayValue(0, row, col);
                        if (value.Type == SpreadsheetGear.CustomFunctions.ValueType.Number)
                            numbers[row, col] = value.Number;
                    }
                }
                // Get the two arguments as numbers, and sum them. 
                result.Number = SumThem(numbers);
            }
            else
                // Return ValueError.Value. 
                result.Error = SpreadsheetGear.ValueError.Value; 
        }
 
        private double SumThem(double[,] numbers)
        {
            double sum = 0.0;
            int rowCount = numbers.GetUpperBound(0) + 1;
            int colCount = numbers.GetUpperBound(1) + 1;
            for (int row = 0; row < rowCount; row++)
                for (int col = 0; col < colCount; col++)
                    sum += numbers[row, col];
            return sum;
        }
 
        // Singleton class - so make the constructor private. 
        private MySum() 
            : base( 
            // The name of the custom function. 
            "MYSUM", 
            // For a given set of inputs, this function always returns the same value. 
            SpreadsheetGear.CustomFunctions.Volatility.Invariant, 
            // This function returns a number. 
            SpreadsheetGear.CustomFunctions.ValueType.Number) 
        { 
        } 
    }
}