【问题标题】:ExcelDna F# and optional argumentsExcelDna F# 和可选参数
【发布时间】:2019-05-10 22:43:56
【问题描述】:

对于标量(即非类数组)可选参数,我会使用这种模式:

[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test1 ([<ExcelArgument(Description= "Optional. This is a double. Default is 42.0.")>] arg1 : obj) : double = 
    match arg1 with
    | :? ExcelMissing -> 42.0  // the argument was missing
    | :? double as d  -> d     // the argument was a double
    | _               -> -1.0  // otherwise

我不确定这段代码在 Excel-Dna / F# 中是否“惯用”,但它似乎“有效”。

但是我不确定如何处理可选的类似数组的参数。例如:

[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test2 ([<ExcelArgument(Description= "Optional. This is a double. Default is [42, 42].")>] arg1 : obj[]) : double[] = 
    match arg1.[0] with
    | :? ExcelMissing -> [42.0; 42.0] |> List.toArray // the argument was missing OR it was an empty array
    | :? double as d  -> arg1 |> castToDouble         // the argument was an array and its first argument was a double
    | _               -> Array.empty                  // otherwise

以上似乎适用于大多数情况,但不允许正确处理边缘情况:例如,如果 arg1 是一个空数组。 (castToDouble是自定义的obj[] -&gt; double[]转换函数)

在 F#/Excel-Dna 中处理 可选 双数组的正确/惯用方法是什么,然后我该如何重写 test_test2?

=========== 编辑 ===

按照 Govert 的建议,我尝试了以下方法:

[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test3 ([<ExcelArgument(Description= "Optional. This is a double. Default is [42, 42].")>] arg1 : obj) : double[] = 
    match arg1 with
    | :? (double[]) as ds  -> [1.0; 2.0] |> List.toArray   // the argument was a array of double elements
    | :? ExcelMissing      -> [42.0; 42.0] |> List.toArray // the argument was missing OR it was an empty array
    | _                    -> Array.empty                  // otherwise        

...但不幸的是,当我传递一个双精度数组(或其他任何东西)时,我得到了一个#NUM! 输出。只有当我什么都不传递时,我才能正确获得 [42.0, 42.0] 数组。

【问题讨论】:

  • 最好将类型声明为 'obj',然后从那里检查。
  • 谢谢,我试过了(请参阅我的编辑部分),但没有成功。我做错了什么?
  • “| :? (double[])” 真的适合你吗?我希望它以 obj 数组的形式出现。
  • 另外,你不能真正返回 Array.empty 作为结果。这有几个问题,一个很明显,一个更微妙。明显的问题是您必须返回 Excel 一些它认为可以放入单元格(或多个单元格,如果您将 UDF 称为数组公式)中的内容。这意味着,数字(所有数字实际上都是浮点数)、字符串、布尔值或特殊的 Excel 错误值之一。 Excel 不知道如何处理空数组。更微妙的问题是语义:在这种情况下,您打算返回错误值还是默认值?
  • @Jim Foye,| :? (double[]) 似乎不匹配。 | :? (obj[]) 也不匹配,但 | :? (obj[,]) 匹配。

标签: f# excel-dna


【解决方案1】:

这涵盖了所有可能性:


[<ExcelFunction("describes the input argument")>]
let describe(arg1 : obj) : string =
    match arg1 with
        | :? double as d        -> sprintf "Double: %f" d
        | :? string as s        -> "String: " + s
        | :? bool as b          -> sprintf "Boolean: %b" b
        | :? ExcelError as err  -> sprintf "ExcelError: %A" err
        | :? (obj[,]) as arr    -> sprintf "Array[%i, %i]" (Array2D.length1 arr) (Array2D.length2 arr)
        | :? ExcelEmpty         -> "<<Empty>>"
        | :? ExcelMissing       -> "<<Missing>>"
        | _                     -> "!? Unheard of ?!"

【讨论】:

  • 谢谢!这是否意味着没有 直接 方法可以匹配 obj[](obj 的 1d 数组)或 double[,](基本类型的 2d 数组)之类的东西?也就是说,为了匹配 doubles 的 optional 1d 数组,我应该确定 1)它是否是缺少的参数,2)如果没有丢失,它是一个二维数组吗,3) 如果它是一个二维数组,它的长度是否等于 1 和 4) 如果它确实是一个 obj 数组,那么所有元素都是相同类型的(例如这里它们都是双元素吗)?
  • 如果您的参数是 obj 类型,您将永远不会从 Excel-DNA 封送层获得 double[,] 或 1d obj[]。上面的 sn-p 显示了您可能得到的所有不同类型。与内置函数一样,如果您无法处理给定的参数,则可以返回 ExcelError.ExcelErrorValue (#VALUE) 之类的内容。
  • Govert 的回答是正确的(当然——他是 Excel-Dna 的作者)。因此,一旦你知道你拥有什么,并且你拥有的是 obj[,],你就必须做更多的工作才能看到里面有什么。你不能假设有人给你双打,例如,那里可能有其他类型加上空单元格(这将是 ExcelMissing)。
猜你喜欢
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
相关资源
最近更新 更多