7

我正在使用 F# 和 Excel 互操作将数据输出到 Excel 电子表格。我的第一种方法是单独设置每个单元格:

worksheet.Range(range1).Value2 <- "=sum(a1:a10)"
worksheet.Range(range2).Value2 <- "=min(a1:a10)"
worksheet.Range(range3).Value2 <- "=max(a1:a10)"
(* etc *)

但是,当有大量公式时,这太慢了,所以我切换到一个数组:

worksheet.Range(range).Value2 <- [| "=sum(a1:a10)"
                                    "=min(a1:a10)"
                                    "=max(a1:a10)" |]

或者

worksheet.Range(range).Formula <- [| "=sum(a1:a10)"
                                     "=min(a1:a10)"
                                     "=max(a1:a10)" |]

但是,现在 Excel 只在单元格中显示这些字符串,而不是计算公式的值。我也试过:

worksheet.Range(range).FormulaArray <- [| "=sum(a1:a10)"
                                          "=min(a1:a10)"
                                          "=max(a1:a10)" |]

但这与每个公式的目标范围相混淆。我不确定那里发生了什么。(Excel 没有将其保留为"a1:a10",而是根据公式所在的位置翻译了目标范围。)

有一个更好的方法吗?

更新:我也尝试使用“=MIN($G$2:$G$5)”,但产生了相同的效果,其中 Excel 只是显示字符串而不评估公式。

对于它的价值,当我输入单元格时,擦除然后重新添加公式中的任何字符,当我点击“输入”时,Excel 将对其进行评估。

更新 2:我还尝试了以下方法:

worksheet.Range(range).FormulaR1C1 <- [| "=sum(R2C[0]:R4C[0])"
                                          "=average(R2C[0]:R4C[0])"
                                          "=min(R2C[0]:R4C[0])"
                                          "=max(R2C[0]:R4C[0])" |]

但我遇到了同样的问题:Excel 将它们呈现为字符串而不是评估公式。

4

4 回答 4

8

丹尼尔的回答应该有效,但我发现使用 R1C1 格式的公式更容易。您的代码应如下所示才能使用它:

ws.Range(range).FormulaR1C1 <- [| "=sum(R1C1:R10C1)";
                                  "=min(R1C1:R10C1)"; 
                                  "=max(R1C1:R10C1)" |]

这将生成具有绝对地址的公式。您可以使用 R[vertical_offset]C[horizo​​ntal_offset] 构建相对地址。选择整行或整列也很容易:R1 是整个第一行,C4 是整个“D”列。

使用纯 F# 中的 String.Format 或 sprintf 轻松构建 R1C1 地址。

编辑:我快速检查了 vba,它不起作用。Excel 将第一个数组元素放在范围内的每个单元格中。无论如何,R1C1 寻址点仍然有效。它就像标题公式的魅力(即 ws.Range(headerRange).FormulaR1C1 <- "=sum(R2C[0]:R10C[0]")),所以我将保持答案不变。

EDIT2:我认为 ArrayFormula 是用于数组公式的,所以它也不起作用。

EDIT3:我做了一些研究,找到了我认为不可能的事情的答案:)。

首先,将此字符串作为公式,将它们向上转换为对象:

let formulas : obj[] = [| "=sum(R1C1:R10C1)";
                          "=min(R1C1:R10C1)"; 
                          "=max(R1C1:R10C1)" |]

然后把它放在FormulaR1C1中:

ws.Range(range).FormulaR1C1 <- formulas

第二,重要部分:上面的例子假设范围是三个单元格的水平范围(即F3:H3)。如果您尝试将其放在垂直范围内(即 F3:F5),您会注意到,该求和公式在范围内的每个单元格中重复。我敢打赌,在这种情况下,公式应该是二维对象数组,外部数组的第一行是公式数组,但是我在尝试将其放入 range.FormulaR1C1 时得到了 SafeArrayTypeObjectExtension。看看这个 msdn 文档

如果范围是一维或二维范围,则可以将公式设置为相同维度的 Visual Basic 数组。同样,您可以将公式放入 Visual Basic 数组中。

稍后我将再次查看此异常。

于 2012-09-18T20:42:11.020 回答
1

假设您的第一种方法有效,并且速度慢意味着输入速度太慢(不执行),那么像这样更新一堆单元格可能会更快/更容易

[
  range1, "=sum(a1:a10)"
  range2, "=min(a1:a10)"
  range3, "=max(a1:a10)"
  ...
]
|> List.iter (fun (range, value) -> worksheet.Range(range).Value2 <- value)
于 2012-09-18T21:17:48.400 回答
1

或者,您可能会从 fsnip.net http://fssnip.net/aV上的这个片段中得到一些想法,它为 Excel 实现了一些高阶函数。(这比使用电子表格设备在性能方面具有更长远的优势,尽管该片段与性能无关。)

于 2012-09-18T21:26:35.087 回答
0

如果您无法在 Excel 中解决性能问题,您可能需要考虑 SpreadsheetGear (http://www.spreadsheetgear.com/)。它几乎复制了整个 Excel API,但速度更快。(另一个优点 - 如果您正在开发要在服务器上运行的东西,则不必在服务器上安装 Excel。)

于 2012-09-18T21:20:09.893 回答