-3

Some background: We have a shared Google Sheet to track our openings, screenings, and other events at a movie theater. We have a main tab ("Master") that contains all of our events and the details that go with them, and a tab for archiving ("Archive").

I would like to write a script within Google Sheets to detect events & screenings that are from yesterday and earlier based on the date (in column E), take the full row(s) (events) that meet that criteria, copy & paste them to the separate "Archive" tab, and then delete the row(s) from the "Master" tab.

Anything to point me in the right direction would be super helpful. I found a few similar responses to this but they're specific to Excel/VBA and I'm not familiar with that (or much Javascript, for that matter).

W M
  • 7
  • 2
  • Yes, it's possible. However Stack Overflow is not the right place to ask this question. Find a sample script online and try to adapt it for your purpose, then post here if you're really stuck with any errors/issues you may be having. – ross Jul 18 '19 at 20:00
  • Welcome. A clarification: Apps Script is NOT strict JavaScript - it is _based_ on JavaScript [Basic JavaScript features](https://developers.google.com/apps-script/guides/services/#basic_javascript_features), sigh. Even if your script miraculously appeared-you wouldn't know what to do with it. I suggest that you do some tutorials to get a handle on how things work. Try [Your First Script](https://developers.google.com/apps-script/overview#your_first_script) and [Removing Duplicate Rows in a Spreadsheet](https://developers.google.com/apps-script/articles/removing_duplicates). – Tedinoz Jul 20 '19 at 03:39

1 Answers1

0

I suggested that you do some tutorials to familiarise yourself with how to write scripts.

In this answer, I will flesh out the steps that your code needs to address. You will find many existing topics on the same or similar question. This is merely in order to enable you to better search for the elements of code that you need. Consider that this may be just one way of achieving your outcome.

  1. You have one spreadsheet with two sheets and you will refer to both sheets at different stages. getSheetByName(name) will enable you to create a re-usable variable for a sheet.

  2. You will need to find the bottom row in each sheet. getLastRow() will help.

  3. You want to find rows in "Master" for dates, so you need to get ALL values for "Master".
    You'll start by defining the range - use getRange(row, column, numRows, numColumns), though this is just one of 5 ways to define a range.

  4. Having defined the range you'll need the values in "Master" so that you can access the date field. Use getValues() in conjunction with the range that defined. FWIW, note how this is in plural because there are lots of values. If you just wanted a single cell, you'd use getValue().

  5. You'll want to loop through the rows in "Master" and find those rows that have a date prior to today. The "Removing Duplicate Rows in a Spreadsheet" tutorial shows one way of looping, and you can read up on basic JavaScript "Loops and iteration".

    In your scenario, there is a 'hitch' with looping. If one adopts the "usual" process, then one will loop from the first row to the last. However, you are deleting a row from "Master" and, as each row is deleted, the row numbers of the remaining rows will/may change; so the "usual" process won't do. What you need to do is two things: first) loop from the bottom of the range; this will ensure that the row numbers of remaining rows will never change; second) sort the data so that the oldest dates are at the bottom. So... now you will loop from the bottom to the top, and you will evaluate all the oldest dates without any risk that when you encounter a date greater than "today", there will be NO risk of further rows with a date less than "today". Of course, once the code is complete, you can always re-sort the data on "Master" back to any order that you might wish.

  6. You need to compare the date in the row in "Master" with today's date and then build a if...else statement so that you can define what to do depending on the result. Comparing dates is sometimes easier said than done. This topic is relevant Checking if one date is greater than the other using Google Script and you can search on other topics for "Google Sheets Script date comparison".

  7. When you find a date less than today, you want to copy the details of that row to "Archive". This is a two part process first) to gather there the data from the row on "Master", and second) to "copy" that data to "Archive". Gathering the data will have been covered in the tutorials. There are many options for copying the data to "Archive". You could append a row and use setValues to update the new values. An alternative is to accumulate the additional "Archive" data and add it to the "Archive" after the loops have been completed.

  8. When you find a date less than today, you want to delete the row from "Master". There's a command for that: deleteRow(rowPosition).

  9. You can process your function manually, on demand, or you may prefer it to be automated as a time-driven installable trigger. The option is yours.

There are many ways that you can combine these elements. In preparing the summary above, I had to make sure that I was providing accurate and complete advice. So the following is but one approach to achieving your goal. It should be noted that my test data assumes that columns A and C are formatted for date and time respectively.


 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 - before


Master - After
Master-after


Archive - After
Archive - after

Community
  • 1
  • 1
Tedinoz
  • 5,911
  • 3
  • 25
  • 35
  • This is fantastic. I have done a decent amount of writing scripts specifically for Sheets and was getting hung up on the `if...else` aspect. I'm going to study each of those links and really try to avoid asking someone to write my code for me, but I sincerely appreciate all of the effort you put forward on this. Thank you. – W M Jul 21 '19 at 16:18