Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google apps script GoogleApps脚本:表单数据操作,如果某些单元格为空,则删除行,同时保留某些列_Google Apps Script_Google Sheets_Data Manipulation - Fatal编程技术网

Google apps script GoogleApps脚本:表单数据操作,如果某些单元格为空,则删除行,同时保留某些列

Google apps script GoogleApps脚本:表单数据操作,如果某些单元格为空,则删除行,同时保留某些列,google-apps-script,google-sheets,data-manipulation,Google Apps Script,Google Sheets,Data Manipulation,这个问题是以下问题的继续: 我有一张“表单回复”表,用户最多可以填写5次相同的问题。以下代码将在“粘贴值”表中逐行组织这些行。除此之外,我还尝试按时间戳列按升序对列进行排序(这样来自google表单的新回复将显示在顶部) 第一个问题是,我的粘贴值表(A、O、p、Q、R、S)中有其他列不在表单表中。当一个新表单位于顶部时,这些列中的信息不会与它们应该位于的正确行一起移动;他们只是呆在原地 第二个问题是,如果我尝试添加表单提交触发器,以便每次提交新表单时,粘贴值表都会更新,那么这些行将从头到尾累积

这个问题是以下问题的继续:

我有一张“表单回复”表,用户最多可以填写5次相同的问题。以下代码将在“粘贴值”表中逐行组织这些行。除此之外,我还尝试按时间戳列按升序对列进行排序(这样来自google表单的新回复将显示在顶部)

第一个问题是,我的粘贴值表(A、O、p、Q、R、S)中有其他列不在表单表中。当一个新表单位于顶部时,这些列中的信息不会与它们应该位于的正确行一起移动;他们只是呆在原地

第二个问题是,如果我尝试添加表单提交触发器,以便每次提交新表单时,粘贴值表都会更新,那么这些行将从头到尾累积

例如,如果我有:
第1行
第2行
第3行

然后提交一个新表单,它将变成:
第1行
第2行
第3行
第1行
第2行
第3行
第4行

这会导致重复我不想要的行

我的最终目标是实现以下目标:

1) 每次有人提交一份新表格,答案都会排在第一位;在“表单响应”和“粘贴值”中,所有内容都按升序(按时间戳列)排序

2) 添加一个on-edit触发器,以便每次用户提交表单时,仅将新行添加到“粘贴值”中,而不是所有行重复一次又一次

3) 列:A、O、p、Q、R、S和T是我希望能够在“粘贴值”中自由编辑的列,这意味着每次向“粘贴值”添加新行时,这些列中的相应信息将随该行移动,并且不受编辑时触发器的影响

以下是google sheet示例:

表单响应表是google表单收到的数据。粘贴值“这是目标”表是我希望它成为的

行操作的代码:

function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var src = ss.getSheetByName("Form Responses");
  var dst = ss.getSheetByName("Paste Values");
  var values = src.getDataRange().getValues();
  var header = values.splice(0, 1)[0].splice(0, 13);
  var res = values.reduce(function(ar, e) {
    var h = e.splice(0, 3);
    h.unshift("");
    for (var i = 0; i < 5; i++) {
      var temp = e.splice(0, 10);
      if (temp.filter(String).length == 0) continue;
      if (temp.length < 10) temp.splice(temp.length, 10 - temp.length, "");
      ar.push(h.concat(temp));
    }
    return ar;
  }, []);
  if (dst.getRange("A1").getValue() != "Status") res.unshift(["Status"].concat(header));
  dst.getRange(dst.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
}
更新了将行操作实现为粘贴值(并从表单响应的每一行返回每一行(拆分它们)的尝试):


Tanaike的代码是一件艺术品,但我认为它是基于一个假设,即您只会运行脚本一次

你说过用户会填写谷歌表格。然后对其进行操作,以便将具有相同列的行传输到一列。但具有讽刺意味的是,您随后将其分解以生成“粘贴值”的结果

我建议一个远不那么复杂的过程:

  • 在收到任何表单响应之前,创建并安装“粘贴值”的标题
  • 编写一个作为
    OnFormSubmit'触发器手动安装的脚本。使用触发器返回的对象数据将相关数据复制到“粘贴值”的最后一行(加1)。您可以考虑调整表单,以便从下拉菜单中选择提交者的名称,以确保拼写一致。
  • 逐步排序“粘贴值”;也就是说,将代码添加到
    FormSubmit
    触发器
这使您能够在粘贴值上写入注释和其他注释,排序后这些注释和注释将与相关行保持对齐

代码

