Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用于循环Google应用程序脚本?例如VBA_Javascript_For Loop_Google Sheets_User Defined Functions - Fatal编程技术网

Javascript 用于循环Google应用程序脚本?例如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

我在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 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的背景,你必须改变思维方式

  • 在Excel中编写用户定义函数(UDF)时,可以传递如下参数:
    =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);
    }