自动存档时间表;基于时间的触发

时间:2019-07-10 23:26:50

标签: google-apps-script google-sheets triggers archive schedule

我被要求创建一个实时的Google表格电子表格来跟踪我们船厂的工作时间表。我没有使用脚本的经验,但是发现我可以对我的工作表进行编程,而不是隐藏公式,这将产生更清晰的结果。我已经能够使工作表组织起来,并且能够手动将其存档(onEdit)。我正在寻找的是让它在凌晨1点自动运行代码,因此当我们开始工作时,它将根据特定列中的单元格值进行存档。

这是我的onEdit脚本有效的示例,但是当有人尝试检查“ YES”列时,会有些滞后,并且可能导致检查错误的单元格,然后我手动进行更正。

function onEdit() {
  var sheetNameToWatch = "Schedule";

  var columnNumberToWatch = 28;
  var valueToWatch = "Yes";
  var sheetNameToMoveTheRowTo = "Archive";

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getActiveCell();

  if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {

    var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
    var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
    sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange);
    sheet.deleteRow(range.getRow());
  }
}

因此,此代码在100%失败时运行,但是可以保存并执行,老实说,我不知道为什么。可能是我误解了需要在“功能”区域之后插入的值。我确实使用“自动存档”触发器进行了此设置,该触发器在工作表上创建了带有“运行”选项的菜单按钮,但是当您单击该按钮时,它仅在第28列中的最后一行带有“是”(每次按按钮将移动1行,直到所有行都被移动为止),并且该按钮对工作表的其他用户无效。

function createTrigger() {
  ScriptApp.newTrigger("Move Archive") //Move Archive is the name of the script
    .timeBased()
    .everyMinutes(1) // only set to 1 minute for testing, I can change this out for a daily timer
    .create();
}


function myFunction() {
  var sheetNameToWatch = "Schedule"; // "schedule" is the sheet we enter info on

  var columnNumberToWatch = 28; //Column is "AB"
  var valueToWatch = "Yes";
  var sheetNameToMoveTheRowTo = "Archive"; //"Archive is the sheet the info is sent to"

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getActiveCell();

  if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {

    var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
    var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
    sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange); // I get its programmed for last row with "Yes" here, unsure on how to change this.
    sheet.deleteRow(range.getRow());

    function myfunction() {
      ScriptApp.deleteTrigger("Move Archive"); // could have wrong value here

    }
  }
}

我想要做的是根据第28栏(AB)中的“是”值将表格“归档”。我希望具有该列值的每一行自动在凌晨1点存档。任何帮助表示赞赏。如果有人甚至想为初学者推荐一本书或数字指导,那就太好了。

2 个答案:

答案 0 :(得分:0)

您有四个项目文件,每个文件包含相同名称的脚本,执行相同或相似的任务。您遇到了滞后,因为您有多个同名的简单且可安装的脚本。本质上,它们都试图同时执行。

以下答案应被视为解决您情况的一种可能方法。

此脚本的元素是:

  • 只有一个项目文件。不必要的项目文件已删除。
  • 只有一个功能。
  • 该函数是单个“简单”触发器(onEdit(e)),它利用了onEdit返回的各种事件对象。没有可安装的触发器,并且已删除任何/所有可安装的触发器。
  • 该函数按照问题中的描述更新“计划”和“归档”表;然后对“计划”和“归档”表进行排序。
  • 如果“铁路车”表上有更改,该函数将对该表进行排序。

