google-sheetsgoogle-apps-scripttriggersgoogle-workspace

Archive a row after a dropdown status is selected on multiple sheets


I have a file with three sheets. On all three sheets, when a certain dropdown selection is changed to "Cleared" I want the script to copy that row of data over into a hidden archive sheet and then clear that row on the main sheet.

I had this working when it was just one sheet that it was watching and archiving. But I can't get the code to work right for three different sheets that I want archived to three separate hidden archived sheets.

When I clear an item on one sheet, it is grabbing that row and rows from other sheets and archiving those rows even though I haven't selected those as "Cleared". I know something is messed up in my code but I don't know how to fix it.

Here is the current code:

function onChange(e) {
  // Define the relevant sheets and columns 
  var mainSheet = e.source.getSheetByName("Individual Licenses");    
  var archiveSheet = e.source.getSheetByName("Individual Archive"); 
  var columnToWatch = 10; 
  var secondSheet = e.source.getSheetByName("Branch Licenses"); 
  var archivebranchSheet = e.source.getSheetByName("Branch Archive"); 
  var columnToWatch = 10; 
  var thirdSheet = e.source.getSheetByName("Company Licenses"); 
  var archivecompanySheet = e.source.getSheetByName("Company Archive"); 
  var columnToWatch = 10; 
// Column J (0-based index)

  // Get the edited range 
  var editedIRange = e.range;
  var editedBRange = e.range;
  var editedCRange = e.range;

  // Check if the edited cell is in the "Milestone" column 
  if (editedIRange.getColumn() == columnToWatch) { 
      // Check if the status is "Cleared" 
      if (e.value == "Cleared") { 
      // Get the entire row of the edited cell 
      var rowData = mainSheet.getRange(editedIRange.getRow(), 1, 1, mainSheet.getLastColumn()).getValues()[0];

      // Find the first empty row in the Archive sheet 
      var archiveFirstEmptyRow = archiveSheet.getLastRow() + 1;

      // Copy the row data to the Archive sheet 
      archiveSheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);

      // Delete the row in the Main Data sheet 
      mainSheet.deleteRow(editedIRange.getRow()); 
      } 
    } 

  if (editedBRange.getColumn() == columnToWatch) { 
      // Check if the status is "Cleared" 
      if (e.value == "Cleared") { 
      // Get the entire row of the edited cell 
      var rowData = secondSheet.getRange(editedBRange.getRow(), 1, 1, secondSheet.getLastColumn()).getValues()[0];

      // Find the first empty row in the Archive sheet 
      var archiveFirstEmptyRow = archivebranchSheet.getLastRow() + 1;

      // Copy the row data to the Archive sheet 
      archivebranchSheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);

      // Delete the row in the Main Data sheet 
      secondSheet.deleteRow(editedBRange.getRow()); 
      } 
    } 

  if (editedCRange.getColumn() == columnToWatch) { 
      // Check if the status is "Cleared" 
      if (e.value == "Cleared") { 
      // Get the entire row of the edited cell 
      var rowData = thirdSheet.getRange(editedCRange.getRow(), 1, 1, thirdSheet.getLastColumn()).getValues()[0];

      // Find the first empty row in the Archive sheet 
      var archiveFirstEmptyRow = archivecompanySheet.getLastRow() + 1;

      // Copy the row data to the Archive sheet 
      archivecompanySheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);

      // Delete the row in the Main Data sheet 
      thirdSheet.deleteRow(editedCRange.getRow()); 
      } 
    } 
}

Solution

  • The reason why When I clear an item on one sheet, it is grabbing that row and rows from other sheets and archiving those rows even though I haven't selected those as "Cleared". is due to the if statements checking if what was edited was Column J and set to Cleared. This would mean that regardless of what sheet you're editing, the other sheets would do the same and what you described.

    Here's a modified version of your script that should achieve what you'd like:

    // Function name from "onChange(e)" to "onEdit(e)"
    function onEdit(e) {
      // Declared variable so that "e.source" doesn't need to be repeated for the sheet names
      var sr = e.source;
      var mainSheet = sr.getSheetByName("Individual Licenses");
      var archiveSheet = sr.getSheetByName("Individual Archive");
      var secondSheet = sr.getSheetByName("Branch Licenses");
      var archivebranchSheet = sr.getSheetByName("Branch Archive");
      var thirdSheet = sr.getSheetByName("Company Licenses");
      var archivecompanySheet = sr.getSheetByName("Company Archive");
      var columnToWatch = 10;
      var editedRange = e.range;
      // Gets the sheet of the edited range
      var ss = editedRange.getSheet();
      // Gets the sheet name of the edited range
      var sh = ss.getName();
      if (sh == mainSheet.getName() || sh == secondSheet.getName() || sh == thirdSheet.getName()) {
        if (editedRange.getColumn() == columnToWatch && e.value == "Cleared") {
          var rowData = ss.getRange(editedRange.getRow(), 1, 1, ss.getLastColumn()).getValues()[0];
          if (sh == mainSheet.getName()) {
            var archiveFirstEmptyRow = archiveSheet.getLastRow() + 1;
            archiveSheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);
          } else if (sh == secondSheet.getName()) {
            var archiveFirstEmptyRow = archivebranchSheet.getLastRow() + 1;
            archivebranchSheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);
          } else if (sh == thirdSheet.getName()) {
            var archiveFirstEmptyRow = archivecompanySheet.getLastRow() + 1;
            archivecompanySheet.getRange(archiveFirstEmptyRow, 1, 1, rowData.length).setValues([rowData]);
          }
          ss.deleteRow(editedRange.getRow());
        }
      }
    }
    

    Note: I've removed the other var columnToWatch = 10; since they're all the same as well as combined var editedIRange = e.range; var editedBRange = e.range;, and var editedCRange = e.range; as var editedRange = e.range;.

    OUTPUT

    OUTPUT

    REFERENCE