【问题标题】:Getting "undefined" when trying to get values from spreadsheet尝试从电子表格中获取值时出现“未定义”
【发布时间】:2015-05-29 17:00:49
【问题描述】:

当我尝试从电子表格的单元格中获取值时,出现“未定义”错误。问题是,如果我对不同的单元格执行相同的命令,我会得到该单元格中的值。这两个单元格之间的唯一区别是产生值的方式。

单元格中正确显示的值是直接从与该电子表格关联的 Google 表单中生成的。调用时不显示的值是由我在 Google 表单中创建的脚本生成的。

表单脚本(在表单提交时触发):

// This code will set the edit form url as the value at cell "C2".

function assignEditUrls() {
    var form = FormApp.getActiveForm();
    var ss = SpreadsheetApp.openById("my-spreadsheet-id")
    var sheet = ss.getSheets()[0];

    var urlCol = 3; // column number where URL's should be populated; A = 1, B = 2 etc
    var formResponses = form.getResponses();

    for (var i = 0; i < formResponses.length; i++) {
        var resultUrl = formResponses[i].getEditResponseUrl();
        sheet.getRange(2 + i, urlCol).setValue(resultUrl); 
    } 
    SpreadsheetApp.flush();
 }

表格(已更改为 HTML)

<table>
    <tr> <!-- Row 1 -->
        <td>Timestamp</td> <!-- A1 -->
        <td>Name</td> <!-- B1 -->
        <td>Edit form URL</td> <!-- C1 -->
    </tr>
    <tr> <!-- Row 2 -->
        <td>5/26/2015 14:04:09</td> <!-- A2: this value came from the form submittion-->
        <td>Jones, Donna</td> <!-- B2: this value came from the form submittion-->
        <td>https://docs.google.com/forms/d/1-FeW-mXh_8g/viewform?edit2=2_ABaOh9</td> <!-- C2: this value came from the the script in the form -->
    </tr>
</table>

电子表格中的脚本(在表单提交时触发)

function onFormSubmit(e) {

    // This script will get the values from different cells in the spreadsheet 
    // and will send them into an email.

    var name = e.range.getValues()[0][1]; // This will get the value from cell "B2".
    var editFormURL = e.range.getValues()[0][2]; // This will get the value from cell "C2".

    var email = 'my-email@university.edu';
    var subject = "Here goes the email subject."
    var message = 'This is the body of the email and includes'
                  + 'the value from cell "B2" <b>'
                  + name + '</b>. This value is retrieved correctly.' 
                  + '<br>But the value from cell "C2" <b>'+ editFormURL
                  + '</b> show as "undefined".';

    MailApp.sendEmail(email, subject, message, {htmlBody: message});
}

电子邮件如下所示:

发送者:my-email@university.edu

主题:这里是电子邮件主题。

主体:

这是电子邮件的正文,包括单元格“B2”Jones, Donna 中的值。此值已正确检索。

但单元格“C2”中的值undefined显示为“undefined”。

问题:

我做错了什么?

【问题讨论】:

  • Logger.log() 语句添加到您的代码以调试您的代码。在 onFormSubmit(e) 函数的顶部添加 Logger.log('range is: ' + e.range.getA1Notation()) 语句。范围是多少?在“查看”菜单下,选择“日志”菜单项,提交表单后
  • 我这样做了,它有助于更​​好地理解问题。我得到了范围:A285:Q285。我的表有 285 行,列从 A 到 X。因此范围缺少从 R 到 X 的列,编辑表单 url 位于 X 列。因此,有了这些新信息,我如何告诉脚本从 A 获取范围到 X 而不是我现在拥有的。
  • 查看新答案。使用e.range.getRow() 获取行。 X 列的列号始终相同。

标签: javascript google-apps-script google-sheets google-spreadsheet-api google-forms


【解决方案1】:

您很可能遇到了比赛条件。

  1. 用户提交表单。这是我们的主要活动。

  2. 提交表单后,所有与该事件关联的触发器都会被触发。

    • assignEditUrls() 在表单脚本中,以及

    • onFormSubmit() 在电子表格脚本中。

    如果您为此事件设置了其他脚本,它们也会触发。这里的复杂之处在于,所有这些触发器都是独立触发的,或多或少同时触发,但没有保证执行顺序。电子表格触发器可能在表单触发器之前运行!所以这是一个问题。

每个触发器都会以特定于其定义的格式接收事件信息。 (参见Event Objects。)由于C2 实际上不是表单提交的一部分,它不会出现在电子表格函数接收到的事件对象中。这是您的第二个问题,但由于您知道该值相对于表单输入的偏移量,您可以使用range.offset() 来获取它。

另一个问题与文档和电子表格的共享方式有关。每个单独的脚本调用都将收到它自己的电子表格副本,该副本与其他副本同步......最终。一个脚本对电子表格所做的更改不会立即对所有其他用户可见。这就产生了三个问题。

怎么办?

您可以尝试协调两个相关触发函数的操作。如果它们在同一个脚本中,锁定服务可以帮助解决这个问题。

您可以只使用一个触发函数来执行这两种操作。

或者您可以让电子表格函数容忍任何延迟,方法是让它等待填充C2。这个 sn-p 会这样做......

...
var editFormURL = null;
var loop = 0;
while (!editFormURL) {
  editFormURL = e.range.offset(0,2).getValue(); // This will get the value from cell "C2".
  if (!editFormURL) {
    // Not ready yet, should we wait?
    if (loop++ < 10) {
      Utilities.sleep(2000); // sleep 2 seconds
    }
    else throw new Error( 'Gave up waiting.' );
  }
}

// If the script gets here, then it has retrieved a value for editFormURL.
...

一个额外的问题:由于您使用的是getValues(),加上复数s,您正在检索二维信息数组。您没有看到问题,因为当您将这些值视为字符串时,javascript 解释器 coerces 将数组转换为您想要的字符串。但这仍然是一个问题——如果你想要一个单一的值,请使用getValue()

【讨论】:

  • 此答案确实改进了我的代码,但问题已通过 Sandy Good 答案解决。我非常感谢您的回答,我希望它可以帮助其他人,因为它帮助了我。谢谢。
【解决方案2】:

获取正确的行,然后使用您的 URL 对列进行硬编码:

var ss = SpreadsheetApp.openById("my-spreadsheet-id")
var sheet = ss.getSheets()[0];

var rowForLookup = e.range.getRow();
var columnOfUrl = 24; //Column X
var theUrl = sheet.getRange(rowForLookup, columnOfUrl).getValue();

【讨论】:

    【解决方案3】:

    所以这段代码是我在实施你的建议后最终得到的。感谢 Sandy Good 和 Mogsdad。

    function onFormSubmit(e) {
    
        Logger.log("Event Range: " + e.range.getA1Notation());
    
        var ss = SpreadsheetApp.getActiveSpreadsheet();
        var sheet = ss.getSheets()[0];
    
        var startRow = e.range.getRow();
        var startCol = 1;
        var numRows = 1;
        var numColumns = sheet.getLastColumn();
    
        var dataRange = sheet.getRange(startRow, startCol, numRows, numColumns);
        var data = dataRange.getValues();
    
        Logger.log("Data Range: " + dataRange.getA1Notation());
    
    
        for (var i = 0; i < data.length; ++i) {
            var column = data[i];
            var name = column[4];
    
            var editFormURL = null;
            var loop = 0;
    
            while (!editFormURL) {
                editFormURL = column[23];
                if (!editFormURL) { 
                    // Not ready yet, should we wait?
                    if (loop++ < 10) {
                        Utilities.sleep(3000); // sleep 2 second
                    }
                    else throw new Error( 'Gave up waiting.' );
                }
            }    
    
            var email = 'my-email@university.edu';
            var subject = "Subject here";
            var message = 'Some text about ' + name + '.' +
                          '<br><br>Please view this link: ' + 
                          + editFormURL;
    
            MailApp.sendEmail(email, subject, message, {htmlBody: message});
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多