简体   繁体   中英

Google Sheets script: return value if substring is within another column

I'm new (read: literally just looking at JS for the first time now) to Javascript/Sheets/scripts in general, so forgive me for how basic this is. I've done a lot of independent research with no luck.

I have a spreadsheet with a column for full name (all caps - LAST, FIRST format), split into two additional columns of LAST and FIRST (full name split via comma), and then a lower caps column that contains the full name of the person in First Last format.

There are some errors in the data - for instance, LAST, FIRST might be followed by First Last that is a totally different name, or an incorrect spelling of the prior column. I'm basically trying to flag it when there is a mismatch in the contents, either spelling-wise or the name overall.

I've written this simple script that pulls the first name (column D) and the full name in First Last format (column F) and checks whether the first name is contained in the full name. Supposedly, it should return the value of search() in column G. That way I can use conditional formatting to flag any #VALUE, that appears from a failed search. indicating that the row needs to be checked.

Unfortunately the script runs infinitely and I can't figure out why I'm unable to hit a break point and actually return values in the corresponding columns in the actual sheet. This is a tiny project and I am struggling to justify learning the interface between scripts and Sheets from scratch, so I would really appreciate some help! Thank you!

   function checkName() {
      var s = SpreadsheetApp.getActiveSheet();
      var data = s.getDataRange().getValues();
      var data_len = data.length;
      for(var i=6; i<data_len; i++) {
        var fname = SpreadsheetApp.getActiveSheet().getRange(i, 4).getValue();
        var fullname = SpreadsheetApp.getActiveSheet().getRange(i, 6).getValue();
        s.getRange(i, 7).setValue(fullname.includes(fname));    
      }
    }

Here's how I'd write a function to meet your requirements:

function checkName() {

  // these two will be used in an Array,
  // which is 0-indexed
  const FIRST_NAME_COLUMN = 3; 
  const FULL_NAME_COLUMN = 5;

  // these two will be used in a Sheets range,
  // which is 1-indexed
  const INCLUDES_COLUMN = 7;
  const FIRST_ROW = 6;

  const s = SpreadsheetApp.getActiveSheet();
  const sheetDataRange = s.getDataRange(); // this is just the whole shebang

  // get the dimensions of the main range
  const RANGE_HEIGHT = sheetDataRange.getHeight();
  const RANGE_WIDTH = sheetDataRange.getWidth();
  
  // use your first row number to constrain the actual data range
  // we'll use this reference to create an array we can easily iterate over
  const dataRange = s.getRange( FIRST_ROW, 1, RANGE_HEIGHT, RANGE_WIDTH );

  // data is a 2-dimensional Array,
  // so you could get values like data[row][column]
  // Also, Arrays are 0-indexed, so every number is 1 less than you had originally
  const data = dataRange.getValues(); 

  Logger.log( data ); // just to inspect

  const includesArray = [];

  for (const row of data) {
    // using a for ... of loop means we don't have to track the index,
    // and we can treat each row as a 1-D array inside the loop
    const firstName = row[FIRST_NAME_COLUMN];
    const fullName = row[FULL_NAME_COLUMN];
    const included = fullName.includes(firstName); // btw this will return a value of TRUE for ones that do include and FALSE for those that don't

    Logger.log( `${firstName}, ${fullName}, ${included}` );
    // debugger;
    includesArray.push( [included] ); // adding an Array that includes just the single element, since that represents a single data column
  }

  Logger.log( includesArray );
  debugger;

  s.getRange( FIRST_ROW, INCLUDES_COLUMN, RANGE_HEIGHT, 1 ).setValues( includesArray );

}

I'm using const when possible, for both scoping and to indicate that I won't be re-assigning the variables. I'm also assigning magic numbers to THESE_CONSTANTS so they have some semantic meaning in the code (that's just for my sanity).

Also, I'm not touching the "database" inside the loop at all - I'm strictly working with JS Arrays here. I've pulled the data from the Sheet with dataRange.getValues() , then I'm writing all the includes values to the Sheet at once after the loop with setValues() . This is where you're likely to see the best improvement in terms of performance.

Give it a shot, and ask any questions you need!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM