评估公式的子公式
Evaluate a sub-formula of a formula
在 select 一个有公式的单元格后,我们可以 select 在 Excel 公式栏中计算它的一部分公式并计算它(通过按 F9)。我需要通过 JavaScript API.
重现子公式的评估
例如,假设单元格A1
、B1
、C1
的值分别为1
、2
、3
,单元格 D1
包含公式 =A1+B1+C1
。我希望能够快速评估子公式,例如 A1+B1
、B1+C1
,并得到结果 3
和 5
.
在VBA中,在manual
计算模式下,我们可以将D1
的初始公式存储在一个变量中,然后赋值一个子公式(例如,=A1+B1
) 到 D1
得到结果 3
,然后像什么都没发生一样将初始公式还原回 D1
;此评估不会引发任何其他单元格的计算,这些单元格是 D1
的后代(感谢 manual
模式)。
但是,对于JavaScript API,重新计算仅在automatic
模式下有效。如果我们将子公式(例如,=A1+B1
)分配给 D1
,所有属于 D1
后代的单元格都将由 ctx.sync
重新计算,这可能代价高昂.
那么有没有办法或解决方法来优化它?
一种可能的解决方法是在工作簿中找到一个没有单元格依赖的孤立单元格(例如,工作表 usedRange
之外的单元格,但我们仍然需要确保没有单元格依赖它,因为 usedRange
...) 的性质,然后将子公式分配给该单元格并获取值。这种方法的缺点是
1) 它仍然是 hack,并且修改了工作表的区域。
2) 用户定义的函数(如果编程不当)可能依赖于工作表的尺寸或包含它的单元格的位置。在这种情况下,在孤立的单元格中评估用户定义的函数可能会导致与原始单元格中的评估不同的结果(或副作用)。
有人能帮忙吗?
我认为您列出的第一种方法可能是最简单的。即,重新读取单元格的公式并将其保存为 javascript 变量(字符串)。接下来就地修改公式,对值发出加载,然后将公式恢复为保存字符串。这种方法唯一真正的缺点是您弄乱了某人的公式,这意味着如果在步骤 1 和步骤 2 之间出现问题,您会使文档处于脏状态。而且,正如您所说,它可能会对计算产生下游影响(性能方面)。
或者,如果您确实知道 那里有什么公式,您可以使用"worksheet functions" 功能。例如,此处计算的是 20 的总和 + 两个工作表范围的总和。
Excel.run(function (ctx) {
var result = ctx.workbook.functions.sum(
20,
ctx.workbook.worksheets.getItem("Sheet1").getRange("F3:F5"),
ctx.workbook.worksheets.getItem("Sheet1").getRange("H3:H5")
).load();
return ctx.sync();
}).catch(function(e) {
console.log(e);
});
这是 "cleanest" 的计算方式,它不会影响工作表状态,您甚至可以链接计算:
Excel.run(function (ctx) {
var range = ctx.workbook.worksheets.getItem("Sheet1").getRange("E2:H5");
var sumOfTwoLookups = ctx.workbook.functions.sum(
ctx.workbook.functions.vlookup("Wrench", range, 2, false),
ctx.workbook.functions.vlookup("Wrench", range, 3, false)
);
sumOfTwoLookups.load();
return ctx.sync();
}).catch(function(e) {
console.log(e);
});
不利之处在于,这不适用于 UDF(就此而言,也不适用于数组公式),并且您需要先验地知道单元格由哪种公式组成。但是如果你说的是计算公式的子公式,我假设你已经有一些关于公式的信息,所以后者可能不是问题。
在 select 一个有公式的单元格后,我们可以 select 在 Excel 公式栏中计算它的一部分公式并计算它(通过按 F9)。我需要通过 JavaScript API.
重现子公式的评估例如,假设单元格A1
、B1
、C1
的值分别为1
、2
、3
,单元格 D1
包含公式 =A1+B1+C1
。我希望能够快速评估子公式,例如 A1+B1
、B1+C1
,并得到结果 3
和 5
.
在VBA中,在manual
计算模式下,我们可以将D1
的初始公式存储在一个变量中,然后赋值一个子公式(例如,=A1+B1
) 到 D1
得到结果 3
,然后像什么都没发生一样将初始公式还原回 D1
;此评估不会引发任何其他单元格的计算,这些单元格是 D1
的后代(感谢 manual
模式)。
但是,对于JavaScript API,重新计算仅在automatic
模式下有效。如果我们将子公式(例如,=A1+B1
)分配给 D1
,所有属于 D1
后代的单元格都将由 ctx.sync
重新计算,这可能代价高昂.
那么有没有办法或解决方法来优化它?
一种可能的解决方法是在工作簿中找到一个没有单元格依赖的孤立单元格(例如,工作表 usedRange
之外的单元格,但我们仍然需要确保没有单元格依赖它,因为 usedRange
...) 的性质,然后将子公式分配给该单元格并获取值。这种方法的缺点是
1) 它仍然是 hack,并且修改了工作表的区域。
2) 用户定义的函数(如果编程不当)可能依赖于工作表的尺寸或包含它的单元格的位置。在这种情况下,在孤立的单元格中评估用户定义的函数可能会导致与原始单元格中的评估不同的结果(或副作用)。
有人能帮忙吗?
我认为您列出的第一种方法可能是最简单的。即,重新读取单元格的公式并将其保存为 javascript 变量(字符串)。接下来就地修改公式,对值发出加载,然后将公式恢复为保存字符串。这种方法唯一真正的缺点是您弄乱了某人的公式,这意味着如果在步骤 1 和步骤 2 之间出现问题,您会使文档处于脏状态。而且,正如您所说,它可能会对计算产生下游影响(性能方面)。
或者,如果您确实知道 那里有什么公式,您可以使用"worksheet functions" 功能。例如,此处计算的是 20 的总和 + 两个工作表范围的总和。
Excel.run(function (ctx) {
var result = ctx.workbook.functions.sum(
20,
ctx.workbook.worksheets.getItem("Sheet1").getRange("F3:F5"),
ctx.workbook.worksheets.getItem("Sheet1").getRange("H3:H5")
).load();
return ctx.sync();
}).catch(function(e) {
console.log(e);
});
这是 "cleanest" 的计算方式,它不会影响工作表状态,您甚至可以链接计算:
Excel.run(function (ctx) {
var range = ctx.workbook.worksheets.getItem("Sheet1").getRange("E2:H5");
var sumOfTwoLookups = ctx.workbook.functions.sum(
ctx.workbook.functions.vlookup("Wrench", range, 2, false),
ctx.workbook.functions.vlookup("Wrench", range, 3, false)
);
sumOfTwoLookups.load();
return ctx.sync();
}).catch(function(e) {
console.log(e);
});
不利之处在于,这不适用于 UDF(就此而言,也不适用于数组公式),并且您需要先验地知道单元格由哪种公式组成。但是如果你说的是计算公式的子公式,我假设你已经有一些关于公式的信息,所以后者可能不是问题。