如何使用for循环在现有2D数组的末尾多次添加2D数组?

时间:2018-04-25 15:37:52

标签: for-loop multidimensional-array google-apps-script google-sheets

起点(边界条件):

  • 每周都有一系列重复活动(每周活动部分 row 9:11)。
  • 我的同事可以设置开始日期A6以及他们想要添加A5的周数。 开始情况:

目标:
运行脚本应该从A5日期到“即将发生的事件”部分(A6)以正确的日期添加row 22 and following周数。 这是脚本成功运行后的样子:

到目前为止有效:
该脚本能够以正确的顺序将一周的定期事件添加到即将发生的事件部分。如果开始日期是在一周的中间,它也可以。 (此处未显示,因为它可能不相关。)

我的代码:

function recurringWeeks() {
  var ss = SpreadsheetApp.getActiveSheet(); // selects the active spreadsheet
  var repeatingWeeks = ss.getRange(5,1).getValue(); // gets how many weeks it should repeat
  var regWeek = ss.getRange(9, 2, 3, 7).getValues(); // gets the regular week data
  var regWeekRepeated = ss.getRange(9, 2, repeatingWeeks*3, 7); // create an array to store the events for all weeks

  // fill regWeekRepeated with regWeek
  for (var j = 0; j < repeatingWeeks; j++){
    for (var i = 0; i < 3; i++){
      regWeekRepeated[i+j*3] = regWeek[i];
  }
  }  

  // Repeat week for "A5" times and add to start/end date a week
  for (var j = 0; j < repeatingWeeks; j++){
    for (var i = 0; i < 3; i++){
    regWeekRepeated[i+j*3][0] = new Date(regWeek[i][0].getTime() + j*7*3600000*24); // <-This line leads to an error message.
    }
  }

  ss.getRange(ss.getLastRow()+1,2,repeatingWeeks*3,7).setValues(regWeekRepeated); // copies weekly events after the last row
}

Repeat week for "A5" times and add to start/end date a week编辑[i + j * 6]至[i + j * 3]

方法
由于我已经解决了如何使用正确的日期和正确的顺序添加一周的重复事件,我将此作为我的“攻击点”。我很确定for-loop完成了这项工作,这是我目前的首选工具。

  • 创建一个数组(regWeek),其中包含一个重复出现的事件 一周有正确的订单和日期。的完成

  • 创建一个数组(regWeekRepeated)并用A5个数填充它 从regWeek开始的常规周(A6)。 错误1 对象不允许添加或更改属性。

  • 对填充的数组regWeekRepeated进行更改。 错误2 TypeError:无法将未定义的属性“0.0”设置为“(class)@ 3d8e4650”
  • 将值复制到“即将发生的事件”部分。的完成

我在搜索结果中找到的最佳点击 creating 2 dimension arrays 但是,这使用.push,据我所知,这意味着一个元素(可以是一行)放在数组的末尾。我也尝试过使用push,但还没有成功。

问题

  • 错误1:为什么不能将数组regWeek中的元素值赋给数组regWeekRepeated?的解决
  • 错误2:此属性问题是否与ERROR 1或其他内容有关?我试图单独解决这两个错误。的解决

  • 在这种情况下,哪种方法更有意义(逻辑上或性能方面):在现有数组的末尾推送单个行,或者将整周用作数组构建块?

A demo version of the spreadsheet

更新V01
变化:regWeekRepeated现在是一个数组 由于我收到了反馈,我已经更改了for loop

  // fill regWeekRepeated with regWeek
  var regWeekRepeated = [];
  for (var j = 0; j < repeatingWeeks; j++){
    for (var i = 0; i < 3; i++){
      regWeekRepeated.push(regWeek[i]);
    }
  }
  Logger.log(regWeekRepeated)

更新V02

  // Repeat week for "A5" times and add to start/end date a week
  for (var j = 0; j < repeatingWeeks; j++){
    for (var i = 0; i < 3; i++){
    regWeekRepeated[i+j*3][0] = new Date(regWeek[i][0].getTime() + j*7*3600000*24); //adds a week to the dates for each cycle
    //Logger.log(regWeekRepeated[i]); // log is as expected and desired
    }
    Logger.log(regWeekRepeated); // second part of log not as expected.
  }
  //Logger.log(regWeekRepeated);
  ss.getRange(ss.getLastRow()+1,2,repeatingWeeks*3,7).setValues(regWeekRepeated); // copies weekly events after the last row

此处的日志输出位于“外部”for loop中。 1 represents the first cycle, 2 the second cycle 看起来第二个for loop会覆盖元素0到2。

这里是google sheets

中的输出

更新V03
这可确保更改不会影响副本。

  // fill regWeekRepeated with regWeek
  for (var j = 0; j < repeatingWeeks; j++){
    for (var i = 0; i < 3; i++){
      regWeekRepeated[i+j*3] = regWeek[i].slice(); // shallow copy of an array
  }
  }

2 个答案:

答案 0 :(得分:1)

regWeekRepeated不是数组。 getRange()不会返回数组。

尝试从

更改
var regWeekRepeated = ss.getRange(9, 2, repeatingWeeks*3, 7); // create an array to store the events for all weeks

var regWeekRepeated = ss.getRange(9, 2, repeatingWeeks*3, 7).getValues(); // create an array to store the events for all weeks

创建数组而不触及电子表格会提高性能。

var regWeekRepeated =[];

答案 1 :(得分:0)

制作电子表格的脚本可能会受到欺骗,因为电子表格和JavaScript术语/词汇表以不同的方式使用相同的术语。也许这就是这里发生的事情。

  
      
  • 错误1:为什么无法将数组regWeek中的元素值赋给数组regWeekRepeated
  •   

regWeekRepeated是一个Range对象而不是JavaScript数组

  
      
  • 错误2:此属性问题是否与ERROR 1或其他内容有关?我试图单独解决这两个错误。
  •   

是的,这是相关的。见上一个答案。

  
      
  • 在这种情况下,哪种方法更有意义(逻辑上或性能方面):在现有数组的末尾推送单个行,或者将整个星期用作数组构建块?
  •   

我们可以说调用Google Apps Scripts类和方法是“昂贵的”,因此我们应该尽量减少对这些元素的调用次数。一种方法是将范围值传递给JavaScript数组,然后直接对其进行所有更改,然后我们将结果值传递给相应的范围。

要将范围的值传递给JavaScript 2D数组,请使用range.getValues()并将JavaScript 2D数组值传递给范围使用范围.setValues()。