1

I have a code that is half working, the last thing I can't figure out is how to find an array item containing a number (eg 123) and some text (m/s) and replace this whole item with a completely blank array item: []. No number and no m/s.

I am not familiar with most of the terminology and am a complete novice at this. This is what I've got so far:

function condForm() {
  var sh = ss.getSheetByName('Sheet1');
  var range = sh.getRange("D4:D20"); //*** for the sake of brevity setting to 20 instead of 154
  var values = range.getValues();  
  var row = [];
  var cols = values[0].length;

  for (var i = 0, l = values.length; i < l; i++)
  {
    row = values[i];
    for (var j = 0; j < cols; j++)
    {
      if (row[j] === 'TTK') { row[j] = ''; }
      if(typeof row[j] != "string") { continue; } // line to allow indexOf to work
      if (row[j].indexOf('m/s') > -1) { var newValue = row[j].replace('m/s', '') } //attempting to use indexOf to search for partial match to m/s, does not work but does not return error
    }
  }
Logger.log(values);
}

Without code the logger outputs [[400.0], [600.0], [600.0], [600.0], [], [1283 m/s], [TTK], [440.0], [661.0], [771.0], [771.0], [], [960m/s], [TTK], [381.0], [667.0], [667.0]]

And with the code above the output becomes [[400.0], [600.0], [600.0], [600.0], [], [1283m/s], [], [440.0], [661.0], [771.0], [771.0], [], [960m/s], [], [381.0], [667.0], [667.0]] = same number of array items = great success

I attempted to use indexOf to search for any array items containing m/s. It didn't work but also didn't return an error. What's it doing? Am I on the right lines at all?

I would like a way to turn [1283m/s] and [960m/s] into blanks: [].

Thank you for reading.

My code was sourced from Max Makhrov: https://stackoverflow.com/a/47575871/1341041

and from Andres Duarte: https://stackoverflow.com/a/60226151/1341041

1 Answers1

2

As far as I can tell you're changing the array row. But you're never changing the array values.

Probably you need something like this in the middle:

...

if (row[j] === 'TTK') { values[i][j] = ''; }
if (typeof row[j] != "string") { continue; }
if (row[j].indexOf('m/s') > -1) { values[i][j] = row[j].replace('m/s', '') }

...

But actually for your purpose I'd propose to use the native tool TextFinder:

function condForm() {
  const sheet = ss.getSheetByName('Sheet1');
  const range = sheet.getRange('D4:D20');
  // range.createTextFinder('m/s').replaceAllWith('');
  range.createTextFinder('.*m/s.*').useRegularExpression(true).replaceAllWith('');
  range.createTextFinder('^TTK$').useRegularExpression(true).replaceAllWith('');
}

https://developers.google.com/apps-script/reference/spreadsheet/text-finder

Just in case, if you really into the nested loops it as well can be done a bit cleaner this way:

var values = [[400], [600], [600], [600], [], ['1283 m/s'], ['TTK'], [440], [661], [771], [771], [], ['960m/s'], ['TTK'], [381], [667], [667]];

for (row in values) {
  for (col in values[row]) {
    if (values[row][col] == 'TTK') values[row][col] = '';
    // values[row][col] = values[row][col].toString().replace(/\s*m\/s/g,'');
    values[row][col] = values[row][col].toString().replace(/.*m\/s.*/,'');
  }
}

console.log(values);
Yuri Khristich
  • 13,448
  • 2
  • 8
  • 23
  • Thanks Yuri, I ended up using the bottom solution. I couldn't work out how to log the array with the 2nd function which does look a lot cleaner. Also weirdly it was telling me that getSheetByName wasn't a function but I implemented with your last solution and it was fine?? Thanks again, great code! – patwick600akabob Aug 22 '21 at 17:51
  • 1
    Oops. My bad. It was the typo. There should be `ss` instead of `SpreadsheetApp` --> `const sheet = ss.getSheetByName('Sheet1');` – Yuri Khristich Aug 22 '21 at 17:54
  • Ah I see, I still couldn't get the text-finder to log the array. Is it much better to use it instead of the nested loop? Which is working perfect by the way. My next plan is to apply Math.max to get the highest number and then I want to implement dynamic ranges, probably using coordinate syntax instead of cell references. – patwick600akabob Aug 22 '21 at 18:34
  • really sorry, I overlooked something that the number is still there from the items that contained m/s. I'd like to get rid of the number as well as the m/s. I might not have made that completely clear in my question. – patwick600akabob Aug 22 '21 at 19:15
  • 1
    If you want to delete all texts that contain "m/s" all you need is just to tweak the regex. Replace `range.createTextFinder('m/s').replaceAllWith('');` with `range.createTextFinder(".*m/s.*").useRegularExpression(true).replaceAllWith('');` in textFinder example. Or replace `replace(/\s*m\/s/g,'');` with `replace(/.*m\/s.*/,'');` in the nested loops example. – Yuri Khristich Aug 22 '21 at 21:50
  • 1
    As for what is better "textFinder" or to loop through the plain JS arrays -- it's up to you. "TextFinder" doesn't give you the array, you will need to use `range.getValues()` after. So the both ways are about the same after all, in your case. – Yuri Khristich Aug 22 '21 at 21:57