function onEdit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var testrange = e.range;
  var testsheet = testrange.getSheet();
  var testsheetname = testsheet.getSheetName();
  var testrow = testrange.getRow();
  var testcolumn = testrange.getColumn();
  var testvalue = e.value;
  var testsheetLC = testsheet.getLastColumn();
  var testsheetRange = testsheet.getRange(testrow,1,1,testsheetLC);
  //Logger.log("DEBUG: the test sheet range is "+testsheetRange.getA1Notation()); 
  //Logger.log("DEBUG: Range: "+testrange.getA1Notation());
  //Logger.log("DEBUG: The row is "+testrow+", and the column is "+testcolumn);
  //Logger.log("DEBUG: The spreadheetsheet is "+e.source.getName()+", the sheet name is  "+testsheet+", the range = "+testrange.getA1Notation()+", and the new value = "+testvalue);
  //Logger.log(JSON.stringify(e));

  // Copy/Paste to Schedule/Archive
  var sheetNameSchedule = "Schedule";
  var colNumberSchedule = 28;
  var valueSchedule = "Yes";
  var sheetNameArchive = "Archive";

  // Sort Schedule
  var sortSchedule = [{column: 1, ascending: true},{column: 2, ascending: true},{column: 7, ascending: false}];// date // Appt (time) // Type (Out/In/RR)
  // Sort Railcars
  var sheetNameRailcars = "Railcars";
  var sortRailcars = [{column: 1, ascending: true}];

  if (testsheetname === sheetNameSchedule && testcolumn === colNumberSchedule && testvalue === valueSchedule){
    // this is a match
    // Logger.log("DEBUG: this was a match");

    // copy/paste to archive
    var targetSheet = ss.getSheetByName(sheetNameArchive);
    var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
    //Logger.log("DEBUG: the target range is "+targetRange.getA1Notation());
    testsheetRange.moveTo(targetRange);
    testsheet.deleteRow(testrow);

    // sort the Schedule Sheet
    var Avals = testsheet.getRange("A1:A").getValues();
    var Alast = Avals.filter(String).length;
    //Logger.log("DEBUG: The last row of content (in column A) = "+Alast+", and the last column = "+testsheetLC);
    var sortrange = testsheet.getRange(2,1,Alast-1,testsheetLC);
    //Logger.log("DEBUG: the sort range = "+sortrange.getA1Notation());
    sortrange.sort(sortSchedule);

    // sort the Archive Sheet
    var ATvals = targetSheet.getRange("A1:A").getValues();
    var ATlast = ATvals.filter(String).length;
    //Logger.log("DEBUG: The last row of content (in column A) = "+ATlast+", and the last column = "+testsheetLC);
    var sortrange = targetSheet.getRange(2,1,ATlast-1,testsheetLC);
    //Logger.log("DEBUG: the sort range = "+sortrange.getA1Notation());
    sortrange.sort(sortSchedule);
  }
  else if (testsheetname === sheetNameRailcars){

    // sort the sheet
    var Avals = testsheet.getRange("A1:A").getValues();
    var Alast = Avals.filter(String).length;
    //Logger.log("DEBUG: The last row of content (in column A) = "+Alast+", and the last column = "+testsheetLC);
    var sortrange = testsheet.getRange(2,1,Alast-1,testsheetLC);
    //Logger.log("DEBUG: the sort range = "+sortrange.getA1Notation());
    sortrange.sort(sortRailcars);
  } 

}

答案 1 :(得分:0)

您可以设置一个可安装的触发器以每天早上1点运行此功能:

function scheduleToArchive() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var schedule = sheet.getSheetByName("Schedule");
  var archive = sheet.getSheetByName("Archive");
  var scheduleData = schedule.getRange(2, 1, (sheet.getRange('A:A').getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow()), 28);

  for (row = 2; row <= scheduleData.getNumRows(); row++){
    var data = schedule.getRange(row, 1, 1, 28).getValues();

    if (data[0][27] == 'Yes'){
     archive.getRange((archive.getLastRow() + 1), 1, 1, 28).setValues(data);
    }    
    schedule.getRange(row, 1, 1, 28).clear();
  }  
}

在电子表格中,当getDataRange()在名为“ Schedule”的工作表上运行时,即使前20行中只有数据,它也会将行631作为最后一行返回数据。我改用SpreadsheetApp.Direction.DOWN并在A列上运行它。