【问题标题】:Find Difference Rows between two Sheets after comparing their Codes in a Column在比较列中的代码后查找两个工作表之间的差异行
【发布时间】:2020-07-27 10:34:10
【问题描述】:

我试图通过比较位于列中的Codes 与位于Database 表的列中的Codes 来查找添加到Data 表的NEW 行。我通过找出这两个代码之间的差异来做到这一点。

...
// Get Mappings array
let Maplist = shtMap.getRange(2, 1, r_Map - 1, 2).getValues();

// find new codes that have come in the Data sheet
let DataCodes = [...new Set(shtData.getRange(2, 1, r_Data - 1, 1).getValues().flat())];
let DatabaseCodes = [...new Set(shtDatabase.getRange(2, 2, r_Database - 1, 1).getValues().flat())];

let diff =[];
// ===> Below is the line I want to modify to incorporate all the logic given in my Notes section.
diff = DataCodes.reduce( (diff,x) => !DatabaseCodes.includes(x) ? [...diff, [x]] : diff, []);

// Map Emp name to diff Array ===> not working....getting error!
diff = diff.map(function(x, i , arr){
    if(arr.indexOf(x) == i){
        return [...diff, [arr[i][1]]);
    }
}, (Maplist));

// Add Data Validation to `Status` column
var Rng = shtDatabase.getRange(r_Database + 1, 7, diff.length -1, 1);
Rng.clearDataValidations().clearContent();
var rule = SpreadsheetApp.newDataValidation().requireValueInList([`Open`,`Complete`], true).build();
Rng.setDataValidation(rule); // Update `Status` value
...

上面的代码给了我进入Database工作表的Difference i.e. new Codes。有没有办法修改上面的Reduce function code 以拉入entire new rows,以便diff Array 可以附加到Database 工作表的末尾?

注意:

  • 这里Database Sheet 中的Delivery Date 指的是Data Sheet 中的FinalDate。是否可以修改上面的代码以考虑到不匹配的列名,使FinalDate 列的值准确地放在Delivery Date 列中?

  • 对于diff array 中的每个新行,我还需要将包含值Open,CompleteDataValidation dropdown 添加到Database SheetStatus Column 中。上面的代码怎么会考虑到Data Validation code呢?

  • 如您所见,Database Sheet 中的 matching columns 不是连续的,并且与 Data Sheet 的顺序相同,而是分布在工作表中。是否可以修改代码以将每个 diff 数组值正确放入各自的列中?

  • 最后,我必须将Database Sheet 中的每个Owner 名称与Mapping Sheet 数组(其中包含Owner 名称及其对应的Emp 名称)进行比较,然后匹配其对应的Emp 名称并将其添加到Database Sheet 中的Emp 列中。

原因:

  • 我想在内存中完成这一切,最后一口气将这个内存数组转移到Database Sheet。否则,重复访问(读/写)表格需要花费大量时间来运行代码,尤其是在数据很大的情况下。这可以通过一些简洁的代码实现吗?

数据表: 数据库表: 映射表

这里是 [示例文件][4] 的链接。

[4]:

编辑: https://docs.google.com/spreadsheets/d/1DARGtbN8EyEKyF9ceuOusStvuPIXjUR_8OrqfhPxpNQ/edit?usp=sharing

@TheMaster,这是文件中编写的完整代码:

