是否可以编写脚本以根据该行中的日期复制,粘贴和删除整个行? (Google表格)

时间:2019-07-18 18:44:09

标签: javascript google-sheets

某些背景:我们有一个共享的Google表格来跟踪我们在电影院的开幕,放映和其他活动。我们有一个主选项卡(“主”),其中包含我们所有的事件以及与之相关的详细信息,还有一个用于存档的选项卡(“存档”)。

我想在Google表格中编写一个脚本,以根据日期(在E列中)检测昨天和更早的事件和放映,选择符合该条件的整行(事件),并将其粘贴到单独的“存档”标签,然后从“主”标签中删除行。

任何指向我正确方向的建议都会很有帮助。我发现了一些与此类似的响应,但它们特定于Excel / VBA,对此我并不熟悉(或者很多Javascript)。

2 个答案:

答案 0 :(得分:0)

我建议您做一些教程以熟悉如何编写脚本。

在这个答案中,我将充实您的代码需要解决的步骤。您会在相同或相似的问题上找到许多现有的主题。这仅仅是为了使您能够更好地搜索所需的代码元素。考虑到这可能只是实现结果的一种方法。

  1. 您有一个包含两张工作表的电子表格,您将在不同阶段引用这两张工作表。 getSheetByName(name)将使您能够为工作表创建可重复使用的变量。
  2. 您将需要在每张纸的底部找到一行。 getLastRow()会有所帮助。
  3. 您要在“主”中查找日期行,因此需要获取“主”的所有值。
    您将从定义范围开始-使用getRange(row, column, numRows, numColumns),尽管这只是定义范围的5种方法之一。
  4. 已定义范围,您将需要“主”中的值,以便您可以访问日期字段。将getValues()与定义的范围结合使用。 FWIW,请注意这是如何复数的,因为其中有很多值。如果只需要一个单元格,则可以使用getValue()
  5. 您将要遍历“主”中的行,并找到日期在今天之前的那些行。 “删除电子表格中的重复行”教程显示了一种循环方式,您可以阅读基本的JavaScript“循环和迭代”。

    在您的情况下,有一个循环的“障碍物”。如果采用“通常”过程,则将从第一行循环到最后一行。但是,您正在从“母版”中删除一行,并且随着每一行的删除,其余行的行号将/可能会更改;因此“常规”流程将无法执行。您需要做的两件事:第一)从范围的底部开始循环;这将确保其余行的行号永远不会改变;第二)对数据进行排序,以使最早的日期位于底部。所以...现在,您将从下往上循环,您将评估所有最旧的日期,而不会遇到当日期大于“今天”的任何风险时,不再会有日期更少的行的风险比“今天”。当然,代码完成后,您随时可以将“主”上的数据重新排序为所需的任何顺序。

  6. 您需要将“主”行中的日期与今天的日期进行比较,然后构建一个if...else语句,以便您可以根据结果定义要执行的操作。比较日期有时说起来容易做起来难。此主题与Checking if one date is greater than the other using Google Script相关,您可以在其他主题上搜索“ Google Sheets脚本日期比较”。
  7. 找到比今天短的日期时,您想要将该行的详细信息复制到“存档”。这是一个分为两部分的过程,首先是从“主”上的行那里收集数据,其次是将数据“复制”到“存档”。教程中将介绍如何收集数据。有很多选项可用于将数据复制到“存档”。您可以追加一行并使用setValues更新新值。另一种方法是累积其他“归档”数据,并在循环完成后将其添加到“归档”中。
  8. 当您发现一个比今天少的日期时,您想从“主”中删除该行。为此,有一个命令:deleteRow(rowPosition)
  9. 您可以按需手动处理功能,也可以选择将其自动化为时间驱动的可安装触发器。该选项是您的。

可以通过多种方式组合这些元素。 在准备上面的摘要时,我必须确保提供准确而完整的建议。因此,以下只是实现目标的一种方法。应该注意的是,我的测试数据假设A列和C列的格式分别为日期和时间。


 function so5710086103() {

  // set up spreadsheet and sheets
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var master = ss.getSheetByName("Master");
  var archive = ss.getSheetByName("Archive");

  // get the last row and column of Master
  var masterLR = master.getLastRow();
  var masterLC = master.getLastColumn();
  // get the last row and column of Archive
  var archiveLR = archive.getLastRow();
  var archiveLC = archive.getLastColumn();
  //Logger.log("DEBUG: Last Row - Master = "+masterLR+", and Archive = "+archiveLR);
  //Logger.log("DEBUG: Last Column - Master = "+masterLC+", and Archive = "+archiveLC);

  // create a range, sort it and get the data from "Master"
  var masterRange = master.getRange(2, 1, masterLR - 1, masterLC);
  // sort master based on date
  masterRange.sort({
    column: 1,
    ascending: false
  });
  // Logger.log("DEBUG: Master range = "+masterRange.getA1Notation());
  var masterData = masterRange.getValues();
  //Logger.log("DEBUG: Length of Master data = "+masterData.length);

  // create a range and get the data from "Archive"
  var archiveRange = archive.getRange(1, 1, archiveLR, archiveLC);
  var archiveData = archiveRange.getValues();

  // create a formatted date for today
  var formattedToday = Utilities.formatDate(new(Date), 'GMT+10',
    'dd MMMM yyyy');

  // loop through the rows
  // from bottom to top
  for (var i = (+masterLR - 2); i > 0; i--) {

    // convert cell dates to comparable format
    var DBdate = Utilities.formatDate(masterData[i][0], 'GMT+10',
      'dd MMMM yyyy');
    var DBtime = Utilities.formatDate(masterData[i][2], 'GMT+10',
      'hh:mm a');
    //Logger.log("DEBUG: i = "+i+", DBdate = "+DBdate+", Today = "+formattedToday);

    // clear the temporary row array
    var archivecells = [];

    if (DBdate < formattedToday) {

      // the table date is less than today, so archive the data
      // Logger.log("DEBUG: i = "+i+", DBdate = "+DBdate+", Today = "+formattedToday+" - DB value is less than Today. ACTION: Archive this row");

      // copy the row cells to temporary row array
      archivecells.push(DBdate);
      archivecells.push(masterData[i][1]);
      archivecells.push(DBtime);
      archivecells.push(masterData[i][3]);
      archivecells.push(masterData[i][4]);

      // copy the temporary row array to archivedata
      archiveData.push(archivecells);

      // delete the Master Row
      master.deleteRow(i + 2);

    } else {
      // the table date is NOT less than today, so do nothing
      // Logger.log("DEBUG: i = "+i+", DBdate = "+DBdate+", Today = "+formattedToday+" - DB value is NOT less than Today. ACTION: Do nothing");
    }

    // update the accumulated data to Archive.  
    archive.getRange(1, 1, archiveData.length, archiveLC).setValues(
      archiveData);

  }
}


主-之前
Master - before


大师-之后
Master-after


存档-之后
Archive - after

答案 1 :(得分:0)

嗨,这真的很有用,但是运行脚本时却出现错误

  

该范围内的行数必须至少为1。(第29行,文件“代码”)

该代码为25[0-5]

您能帮我吗?