如何在 F# 中编写一个可以从 Excel 调用的函数,它将一个范围作为输入并将一个数组输出到 ssheet 中?

How do I write a function in F# that can be called from Excel and which will take a range as input and output an array into the ssheet?

我知道如何在 C# 中执行此操作,并且我可以使用 Excel DNA 创建加载项。我无法弄清楚启用函数 f 的 F# 语法,为了简单起见,它执行类似于 f(x)= 维数 [2,2] 的二维数组,其中包含 x 的所有 4 个值。因此,我将从 excel 中调用 f,从单元格中获取输入,它会 return 2x2 数组。 (我将在这里做更复杂的事情——但如果我能理解那个简单的案例,我会没事的)。非常感谢帮助!

我创建 F# 函数的尝试如下所示:

let array2D : int [,] = Array2D.zeroCreate 20 20
let g x = array2D

我遇到的问题是,它没有在 xla 名称下的 excel 下拉列表中显示为函数。

工作 C# 示例:

public static double[,] arraytoexcel(int N) 
{ 
    double[,] RetArray = new double[N, N]; 
    for (int i = 0; i < N; i++) { 
        for (int j = 0; j < N; j++) { 
            RetArray[i, j] = N; 
        } 
    } 
    return RetArray; 
}

你可能想要这样的东西:

let calculateCellContents size x y = float (y * size + x) // Whatever math you need

let mkArray size = Array2D.init size size (calculateCellContents size)

请注意 calculateCellContents returns 一个 float(C# double 的 F# 名称),而不是 int。您的 C# 示例具有返回 double 值数组的函数,如果 XLA 正在寻找具有该签名的函数(返回浮点数数组),那么这可能是它未显示的一个可能原因。

现在,如果这不能解决 "this doesn't appear as a function in the excel dropdown" 问题,我想到了另外两种可能性。首先,如果您应该为 Excel 下拉菜单设置函数属性以便能够找到它,则语法为 [<AttributeName>]。例如:

let calculateCellContents size x y = float (y * size + x) // Whatever math you need

[<ExcelFunction(Description="Make a simple array")>]
let mkArray size = Array2D.init size size (calculateCellContents size)

其次,可能是您必须更改函数的类型。 F# 函数的类型为 FSharpFunc,XLA 完全有可能寻找 Func 而不是 FSharpFunc。您可以通过从 F# 函数创建一个新的 System.Func 对象来在它们之间进行转换:

let calculateCellContents size x y = float (y * size + x) // Whatever math you need

let mkArray size = Array2D.init size size (calculateCellContents size)

let mkArrayVisibleFromExcel = new System.Func<int,float>(mkArray)

或者可能:

[<ExcelFunction(Description="Make a simple array")>]
let mkArrayVisibleFromExcel = new System.Func<int,float>(mkArray)

如果这不起作用,请尝试将 mkArray 更改为采用 float 参数,并相应地更改对 Array2D.init 的调用:

let calculateCellContents sizeF x y = float y * sizeF + float x // Whatever math you need

let mkArray (sizeF:float) = 
    Array2D.init (int sizeF) (int sizeF) (calculateCellContents sizeF)

[<ExcelFunction(Description="Make a simple array")>]
let mkArrayVisibleFromExcel = new System.Func<float,float>(mkArray)

如果其中 none 可以使您的函数在 Excel 的 XLA 下拉列表中可见,那我就没主意了。