google-apps-script - 有没有办法重用在遍历一列值时将行附加到工作表的逻辑?

标签 google-apps-script google-sheets

我正在为我教练的运动员制定运动员训练计划和日记。我创建了一张表,在其中设置不同项目的工作量,运动员记录他们完成了多少训练计划。

然后,他们点击顶部的保存按钮,将数据传输到另一个存储训练数据的电子表格。

运动员填写的主页有 4 个部分,每个部分有 10 行,其中有下拉框以设置不同的训练事件。

我有一个可以工作的代码,但是会很长。下面是代码。目前,对于 4 个培训领域中的每一个领域,我都必须拥有 10 批列出的代码(列出了 2 份)。这意味着每个部分有 250 行,因此整个代码有 1000 行。

由于我只是将 if 语句一次向下更改 1 行,然后所有输入范围都会相应更改,有没有办法直接缩短此代码?

//Input values for routines data row 1
var routinesTRPDMT = inputS.getRange("A29").getValues(); 
if (routinesTRPDMT == "TRP"){
var routines = [[inputS.getRange("R1").getValue(),//DAY
inputS.getRange("V1").getValue(),//DATE
inputS.getRange("Z1").getValue(),//MONTH
inputS.getRange("AD1").getValue(),//SESSION
inputS.getRange("B29").getValue(),//ROUTINE
inputS.getRange("D29").getValue(),//SECTION
inputS.getRange("F29").getValue(),//REPS
inputS.getRange("J29").getValue(),//ATTEMPT 1
inputS.getRange("L29").getValue(),//ATTEMPT 2
inputS.getRange("N29").getValue(),//ATTEMPT 3
inputS.getRange("P29").getValue(),//ATTEMPT 4
inputS.getRange("R29").getValue(),//ATTEMPT 5
inputS.getRange("T29").getValue(),//ATTEMPT 6
inputS.getRange("V29").getValue(),//ATTEMPT 7
inputS.getRange("X29").getValue(),//ATTEMPT 8
inputS.getRange("Z29").getValue(),//ATTEMPT 9
inputS.getRange("AB29").getValue(),//ATTEMPT 10
inputS.getRange("AD29").getValue(),//ATTEMPT 11
inputS.getRange("AF29").getValue(),//ATTEMPT 12
dtCurrentTime]];
              
routinesS.getRange(routinesS.getLastRow()+1, 1, 1, 20).setValues(routines);
               
}   

//Input values for routines data row 2
var routinesTRPDMT = inputS.getRange("A30").getValues(); 
if (routinesTRPDMT == "TRP"){
var routines = [[inputS.getRange("R1").getValue(),//DAY
inputS.getRange("V1").getValue(),//DATE
inputS.getRange("Z1").getValue(),//MONTH
inputS.getRange("AD1").getValue(),//SESSION
inputS.getRange("B30").getValue(),//ROUTINE
inputS.getRange("D30").getValue(),//SECTION
inputS.getRange("F30").getValue(),//REPS
inputS.getRange("J30").getValue(),//ATTEMPT 1
inputS.getRange("L30").getValue(),//ATTEMPT 2
inputS.getRange("N30").getValue(),//ATTEMPT 3
inputS.getRange("P30").getValue(),//ATTEMPT 4
inputS.getRange("R30").getValue(),//ATTEMPT 5
inputS.getRange("T30").getValue(),//ATTEMPT 6
inputS.getRange("V30").getValue(),//ATTEMPT 7
inputS.getRange("X30").getValue(),//ATTEMPT 8
inputS.getRange("Z30").getValue(),//ATTEMPT 9
inputS.getRange("AB30").getValue(),//ATTEMPT 10
inputS.getRange("AD30").getValue(),//ATTEMPT 11
inputS.getRange("AF30").getValue(),//ATTEMPT 12
dtCurrentTime]];
              
routinesS.getRange(routinesS.getLastRow()+1, 1, 1, 20).setValues(routines);
               
}                     

sheet structure

最佳答案

不要将代码视为一组指令,而是将其视为算法。对于您的情况,将采取以下步骤来实现目标:

  1. 遍历列A,对于每个[单元格],执行以下操作:

    1. 如果[单元格值]为“TRP”,则:

      1. 从第 1 行、“R”、“V”、“Z”、“AD”列获取 4 个值
      2. 从[与单元格匹配的行]中的行中获取 15 个值
      3. 将 1 和 2 合并为一行,添加时间戳并附加到 [ 工作表 ]

您可能已经注意到:

  1. 条件中的第 1 步具有常量值,因此可以在循环外重用
  2. “单元格”和“匹配行”每次迭代都会变化,因此它们可能成为参数

使用 loop 遍历项目集合,代码重用是通过 functions 实现的.


下面是一个实用函数,用于将初始数据映射到所需的输出。您可以在循环中使用它来遍历通过 getValues() 获取的“A:A”列的值。 (您不必每次都获取单个单元格值,只需扩大范围即可)。您希望它如何与您连接:

const mapRoutine = (rowIdx, constants, rows, callback) => {
  const row = rows[rowIdx];  

  const [ 
    , routine ,, section ,, reps ,,,, 
    a1 ,, a2 ,, a3 ,, a4 , ...restAttempts
  ] = row;
  
  //skip odd indices columns starting from attempt 1 (i.e. !(0 % 2) = !0 => true )
  const attempts5to12 = restAttempts.filter((a,i) => !(i % 2));

  const values = [ routine,section,reps,a1,a2,a3,a4, ...attempts5to12 ];
  
  callback([ 
    ...constants.slice(0,-1), 
    ...values, 
    ...constants.slice(-1) 
  ]);
}

//testing:

const rowIndex = 0;
const constants = [1,2,3,4,5];
const firstRow = [,"R",,"S",,"RP",,,,"1",,"2",,"3",,"4","5",,"6",,"7",,"8",,"9",,"10",,"11",,"12"];

mapRoutine(
  rowIndex, 
  constants,
  [ firstRow ], 
  console.log 
);

signature上面的实用程序很简单,除了最后一个参数,它是一个函数 - 因为 JavaScript 中的函数是第一类对象,因此可以像任何其他对象一样作为参数传递。

在您的情况下,回调可能看起来像这样(注意最后一行中的currying):

const sheet = //get sheet somehow;
const appendRow = (sheet) => (row) => sheet.appendRow(row);
const curriedAppend = appendRow(sheet); //still a function

您需要启用newer V8 runtime使上述工作正常进行

关于google-apps-script - 有没有办法重用在遍历一列值时将行附加到工作表的逻辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62878445/

相关文章:

google-sheets - 将两个单元格合并为一个新单元格,将所有空格替换为破折号和小写字母

javascript - 如何从 Google Sheet App Script 返回#N/A?

google-apps-script - 生成不链接到行号的静态唯一 ID

javascript - 正则表达式执行时间限制在 Google Apps 脚本中如何运作?

google-apps-script - 如何在谷歌应用脚​​本中使用部分字符串获取SheetByName

javascript - 使用 Google Scripts 应用删除两个重复的行

google-sheets - 如何在 Google 表格中设置群组

javascript - 使用谷歌应用程序在脚本编辑器中拆分

javascript - 如何让for循环脚本更加高效?

google-apps-script - 自动将带有 Gmail 标签的电子邮件转换为 PDF 并将其发送到电子邮件地址