function myTest(){

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const shtData = ss.getSheetByName("Data");
  const shtMap = ss.getSheetByName("Mapping");
  const shtDatabase = ss.getSheetByName("Database");

    // get Data Sheet unique list of Owners
  let r_Data = FindLastRow(shtData);
  let c_Data = FindLastColumn(shtData);
  let list = shtData.getRange(2, 4, r_Data - 1, 1).getValues();
  let Datalist = [...new Set(list.flat())];

  // get Mapping Sheet unique list of Owners
  r_Map = FindLastRow(shtMap);
  c_Map = FindLastColumn(shtMap);
  list = shtMap.getRange(2, 1, r_Map - 1, 1).getValues();
  let Maplist = [...new Set(list.flat())];
  
  // find new codes that have come in the Data sheet
  r_Database = FindLastRow(shtDatabase);
  c_Database = FindLastColumn(shtDatabase);
  let DataCodes = [...new Set(shtData.getRange(2, 1, r_Data - 1, 1).getValues().flat())];
  let DatabaseCodes = [...new Set(shtDatabase.getRange(2, 2, r_Database - 1, 1).getValues().flat())];
  
  // find the difference between the 2 arrays and append the new ones to Mapping Sheet, then sort.
  let diff = Datalist.reduce( (diff,x) => !Maplist.includes(x) ? [...diff, [x,'Unassigned']] : diff,[]);
  if(diff.length !== 0){
    shtMap.getRange(r_Map + 1, 1, diff.length, diff[0].length).setValues(diff);
  }

  // Sort the Mappings Sheet on 2nd column, then 1st column
  shtMap.getDataRange().offset(1, 0, shtMap.getDataRange().getNumRows() - 1).sort([{column: 2, ascending: true}, {column: 1, ascending: true}]);
  

//  diff =[];
  // ===> Below is the line I want to modify to incorporate all the logic given in my Notes section.
  diff = DataCodes.reduce( (diff,x) => !DatabaseCodes.includes(x) ? [...diff, [x]] : diff, []);


  // From Notes : Map Emp name to diff Array ===> not working....getting error!
  diff = diff.map( function(x, i, arr){
    if(arr.indexOf(x) == i){
      return [...diff, arr[1][i]];
    }
  }, (Maplist));
  
  // From Notes : Add Data Validation to `Status` column
  var Rng = shtDatabase.getRange(r_Database + 1, 7, diff.length -1, 1);
  Rng.clearDataValidations().clearContent();
  var rule = SpreadsheetApp.newDataValidation().requireValueInList([`Open`,`Complete`], true).build();
  Rng.setDataValidation(rule); // Update `Status` value
}


function FindLastRow(sht) {
  return sht.getRange(1,1).getDataRegion().getLastRow();
};

function FindLastColumn(sht) {
  return sht.getRange(1,1).getDataRegion().getLastColumn();
};

编辑: @Tanaike,我已经更新了帖子中的屏幕截图以及电子表格。例如Data 工作表中的黄色行是new rows,因此需要正确放置在Database 工作表中,并在Status 列中添加数据验证,Emp 名称在Emp 列中(匹配后@987654371 @ 带有映射表)。 Data 表中的FinalDate 列是Database 表中的Delivery Date 列。

我们的想法是创建一个简洁的代码,该代码将创建一个 2D 数组(应包括 datavalidation 和 Emp 名称),以将所有新数据正确放置在 Database 表中。我想避免每次都将数据写入工作表以更新Database工作表中的每一列。

【问题讨论】:

标签: google-apps-script google-sheets row reduce difference


【解决方案1】:

将以下示例脚本添加到您的myTest() 底部怎么样?

修改后的脚本:

从:
  var Rng = shtDatabase.getRange(r_Database + 1, 7, diff.length -1, 1);
  Rng.clearDataValidations().clearContent();
  var rule = SpreadsheetApp.newDataValidation().requireValueInList([`Open`,`Complete`], true).build();
  Rng.setDataValidation(rule); // Update `Status` value
}
至:
  var Rng = shtDatabase.getRange(r_Database + 1, 7, diff.length -1, 1);
  Rng.clearDataValidations().clearContent();
  var rule = SpreadsheetApp.newDataValidation().requireValueInList([`Open`,`Complete`], true).build();
  Rng.setDataValidation(rule); // Update `Status` value

  // I added below script.
  const mapObj = shtMap.getRange("A2:B" + shtMap.getLastRow()).getValues().reduce((o, [a, b]) => Object.assign(o, {[a]: b}), {});
  const existingIdsObj = shtDatabase.getRange("B2:B" + shtData.getLastRow()).getValues().reduce((o, [b]) => Object.assign(o, {[b]: true}), {});
  const putValues = shtData.getRange("A2:G" + shtData.getLastRow()).getValues().reduce((ar, [a,b,c,d,e,f,g]) => {
    if (!existingIdsObj.hasOwnProperty(a)) ar.push([b, a, f, c, , , , d, e, , , g, , mapObj[d]]);
    return ar;
  }, []);
  shtDatabase.getRange(shtDatabase.getLastRow() + 1, 1, putValues.length, putValues[0].length).setValues(putValues);
}
  • 为了检查重复的ID并放入Emp值,我使用了mapObjexistingIdsObj的JSON对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多