Google Script version of VLookup (More Efficient Method?)

后端 未结 2 932
自闭症患者
自闭症患者 2021-01-29 06:11

I\'m trying to put together a function that will allow me to pull a column\'s info from one sheet to another based on a key column. This would work similar to an index match or

2条回答
  •  太阳男子
    2021-01-29 06:51

    Issue:

    • Slow script:

      • O(n2): For every element in array 1, the array 2 is iterated from top to bottom. Even after finding a match in array 2, the loop is not broken(break), but the inner loop is completed until the end of the array2 unnecessarily.

      • getValues() is requested twice for two columns of the same sheet. Contact with spreadsheet is costly. So, limiting it is necessary.

    Solution:

    One possible solution to achieve O(n):

    • Create a new object using array 1 with key as 'the value to look for'. Then it's possible to directly access the value in this object each time for each value in array 2.

    Sample script:

    const ss = SpreadsheetApp.getActive();
    /**
     * @param {GoogleAppsScript.Spreadsheet.Sheet} fromSht -Sheet to import from
     * @param {GoogleAppsScript.Spreadsheet.Sheet} toSht -Sheet to import to
     * @param {Number} fromCompCol -Column number of fromSht to compare
     * @param {Number} toCompCol -Column number of toSht to compare
     * @param {Number} fromCol -Column number of fromSht to get result
     * @param {Number} toCol -Column number of toSht to get result
     */
    function vlookup_2(
      fromSht = ss.getSheetByName('Sheet1'),
      toSht = ss.getSheetByName('Sheet2'),
      fromCompCol = 1,
      toCompCol = 1,
      fromCol = 2,
      toCol = 2
    ) {
      const toShtLr = toSht.getLastRow();
      const toCompArr = toSht.getRange(2, toCompCol, toShtLr - 1, 1).getValues();
      const fromArr = fromSht.getDataRange().getValues();
      fromCompCol--;
      fromCol--;
    
      /*Create a hash object of fromSheet*/
      const obj1 = fromArr.reduce((obj, row) => {
        let el = row[fromCompCol];
        el in obj ? null : (obj[el] = row[fromCol]);
        return obj;
      }, {});
    
      //Paste to column
      toSht
        .getRange(2, toCol, toShtLr - 1, 1)
        .setValues(toCompArr.map(row => (row[0] in obj1 ? [obj1[row[0]]] : [null])));
    }
    
    

    Performance:

    • ~5s for 10000 rows in sheet1 and 10000 rows in sheet 2

    References:

    • Time complexity
    • Hash map

提交回复
热议问题