google-apps-script - 在比较列中的代码后查找两个工作表之间的差异行
问题描述
我试图通过比较位于一列中的行与位于工作表的列中的NEW
行来查找添加到工作表的行。我通过找到两个代码之间的差异来做到这一点。Data
Codes
Codes
Database
...
// 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
...
上面的代码给了我Difference i.e. new Codes
已经进入Database
工作表的代码。有没有办法修改上面的内容Reduce function code
以拉入entire new rows
,diff Array
然后可以将其附加到工作Database
表的末尾?
笔记:
这里的
Delivery Date
inDatabase Sheet
指的是FinalDate
inData Sheet
。是否可以修改上面的代码以考虑到不匹配的列名,以便将FinalDate
列值准确放置在Delivery Date
列中?我还需要为中的每个新行添加一个
DataValidation dropdown
包含值。上述代码如何考虑数据验证代码?Open,Complete
Status Column
Database Sheet
diff array
如您所见,
matching columns
inDatabase Sheet
不是连续的,并且与 的顺序相同Data Sheet
,而是分布在工作表中。是否可以修改代码以将每个 diff 数组值正确放置到各自的列中?最后,我必须将
Owner
中的每个名称Database Sheet
与一个Mapping Sheet
数组(包含Owner
名称及其对应的Emp
名称)进行比较,然后匹配其对应的Emp
名称并将其添加到相应的Emp
列中Database Sheet
。
原因:
- 我想在内存中完成所有这些,最后一口气将这个内存数组转移到
Database Sheet
。否则,重复访问(读/写)表格会花费大量时间来运行代码,尤其是在数据很大的情况下。这可以通过一些简洁的代码实现吗?
这是 [示例文件][4] 的链接。
[4]:
@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
匹配后)。工作表中的列是工作表中的列。Owner
FinalDate
Data
Delivery Date
Database
这个想法是创建一个简洁的代码,该代码将创建一个 2D 数组(应包括 datavalidation 和 Emp 名称),以将所有新数据正确放置在工作Database
表中。我想避免每次都将数据写入工作表以更新工作表中的每一列Database
。
解决方案
如何将以下示例脚本添加到您的底部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 和 put值,我使用了和
Emp
的 JSON 对象。mapObj
existingIdsObj
推荐阅读
- android - Zoom HERE 地图以显示所有标记 Android
- python - ValueError:长度不匹配:预期轴有 23 个元素,新值有 2 个元素。熊猫长度不匹配
- python - 如何将中间数量的数据传递给子进程?
- python - 使用python显示docx文件的内容
- vb.net - 计算文本框中所有行的总和
- python - 带有棉花糖的 Hybrid_property
- covariance - 关于协方差和逆变的问题
- java - Spring 控制器单元测试抛出 NestedServletException
- javascript - 使用反应我试图在点击更新 aa 值时改变按钮的颜色
- html - 如何在flutter webview中将外部css应用于html渲染