【问题标题】:Using built-in spreadsheet functions in a script在脚本中使用内置电子表格函数
【发布时间】:2012-07-24 12:35:35
【问题描述】:

我是第一次使用 Google 应用脚本。 我在 Google Doc 电子表格中使用它。

我正在尝试非常简单的功能,只是为了学习基础知识。例如这有效:

function test_hello() {
    return 'hello';
}

但我对这个简单的问题感到困惑:

function test_today() {
    return today();
}

无论我在哪里使用它都会生成#ERROR!。 当我把光标放在上面时,它会说:

错误:ReferenceError:“今天”未定义。

虽然today() 函数在电子表格中直接使用时有效。

这是否意味着在脚本中,我不能使用电子表格的内置函数? 有什么优雅的方法吗?

一些电子表格功能对我来说非常有用(例如,我喜欢weekday())。

一种不优雅的方式可能是创建列来计算我需要的中间值,并且可以使用电子表格函数进行计算。但我宁愿避免这种肮脏和麻烦的事情。

【问题讨论】:

    标签: google-apps-script google-sheets google-sheets-formula worksheet-function


    【解决方案1】:

    Google Apps 脚本是 JavaScript 的子集,目前不支持电子表格函数。 例如,如果你想创建一个返回今天日期的函数,你应该这样写:

    function test_today(){
    return new Date()
    }// note that this will  eventually return a value in milliseconds , you'll have to set the cell format to 'date' or 'time' or both ;-)
    

    语法与工作表函数相同:=test_today()see tutorial

    关于 javascript 的互联网资源有很多,我发现其中最有用的资源之一是 w3school

    【讨论】:

    • 您知道 Google 是否计划在其脚本语言中实现电子表格功能?就我而言,我正在查看 TO_DATE,用 JavaScript 重写它很痛苦。
    • 我不知道,而且我认为永远不会是这样。
    【解决方案2】:

    Google Apps 脚本仍然没有(2020 年 1 月 7 日)包含用于 Google 表格本机函数的 API。

    但您可以在电子表格中设置命名为命名范围的单元格的公式(本机函数)。

    然后在 GAS 中:

    var nativeOutput = spreadsheet.getRangeByName("outputCell").getValue();
    

    瞧!您的 GAS 正在调用单元格中的本机函数。

    您可以通过命名工作表(或任何工作表)中由另一个单元格中的公式引用的另一个单元格来将数据从 GAS 发送到单元格中的本机函数:

    spreadsheet.getRangeByName("inputCell").setValue(inputData);
    

    您的 GAS 可以动态创建这些单元,而不是对它们进行硬编码,例如:

    // Create native function, its input and output cells; set input value; use native function's output value:
    
    
    // Use active spreadsheet.
    var spreadsheet = SpreadsheetApp.getActive();
    
    
    // Name input, output cells as ranges.
    spreadsheet.setNamedRange("inputCell", spreadsheet.getRange("tuples!F1"));
    spreadsheet.setNamedRange("outputCell", spreadsheet.getRange("tuples!F2"));
    
    var outputCell = spreadsheet.getRangeByName("outputCell");
    var inputCell = spreadsheet.getRangeByName("inputCell");
    
    
    // Set native formula that consumes input cell's value, outputting in formula's cell.
    outputCell.setFormula("=WEEKNUM(inputCell)");
    
    
    // Call native function by setting input cell's value for formula to consume.
    // Formula sets its cell's value to formula's output value.
    inputCell.setValue(15);
    
    // Consume native function output.
    var nativeOutput = outputCell.getValue();
    Logger.log("nativeOutput: "+ JSON.stringify(nativeOutput)); // Logs "nativeOutput: 3"
    

    注意:这种技术会暴露电子表格用户可以访问/更改的单元格中的代码,其他电子表格操作可能会覆盖这些单元格。

    【讨论】:

    • 我在 Google 的文档中似乎找不到 setRangeByName。事实上,您的 SO 答案是 google sheets "setRangeByName" 仅有的 2 个 Google 搜索结果之一。我错过了什么吗? ?
    • clozach:不,你发现了什么:我的错字。我编辑了我的帖子“getRangeByName”->“setRangeByName”。设置范围名称的正确调用是例如。电子表格.setNamedRange(“inputCell”,电子表格.getRange(“元组!F1”));正如我稍后在帖子中正确输入的那样。
    • Exception: You do not have permission to call setFormula
    【解决方案3】:

    电子表格函数能做什么,Javascript 能做什么。我只需要将var day_num = weekday() 替换为var day_num = new Date(date).getDay()

    结果如下:

    /**
    * Writes the day of the week (Monday, Tuesday, etc), based on a date
    */
    function day_name(date) {
      // calculate day number (between 1 and 7)
      var day_num = new Date(date).getDay();
    
      // return the corresponding day name
      switch(day_num) {
        case 0: return 'Sunday';    break;
        case 1: return 'Monday';    break;
        case 2: return 'Tuesday';   break;
        case 3: return 'Wednesday'; break;
        case 4: return 'Thursday';  break;
        case 5: return 'Friday';    break;
        case 6: return 'Saturday';  break;
      }
      return 'DEFECT - not a valid day number';
    };
    

    【讨论】:

    • switch 循环外的语句 (return 'DEFECT - not a valid day number';) 将永远不会执行,因为getDay() 只能返回 0 到 6 之间的整数,您可以将其删除;-)。如果你想做一些错误捕获,你可以检查输入参数是否对new Date()有效
    • 这不是一个答案,应该在实际答案的评论中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多