0

trying to get some help on overwriting some existing data using scripts, and using dynamic column headers. Appreciate the help as I think this is above my experience level at the moment.

Desired outcome:

I would like to change (as in the example below) any cells in column A that are currently set to "Before" to say "AFTER" (in all caps) if Date 1 is after Date 3, and highlight them. I also do not want to change any data in column A if they do not meet this criteria, which means if a cell in column A already says "After" it can remain as is.

I think I can figure out the highlight coding portion, but it's the first part I'm getting stuck on.

My current issue is that I'm finding it difficult to reference column headers for this script, as I need to do this because the headers can be in different columns, so relying on a constant reference to a specific column is not possible. This is also making me confused on how to do the .setValues for this as well since it's going through the entire column potentially.

What I've tried so far:

  1. Attempted to utilize the code in reference 1 below to work for this, but it's overwriting all cells instead of just the cells that are affected
  2. Not sure if I should make functions within a function and use the createTextFinder to find these headers? This seems wrong because I can only use it once and I have 3 columns I need to find
  3. Tried to utilize some scripts that change columns to letters but I'm unsure how to utilize them properly

My Code: And yes, it doesn't work, but this is my best attempt to set it up:

function changeBefore() {

  const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
  const tf = ss.createTextFinder('Before').matchEntireCell(true).matchCase(false);
  const beforeCell = tf.findNext()

  var date1Range = date1.getRange()
  var date3Range = date3.getRange()
  var bacRange = beforeorAfterColumn.getRange()

  if (bacRange=='Before'==date1Range>date3Range){
    beforeorAfterColumn.getRange().setValues('AFTER');

  }//end of if


  function beforeorAfterColumn(){
  var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getDataRange().getValues().shift();
  var colindex = headers.indexOf('Before or After');
  return colindex+1 //to get column index as # value used this code via question/author (https://stackoverflow.com/questions/31214352/how-to-use-a-column-header-to-reference-a-cell-in-google-apps-script-spreadsheet) @Serge inas

  function date1(){
  var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getDataRange().getValues().shift();
  var colindex = headers.indexOf('Date 1');
  return colindex+1

  function date3(){
  var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getDataRange().getValues().shift();
  var colindex = headers.indexOf('Date 3');
  return colindex+1
      }//end of date 3 function
    }//end of date1 function
  }//end of beforeorAfterColumn function
}//end of changeBefore function

Example of current sheet:

enter image description here

Desired outcome of script:

enter image description here

Resources/References:

  1. Using column headers as a reference
  2. Using column headers R1C1
  3. Using whenTextContains to reference via google developers

Raw Data as requested:

Before or After Data 2 Date 1 Date 2 Date 3
Before 6/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 6/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
After 7/1/21 4/1/21
Before 6/1/21 4/1/21
After 7/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
Before 1/1/21 4/1/21
User1938985
  • 127
  • 8
  • For the time you spent for this task and putting together a question, you could've learnt JavaScript arrays and attempted writing a script yourself(instead of putting together samples from SO). See [tag info page](https://stackoverflow.com/tags/google-apps-script/info) for MDN js arrays, if you're interested. So, you would get both arrays and compare each of date by looping through and create a third array with BEFORE/AFTER. – TheMaster Nov 23 '21 at 19:55
  • OK thanks, I honestly didn't know where to start, I just had an idea it was something with changing what I have into something else to get some data from. I'll look into arrays – User1938985 Nov 23 '21 at 20:00

1 Answers1

1

I think this will give you an example that you can build from. It compares Date 1 and Date 3 and changes the value based up whether Date 1 is before or after Date 3 and what the current value of Before or After is.

function beforeOrAfter() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  const [hA,...vs] = sh.getDataRange().getValues();
  let idx = {};
  hA.forEach((h,i) => {idx[h]=i;});
  vs.forEach((r,i) => {
    let d1 = new Date(r[idx['Date 1']]).valueOf();
    let d3 = new Date(r[idx['Date 3']]).valueOf();
    let ba = r[idx['Before or After']];
    if(d1 > d3 && ba != 'After') {
      sh.getRange(i+2,idx['Before or After'] + 1).setValue("AFTER").setBackground('#ffff00');
    }
    if(d1 < d3 && ba != 'Before') {
      sh.getRange(i+2,idx['Before or After'] + 1).setValue("BEFORE").setBackground('#ffff00');
    }
  });
}

I ran the code on your table and this is the result:

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
Cooper
  • 59,616
  • 6
  • 23
  • 54
  • Really appreciate the quick response/help. I tried this script initially (changing Sheet0 to Sheet1) and it doesn't appear to change anything on the sheet, but it does run without error. I'll do some more testing and review though. Via Masters suggestion I'm going to read up on arrays as well, see if I can make my question more concise? – User1938985 Nov 23 '21 at 20:47
  • Please provide data that I can cut and paste and I'll get the code to run – Cooper Nov 23 '21 at 20:49
  • provided a table as an edit, thanks! – User1938985 Nov 23 '21 at 21:10
  • I tried it on a new tab and it worked! I'll have to research your answer a bit more here to fully understand, but this is very useful thank you! – User1938985 Nov 23 '21 at 21:29
  • Just for my better understanding, what is: ((h,i) => {idx[h]=i;}); ? It looks like idx is a empty method (may not be the correct word)? But are h, and i, just variables to stand in (I thought i was a variable in script)? Because const [hA,...vs] = sh.getDataRange().getValues(); makes sense to make (sorta), that you made an array but what is [hA,...vs] I've never seen that before. – User1938985 Nov 23 '21 at 21:39
  • 1
    idx[h] provides the index into the row array for each column header – Cooper Nov 24 '21 at 01:01
  • 1
    The [hA,...vs] is an array literal assignment that assigned the hA to the header array and the rest of the data to vs. You can learn more about it in books on ECMAScript 2015 or ES6 – Cooper Nov 24 '21 at 01:03