首页 > 解决方案 > 有没有办法重用在遍历一列值时将行附加到工作表的逻辑?

问题描述

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

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

运动员填写的主页有 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);
               
}                     

片状结构

标签: google-apps-scriptgoogle-sheets

解决方案


少把你的代码当作一组指令,而更像是一个算法。在您的情况下,将采取以下步骤来实现目标:

  1. 遍历 column A,对于每个 [ cell ],执行以下操作:

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

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

您可能已经注意到:

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

通过使用循环遍历项目集合,通过函数实现代码重用。


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

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 
);

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

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

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

您需要启用较新的 V8 运行时才能使上述功能正常工作


推荐阅读