function so55716140_01(event) {
  // setup this function as an installable trigger OnFormSubmit

  // set up spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourcename = "Form Responses 2";
  var targetname = "Paste Values";
  var sourcesheet = ss.getSheetByName(sourcename);
  var targetsheet = ss.getSheetByName(targetname);

  // get the response data - assumes 10 questions plus timestamp
  var sourcerow = event.range.getRow();
  // Logger.log("DEBUG: Response row = "+sourcerow); //DEBUG
  var sourcerange = sourcesheet.getRange(sourcerow, 1, 1, 11);
  //Logger.log("DEBUG: Source range = "+sourcerange.getA1Notation()); //DEBUG
  var sourcedata = sourcerange.getValues();

  // setup the target
  var Bvals = targetsheet.getRange("B1:B").getValues();
  var Blast = Bvals.filter(String).length;
  //Logger.log("DEBUG: Blast = "+Blast); //DEBUG
  var targetrange = targetsheet.getRange(Blast + 1, 2, 1, 11);
  //Logger.log("DEBUG: Target range = "+targetrange.getA1Notation()); //DEBUG

  // paste the response to the target
  targetrange.setValues(sourcedata);

 // OP to add sort code according to preference
}

可能包含5个部分的表单的代码

function ejb_op3(event) {

  // setup this function as an installable trigger OnFormSubmit

  // set up spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourcename = "Form Responses 4";
  var targetname = "Paste Values";
  var sourcesheet = ss.getSheetByName(sourcename);
  var targetsheet = ss.getSheetByName(targetname);

  // get the response row and range
  var sourcerow = event.range.getRow();
  //Logger.log("DEBUG: Response row = "+sourcerow); //DEBUG

  // range is from Column A to Column AZ: 52 columns; 3=common; 4x10 (40) = printer "section" questions PLUS "do you want to submit another form"; the final (5th) 1x9 printer "section" questions; 3+40+9=52
  var sourcerange = sourcesheet.getRange(sourcerow, 1, 1, 52);
  //Logger.log("DEBUG: Source range = "+sourcerange.getA1Notation()); //DEBUG

  // get the response data
  var sourcedata = sourcerange.getValues();

  // find the number of rows already populated on the target
  var Bvals = targetsheet.getRange("B1:B").getValues();
  var Blast = Bvals.filter(String).length;
  //Logger.log("DEBUG: Blast = "+Blast); //DEBUG

  // establish some variables
  var datastart = 3; // the first 3 columns are common data
  var dataqty = 10; // the first 4 responses have 10 columns of response data
  var printcount = 0; // status counter
  var responsecount = 0; // column status counter
  var responsedata = []; // array to compile responses

  // process the first section
  if (printcount == 0) {
    responsedata = [];

    // get the timestamp, submitter name and email
    responsedata.push(sourcedata[0][0]);
    responsedata.push(sourcedata[0][1]);
    responsedata.push(sourcedata[0][2]);

    //get the responses for the next 10 questions
    for (i = datastart; i < (datastart + dataqty); i++) {
      responsedata.push(sourcedata[0][i]);
    }

    // define the target range
    // the last line (Blast)plus one line plus the print count; column B; 1 row; 13 columns
    var targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 13);
    // paste the values to the target
    targetrange.setValues([responsedata]);

    // update variables
    responsecount = i; // copy the value of i
    printcount++; // update status counter
    responsedata = []; // clear the array ready for the next section
  }
  // end opening response

  // build routine for 2nd to 4th sections
  for (z = 2; z < 5; z++) {

    //Make sure not to double count the first section
    if (printcount > 0 && printcount < 5) {

      // test if the next section exists
      if (sourcedata[0][i - 1] == "Yes") {
        // Yes for next section
        //Logger.log("DEBUG: value = "+sourcedata[0][i-1]);  //DEBUG

        // get the timestamp, submitter name and email
        responsedata.push(sourcedata[0][0]);
        responsedata.push(sourcedata[0][1]);
        responsedata.push(sourcedata[0][2]);

        //get the responses for the next 10 questions
        for (i = responsecount; i < (responsecount + dataqty); i++) {
          responsedata.push(sourcedata[0][i]);
          //Logger.log("DEBUG: data: "+sourcedata[0][i]);//DEBUG
        }

        // define the target range
        // the last line (Blast) plus one line plus the print count; column B; 1 row; 13 columns
        targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 13);
        // paste the values to the target
        targetrange.setValues([responsedata]);

        // update variables
        responsecount = i;
        printcount++;
        responsedata = [];
      } else {
        // NO for next section
      }
      // end routine if the next section exists
    } // end routine for the next section
  } // end routine for sections 2, 3 and 4

  // checking for 5th response
  if (printcount == 4) {

    // test if response exists
    if (sourcedata[0][i - 1] == "Yes") {
      // Yes for next section
      //Logger.log("DEBUG: value = "+sourcedata[0][i-1]);  //DEBUG

      // get the timestamp, submitter name and email
      responsedata.push(sourcedata[0][0]);
      responsedata.push(sourcedata[0][1]);
      responsedata.push(sourcedata[0][2]);

      //get the responses for the next 9 (nine) questions
      for (i = responsecount; i < (responsecount + dataqty - 1); i++) {
        responsedata.push(sourcedata[0][i]);
        //Logger.log("DEBUG: data: "+sourcedata[0][i]);//DEBUG
      }

      // define the target range
      // the last line (Blast) plus one line plus the print count; column B; 1 row; 12 columns only
      targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 12);
      // paste the values to the target
      targetrange.setValues([responsedata]);
    } else {
      // NO for next section
    }
  }
  // end routine for the 5th section


}
函数ejb_op3(事件){
//将此函数设置为可安装的触发器OnFormSubmit
//设置电子表格
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sourcename=“表单响应4”;
var targetname=“粘贴值”;
var sourcesheet=ss.getSheetByName(sourcename);
var targetsheet=ss.getSheetByName(targetname);
//获取响应行和范围
var sourcerow=event.range.getRow();
//Logger.log(“调试:响应行=“+sourcerow);//调试
//范围从A列到AZ列:52列;3=普通;4x10(40)=打印机“部分”问题加上“是否要提交另一份表格”;最后(第5)个1x9打印机“部分”问题;3+40+9=52
var sourcerange=sourcesheet.getRange(sourcerow,1,1,52);
//Logger.log(“调试:源范围=“+sourcerange.getA1Notation());//调试
//获取响应数据
var sourcedata=sourcerange.getValues();
//查找目标上已填充的行数
var Bvals=targetsheet.getRange(“B1:B”).getValues();
var Blast=Bvals.filter(String).length;
//Logger.log(“调试:Blast=“+Blast);//调试
//建立一些变量
var datastart=3;//前3列是公共数据
var dataqty=10;//前4个响应有10列响应数据
var printcount=0;//状态计数器
var responsecount=0;//列状态计数器
var responsedata=[];//用于编译响应的数组
//处理第一部分
如果(printcount==0){
响应数据=[];
//获取时间戳、提交人姓名和电子邮件
responsedata.push(sourcedata[0][0]);
responsedata.push(sourcedata[0][1]);
responsedata.push(sourcedata[0][2]);
//获取接下来10个问题的答案
对于(i=datastart;i<(datastart+dataqty);i++){
responsedata.push(源数据[0][i]);
}
//定义目标范围
//最后一行(Blast)加上一行加上打印计数;B列;1行;13列
var targetrange=targetsheet.getRange(Blast+1+printcount,2,1,13);
//将值粘贴到目标
targetrange.setValues([responsedata]);
//更新变量
responsecount=i;//复制i的值
printcount++;//更新状态计数器
responsedata=[];//清除数组以准备下一节
}
//端部开启响应
//第2至第4节的构建例程
对于(z=2;z<5;z++){
//一定不要把它弄脏
function so55716140_01(event) {
  // setup this function as an installable trigger OnFormSubmit

  // set up spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourcename = "Form Responses 2";
  var targetname = "Paste Values";
  var sourcesheet = ss.getSheetByName(sourcename);
  var targetsheet = ss.getSheetByName(targetname);

  // get the response data - assumes 10 questions plus timestamp
  var sourcerow = event.range.getRow();
  // Logger.log("DEBUG: Response row = "+sourcerow); //DEBUG
  var sourcerange = sourcesheet.getRange(sourcerow, 1, 1, 11);
  //Logger.log("DEBUG: Source range = "+sourcerange.getA1Notation()); //DEBUG
  var sourcedata = sourcerange.getValues();

  // setup the target
  var Bvals = targetsheet.getRange("B1:B").getValues();
  var Blast = Bvals.filter(String).length;
  //Logger.log("DEBUG: Blast = "+Blast); //DEBUG
  var targetrange = targetsheet.getRange(Blast + 1, 2, 1, 11);
  //Logger.log("DEBUG: Target range = "+targetrange.getA1Notation()); //DEBUG

  // paste the response to the target
  targetrange.setValues(sourcedata);

 // OP to add sort code according to preference
}
function ejb_op3(event) {

  // setup this function as an installable trigger OnFormSubmit

  // set up spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourcename = "Form Responses 4";
  var targetname = "Paste Values";
  var sourcesheet = ss.getSheetByName(sourcename);
  var targetsheet = ss.getSheetByName(targetname);

  // get the response row and range
  var sourcerow = event.range.getRow();
  //Logger.log("DEBUG: Response row = "+sourcerow); //DEBUG

  // range is from Column A to Column AZ: 52 columns; 3=common; 4x10 (40) = printer "section" questions PLUS "do you want to submit another form"; the final (5th) 1x9 printer "section" questions; 3+40+9=52
  var sourcerange = sourcesheet.getRange(sourcerow, 1, 1, 52);
  //Logger.log("DEBUG: Source range = "+sourcerange.getA1Notation()); //DEBUG

  // get the response data
  var sourcedata = sourcerange.getValues();

  // find the number of rows already populated on the target
  var Bvals = targetsheet.getRange("B1:B").getValues();
  var Blast = Bvals.filter(String).length;
  //Logger.log("DEBUG: Blast = "+Blast); //DEBUG

  // establish some variables
  var datastart = 3; // the first 3 columns are common data
  var dataqty = 10; // the first 4 responses have 10 columns of response data
  var printcount = 0; // status counter
  var responsecount = 0; // column status counter
  var responsedata = []; // array to compile responses

  // process the first section
  if (printcount == 0) {
    responsedata = [];

    // get the timestamp, submitter name and email
    responsedata.push(sourcedata[0][0]);
    responsedata.push(sourcedata[0][1]);
    responsedata.push(sourcedata[0][2]);

    //get the responses for the next 10 questions
    for (i = datastart; i < (datastart + dataqty); i++) {
      responsedata.push(sourcedata[0][i]);
    }

    // define the target range
    // the last line (Blast)plus one line plus the print count; column B; 1 row; 13 columns
    var targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 13);
    // paste the values to the target
    targetrange.setValues([responsedata]);

    // update variables
    responsecount = i; // copy the value of i
    printcount++; // update status counter
    responsedata = []; // clear the array ready for the next section
  }
  // end opening response

  // build routine for 2nd to 4th sections
  for (z = 2; z < 5; z++) {

    //Make sure not to double count the first section
    if (printcount > 0 && printcount < 5) {

      // test if the next section exists
      if (sourcedata[0][i - 1] == "Yes") {
        // Yes for next section
        //Logger.log("DEBUG: value = "+sourcedata[0][i-1]);  //DEBUG

        // get the timestamp, submitter name and email
        responsedata.push(sourcedata[0][0]);
        responsedata.push(sourcedata[0][1]);
        responsedata.push(sourcedata[0][2]);

        //get the responses for the next 10 questions
        for (i = responsecount; i < (responsecount + dataqty); i++) {
          responsedata.push(sourcedata[0][i]);
          //Logger.log("DEBUG: data: "+sourcedata[0][i]);//DEBUG
        }

        // define the target range
        // the last line (Blast) plus one line plus the print count; column B; 1 row; 13 columns
        targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 13);
        // paste the values to the target
        targetrange.setValues([responsedata]);

        // update variables
        responsecount = i;
        printcount++;
        responsedata = [];
      } else {
        // NO for next section
      }
      // end routine if the next section exists
    } // end routine for the next section
  } // end routine for sections 2, 3 and 4

  // checking for 5th response
  if (printcount == 4) {

    // test if response exists
    if (sourcedata[0][i - 1] == "Yes") {
      // Yes for next section
      //Logger.log("DEBUG: value = "+sourcedata[0][i-1]);  //DEBUG

      // get the timestamp, submitter name and email
      responsedata.push(sourcedata[0][0]);
      responsedata.push(sourcedata[0][1]);
      responsedata.push(sourcedata[0][2]);

      //get the responses for the next 9 (nine) questions
      for (i = responsecount; i < (responsecount + dataqty - 1); i++) {
        responsedata.push(sourcedata[0][i]);
        //Logger.log("DEBUG: data: "+sourcedata[0][i]);//DEBUG
      }

      // define the target range
      // the last line (Blast) plus one line plus the print count; column B; 1 row; 12 columns only
      targetrange = targetsheet.getRange(Blast + 1 + printcount, 2, 1, 12);
      // paste the values to the target
      targetrange.setValues([responsedata]);
    } else {
      // NO for next section
    }
  }
  // end routine for the 5th section


}