Javascript 用于循环Google应用程序脚本?例如VBA
我在Excel中有一个VBA自定义项,用于计算父-子计算的顶级数量。我在这里问了类似的问题 代码是Javascript 用于循环Google应用程序脚本?例如VBA,javascript,for-loop,google-sheets,user-defined-functions,Javascript,For Loop,Google Sheets,User Defined Functions,我在Excel中有一个VBA自定义项,用于计算父-子计算的顶级数量。我在这里问了类似的问题 代码是 Function ParentChildCalc(critCell As Range, valCell As Range) As Double Application.Volatile Dim numYes As Long Dim i As Long Dim temp As Double Do Until i = 5000 If critC
Function ParentChildCalc(critCell As Range, valCell As Range) As Double
Application.Volatile
Dim numYes As Long
Dim i As Long
Dim temp As Double
Do Until i = 5000
If critCell.Offset(i, 0) = "Yes" Then numYes = numYes + 1
If numYes = 2 Then Exit Do
temp = temp + valCell.Offset(i, 0)
i = i + 1
Loop
ParentChildCalc = temp
End Function
我试图将此UDF转换为JavaScript或TypeScript,但我仍然坚持使用公式中的偏移量和循环部分
这是我最好的机会
/**
* ParentChildCalc1
* @customfunction ParentChildCalc1
* @param {string} critCell Critical Cell
* @param {number} valCell Value Cell
* @returns {number} ParentChildCalc1
*/
function ParentChildCalc1(critCell, valCell) {
var blank = ""
var TopYes = "Yes"
var i = 1
var numYes = 1
if (critCell[i,0] == TopYes) {
numYes = numYes++
if numYes = 2 {
}
return (valCell);
} else {
return (blank);
}
}
在GoogleSheets中运行脚本并不像Excel那样工作,它可以是好的也可以是坏的。来自Excel VBA的背景,你必须改变思维方式
=MyUDF(A1,C3)
。函数签名将为您提供两个范围
对象作为参数。在谷歌表单中,情况并非如此。所有范围参数都转换为值(或值数组)。这意味着在Sheets单元格中,如果键入=MyUDF(A1,C3
,脚本代码将获得A1和C3的值。这不是您想要的range
对象。这是一组迂回的逻辑,但它与Sheets实现底层函数和脚本的方式一致。以下函数将从活动单元格中提取公式单元格并对其进行分析,以获得所需的范围对象
注意:如果UDF调用位于复合公式中,则必须修改此函数以选择它。例如,如果
公式是=MyUDF(A1,C3)
。但是如果您的公式是
=如果(A2='Yes','',MyUDF(A1,C3))
。您可以修改该函数以检测
这个,但是这里没有提供
以下是单个块中的全部代码:
/**
* ParentChildCalc1
* @customfunction ParentChildCalc1
* @param {string} critCell Critical Cell
* @param {number} valCell Value Cell
* @returns {number} ParentChildCalc1
*/
function ParentChildCalc1(critCell, valCell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var critCell = GetParamRange(1);
var valCell = GetParamRange(2);
const safetyNet = 5000;
var runningSum = 0;
var numYes = 0;
for (var i = 0; !valCell.offset(i,0).isBlank(); i++) {
if (critCell.offset(i,0).getValue() == 'Yes') {
numYes++;
if (numYes == 2) break;
if (i == safetyNet) {
throw new Error('exceeded safety net limit in ParentChildCalc1, searching ' + safetyNet + ' rows.');
}
}
runningSum = runningSum + valCell.offset(i,0).getValue();
}
return (runningSum);
}
function GetParamRange(paramNumber) {
var activeSheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
//--- expecting two parameters, split here and check
const MAXARGS = 2;
var args = formula.match(/=\w+\((.*)\)/i)[1].split(',');
if (args.length != MAXARGS) {
throw new Error('in GetParamRange: ' + args.join(',') + '- invalid number of arguments, expecting ' + MAXARGS);
}
if ((paramNumber < 1) || (paramNumber > MAXARGS)) {
throw new Error('in GetParamRange: invalid parameter requested, must be ' + MAXARGS + ' or less');
}
//--- is the worksheet specified?
var paramRange;
var parts = args[paramNumber-1].split('!');
if (parts.length == 2) {
//--- use worksheet and cell to get the range
Logger.log('activeSheet = ' + activeSheet.getName());
ss = SpreadsheetApp.getActive().getSheetByName(parts[0].replace(/\'/g, ''));
paramRange = ss.getRange(parts[1]);
}
else {
//--- get the range from the active sheet
paramRange = activeSheet.getRange(parts[0]);
}
return(paramRange);
}
/**
*亲子关系
*@customfunction ParentChildCalc1
*@param{string}critCell关键单元
*@param{number}valCell值单元格
*@returns{number}ParentChildCalc1
*/
函数ParentChildCalc1(critCell、valCell){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var critCell=GetParamRange(1);
var valCell=GetParamRange(2);
常数安全网=5000;
var runningSum=0;
var numYes=0;
对于(var i=0;!valCell.offset(i,0).isBlank();i++){
if(critCell.offset(i,0).getValue()=='Yes'){
numYes++;
如果(numYes==2)中断;
如果(i==安全网){
抛出新错误('超过ParentChildCalc1中的安全网限制,正在搜索'+safetyNet+'行');
}
}
runningSum=runningSum+valCell.offset(i,0.getValue();
}
返回(runningSum);
}
函数GetParamRange(paramNumber){
var activeSheet=SpreadsheetApp.getActiveSheet();
var formula=SpreadsheetApp.getActiveRange().getFormula();
//---需要两个参数,请在此处拆分并检查
常量MAXARGS=2;
var args=formula.match(/=\w+\(.*\)/i)[1].split(',');
如果(args.length!=MAXARGS){
抛出新错误('GetParamRange中:'+args.join(',')+'-参数数无效,应为'+MAXARGS);
}
if((paramNumber<1)| |(paramNumber>MAXARGS)){
抛出新错误('在GetParamRange中:请求的参数无效,必须为'+MAXARGS+'或更小');
}
//---是否指定了工作表?
var参数范围;
var parts=args[paramNumber-1]。拆分(“!”);
如果(parts.length==2){
//---使用工作表和单元格获取范围
Logger.log('activeSheet='+activeSheet.getName());
ss=SpreadsheetApp.getActive().getSheetByName(零件[0]。替换(/\'/g');
paramRange=ss.getRange(第[1]部分);
}
否则{
//---从活动工作表中获取范围
paramRange=activeSheet.getRange(parts[0]);
}
返回(参数范围);
}
因此,要使用此函数,只需将公式
=ParentChildCalc1(D7,C7)
在单元格E7中。我认为这是一个关于如何在JavaScript/TypeScript中创建for
循环直到I
达到5000的基本问题。您应该为JavaScript标记此循环,并可能删除excel和office-js的标记。如果您为不了解VBA的人描述循环中到底发生了什么ooks很容易解决。直觉上它看起来几乎清晰,但并不完全清晰。
/**
* ParentChildCalc1
* @customfunction ParentChildCalc1
* @param {string} critCell Critical Cell
* @param {number} valCell Value Cell
* @returns {number} ParentChildCalc1
*/
function ParentChildCalc1(critCell, valCell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var critCell = GetParamRange(1);
var valCell = GetParamRange(2);
const safetyNet = 5000;
var runningSum = 0;
var numYes = 0;
for (var i = 0; !valCell.offset(i,0).isBlank(); i++) {
if (critCell.offset(i,0).getValue() == 'Yes') {
numYes++;
if (numYes == 2) break;
if (i == safetyNet) {
throw new Error('exceeded safety net limit in ParentChildCalc1, searching ' + safetyNet + ' rows.');
}
}
runningSum = runningSum + valCell.offset(i,0).getValue();
}
return (runningSum);
}
/**
* ParentChildCalc1
* @customfunction ParentChildCalc1
* @param {string} critCell Critical Cell
* @param {number} valCell Value Cell
* @returns {number} ParentChildCalc1
*/
function ParentChildCalc1(critCell, valCell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var critCell = GetParamRange(1);
var valCell = GetParamRange(2);
const safetyNet = 5000;
var runningSum = 0;
var numYes = 0;
for (var i = 0; !valCell.offset(i,0).isBlank(); i++) {
if (critCell.offset(i,0).getValue() == 'Yes') {
numYes++;
if (numYes == 2) break;
if (i == safetyNet) {
throw new Error('exceeded safety net limit in ParentChildCalc1, searching ' + safetyNet + ' rows.');
}
}
runningSum = runningSum + valCell.offset(i,0).getValue();
}
return (runningSum);
}
function GetParamRange(paramNumber) {
var activeSheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
//--- expecting two parameters, split here and check
const MAXARGS = 2;
var args = formula.match(/=\w+\((.*)\)/i)[1].split(',');
if (args.length != MAXARGS) {
throw new Error('in GetParamRange: ' + args.join(',') + '- invalid number of arguments, expecting ' + MAXARGS);
}
if ((paramNumber < 1) || (paramNumber > MAXARGS)) {
throw new Error('in GetParamRange: invalid parameter requested, must be ' + MAXARGS + ' or less');
}
//--- is the worksheet specified?
var paramRange;
var parts = args[paramNumber-1].split('!');
if (parts.length == 2) {
//--- use worksheet and cell to get the range
Logger.log('activeSheet = ' + activeSheet.getName());
ss = SpreadsheetApp.getActive().getSheetByName(parts[0].replace(/\'/g, ''));
paramRange = ss.getRange(parts[1]);
}
else {
//--- get the range from the active sheet
paramRange = activeSheet.getRange(parts[0]);
}
return(paramRange);
}