javascriptgoogle-sheetsgoogle-apps-script

How can I get the date index match and run script


I have a script that works like copy paste with Index Match of entry and database sheet. It works perfectly if entrysheet C7:I7 has text value but not work when its date 14.11.2024 has tried the Utilities.formatDate but not help.

What the script do

Check if an value in row 4 already appears in "database"
if yes, then update the value in Column B
if no, then append the row 4 and row 7 values to "database"

Can someone tell me where I'm making a mistake?

function CopyEntry2Db() {
  var ss = SpreadsheetApp.getActiveSpreadsheet()
  var entrySheet = ss.getSheetByName("entry")
  var dbSheet = ss.getSheetByName("database")

  // get Entry sheet row 4 and 7 and flatten to 1D arrays
  var entryRow4 = entrySheet.getRange("C7:I7").getDisplayValues().flat()
  //var entryRow4 = Utilities.formatDate(entryRow, "GMT+1", "dd/MM/yyyy");
  var entryRow7 = entrySheet.getRange("C4:I4").getValues().flat()
  // Logger.log(entryRow4) // DEBUG
  // Logger.log(entryRow7) // DEBUG

  // get database sheet columns A and B
  var dbSheetLR = dbSheet.getLastRow()
  // Logger.log("DEBUG: Last row of data on database = "+dbSheetLR+", so number of rows of data exlcuding header = "+(+dbSheetLR-1))
  var dbColAValues = dbSheet.getRange(2,1,dbSheetLR-1,1).getValues().flat()
  // Logger.log(dbColAValues) // DEBUG
   var dbColBValues = dbSheet.getRange(2,2,dbSheetLR-1,1).getValues().flat()
  // Logger.log(dbColBValues) // DEBUG

  // create a temporary array to hold values to add to database
  var tempArray = []

  // loop though the row4 entry values to find a match on db column A
  // if indexOf return value = -1, then no match, so add entry value to db
  // if indexOf returns value <. -1, then value is array index
  for (var i=0;i<entryRow4.length;i++){
    var idxMatch = dbColAValues.indexOf(entryRow4[i]);
    //Logger.log("DEBUG: The entry value = "+entryRow4[i]+", index match = "+idxMatch)
    if (idxMatch == -1 ){
      // no match, so add entry values to tempArray
      tempArray.push([entryRow4[i],entryRow7[i]])
    }else{
       // Logger.log("matches value = the index = "+idxMatch+""+", Column A = "+entryRow4[i]+", new value = "+entryRow7[i])
      // match, so update dbColB value
      dbColBValues[i] = entryRow7[i]
    }
  }
  // Logger.log(tempArray) // DEBUG
  // Logger.log(dbColBValues) // DEBUG

  // convert dbColBValues to 2d array
  var nArr = [];
  while(dbColBValues.length > 0) {
    nArr.push(dbColBValues.splice(0,1));
  }
  // Logger.log("DEBUG: the Column B range = "+dbSheet.getRange(2,2,nArr.length,1).getA1Notation())
  // update dbColBValues
  dbSheet.getRange(2,2,nArr.length,1).setValues(nArr)

  // copy new entry values to database Sheet
  // Logger.log("the target range = "+dbSheet.getRange(dbSheetLR+1,1,tempArray.length,2).getA1Notation())
  dbSheet.getRange(dbSheetLR+1,1,tempArray.length,2).setValues(tempArray) 
}

Solution

  • Comparing a string to an Object

    Considering that your date values have a uniform format, the primary issue with your code is that you are using a getDisplayValues() to turn the values in a string on the line:

    var entryRow4 = entrySheet.getRange("C7:I7").getDisplayValues().flat()
    

    To an object using the getValues() on the line:

      var dbColAValues = dbSheet.getRange(2,1,dbSheetLR-1,1).getValues().flat()
    

    which causes a major issue with finding its exact values, for easier identification of its comparison, they must be in the same format.

    Here's the complete modified code:

    function CopyEntry2Db() {
      var ss = SpreadsheetApp.getActiveSpreadsheet()
      var entrySheet = ss.getSheetByName("entry")
      var dbSheet = ss.getSheetByName("database")
    
      var entryRow4 = entrySheet.getRange("C7:I7").getDisplayValues().flat()
      var entryRow7 = entrySheet.getRange("C4:I4").getValues().flat()
    
      var dbSheetLR = dbSheet.getLastRow()
      var dbColAValues = dbSheet.getRange(2,1,dbSheetLR-1,1).getDisplayValues().flat()
       var dbColBValues = dbSheet.getRange(2,2,dbSheetLR-1,1).getValues().flat()
    
      var tempArray = []
    
      for (var i=0;i<entryRow4.length;i++){
        var idxMatch = dbColAValues.indexOf(entryRow4[i]);
        if (idxMatch == -1 ){
          tempArray.push([entryRow4[i],entryRow7[i]])
        }else{
          dbColBValues[idxMatch] = entryRow7[i]
        }
      }
    
      var nArr = [];
      while(dbColBValues.length > 0) {
        nArr.push(dbColBValues.splice(0,1));
      }
    
      dbSheet.getRange(2,2,nArr.length,1).setValues(nArr)
    
      dbSheet.getRange(dbSheetLR+1,1,tempArray.length,2).setValues(tempArray) 
    }
    

    I also have seen some issues with the indexing on the else statement instead of [i] I replace it with the variable [idxMatch]

    Sample Output:

    enter image description here

    References:

    1. getDisplayValues()
    2. getValues()