【问题标题】:"cannot read property 'indexOf' of undefined"“无法读取未定义的属性‘indexOf’”
【发布时间】:2021-02-14 11:24:45
【问题描述】:

我正在编写一个简单的代码来遍历一个范围内的所有链接,从这些电子表格(链接)中收集信息并粘贴到循环的当前行中。

function UpdateProjects()
{

//----------EDIT THIS FOR A DIFFERENT CLIENT-------------
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Projects");
  var etilastrow = sheet.getLastRow();

  var urlRange = sheet.getRange(2, 1, etilastrow);
  var urlsvalues = urlRange.getValues();
  var urls = urlRange.getFormulas();
  Logger.log(urls)

  //looping through all of the rows
  for (var i = 0; i < etilastrow; ++i) {
   currentRow = 2 + i;
  var dirturl = urls[i];
  var remove_before = dirturl[i].indexOf('",');
    var url = dirturl[i].substring(12, remove_before);

Logger.log(currentRow);
    Logger.log(url);

//-----------------Loop code below until last project-------
  var projectPCBdesignsheet = SpreadsheetApp.openByUrl(url).getSheetByName("Main");
    var lstrow = projectPCBdesignsheet.getLastRow(); 

  const vA=projectPCBdesignsheet.getRange(7,2,lstrow).getValues();//get data from project's PCB Design sheet
   
//add last edit values  
  sheet.getRange(currentRow, 4).setValue(vA[10]);
  sheet.getRange(currentRow, 5).setValue(vA[11]);    

//additional data from PCB design sheet
  sheet.getRange(currentRow, 6).setValue(vA[0]);
  sheet.getRange(currentRow, 7).setValue(vA[1]);
  sheet.getRange(currentRow, 8).setValue(vA[2]);
  sheet.getRange(currentRow, 9).setValue(vA[3]);  
  sheet.getRange(currentRow, 11).setValue(vA[5]); 
}
}

如果我将 url 硬编码到变量中,脚本就可以工作。现在,从日志中,我可以看到行号和干净的 url。

问题是脚本因以下错误而停止: “类型错误:无法读取未定义的属性‘indexOf’ ETI更新项目 @UpdateProjects.gs:18"

我不明白它如何在第 18 行找到错误,如果它向我显示 currentRow 和 url 的日志,它们位于“indexOf”行之后。

【问题讨论】:

  • etilastrow 不应该这样使用,因为你开始从第 2 行而不是第 1 行获取行,你能从中减去它是否有帮助?

标签: javascript google-apps-script google-sheets indexof


【解决方案1】:

问题:

问题 1:

从第二行开始,数据中多了一个空单元格:

var urlRange = sheet.getRange(2, 1, etilastrow);

这会给你类似的东西:[[=link],['']]

这可以通过将etilastrow 更改为etilastrow-1 来解决。

for 循环中也是如此。

问题 2:

即使您修复了问题 1,当前代码中的主要问题也会产生您遇到的错误:

var dirturl = urls[i];
var remove_before = dirturl[i].indexOf('",');

请记住,urls 是一个由 etilastrow 行组成的数组,但只有 一个 列。如果你解释你的代码,你所调用的本质上是urls[i][i]。这将在第二次迭代后返回undefined,此时i 变为1,因为数据中只有一列。

您的代码有效的原因是因为您正在测试它并填充了一个单元格,因此urls[0][0] 可以正常工作,但是如果您添加更多 URL,第二个索引将增加到超过 0,例如 @ 987654338@ 将丢弃并出错,因为urls 只有一列。

要解决此问题,您可以更改:

var dirturl = urls[i];
var remove_before = dirturl[i].indexOf('",');
var url = dirturl[i].substring(12, remove_before);

到:

var dirturl = urls[i];
var remove_before = dirturl[0].indexOf('",');
var url = dirturl[0].substring(12, remove_before);

改进:

改进 1:

我建议您阅读 for 循环,因为它们在处理索引和数组时可能会令人困惑,您需要足够舒适地处理它们。使用forEachflat() 直接处理每个网址:

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Projects");
  var etilastrow = sheet.getLastRow();

  var urlRange = sheet.getRange(2, 1, etilastrow-1);
  var urlsvalues = urlRange.getValues();
  var urls = urlRange.getFormulas();


  urls.flat().forEach((r,i)=>{
    let currentRow = i + 2;
    let remove_before = r.indexOf('",');
    let url = r.substring(12, remove_before);
    console.log(url)
    console.log(currentRow)
    // put here the rest of your code
  })

改进 2:

从 Google Apps 脚本的角度来看,多次调用 setValue 以及在 for 循环内可能会降低很多性能。根据Best Practices,正确的做法是将值存储在一个数组中,然后在for循环之外使用setValues。这样,您只使用一次setValues

我可以尝试优化你的那部分代码,但答案不会有足够的帮助,因为已经有很多关于这种优化的帖子,而且你的代码应该可以使用我指出的更正。

【讨论】:

  • Marios,非常感谢您的帮助并为此预留了一些时间。我根据您的建议进行了一些修改,并且还使用单个 setValues 更新了 setValue。脚本运行得又快又好。有一个小问题:forEach 循环在找到一个没有 url 的空单元格之前不会终止。这是通过“无效参数:url”。我注意到不可能返回、中断或继续这种类型的循环,所以我想不可能用 if (url == "") 来解决这个问题。再次感谢您的支持。真的,真的很感激。
  • 仅供参考,我还尝试在用户选择该特定工作表时运行此脚本(必要时会更新信息)。我在 GAS 上的基本技能导致了这样的脚本,不幸的是它不起作用。 function onSelectionChange(e) { // 当工作表被选中时运行更新脚本 var sheet = e.sheet; var ssname = SpreadsheetApp.getActiveSheet().getName(); if(ssname === "项目") { UpdateProjects(); } }
  • @Andre8426 很高兴您的问题得到解决。 forEach 将在数组末尾终止。如果您在此之前不终止,恐怕您需要使用for 循环。性能方面,for 循环不会丢失任何东西,所以如果你想breakcontinue,我的建议是继续使用 for 循环。
  • @Andre8426 我建议您发布有关修改的新问题。 Stackoverflow 不允许跟进问题。很抱歉给您带来不便。
猜你喜欢
  • 2014-09-14
  • 2016-08-26
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2021-08-22
  • 1970-01-01
  • 2022-09-27
相关资源
最近更新 更多