[英]Paste values from one sheet to another and remove duplicates
I have two worksheets in my google spreadsheet: 我的Google电子表格中有两个工作表:
Input data is coming into the Get Data
worksheet via the importxml
function. 输入数据通过
importxml
函数进入“ Get Data
工作表。
However, I would like to copy all values of the Get Data
sheet to the Final Data
sheet and if there are duplicates(in terms of rows) append the unique row. 但是,我想将“
Get Data
表的所有值复制到“ Final Data
表,如果有重复项(就行而言),请追加唯一行。
Here is what I tried: 这是我尝试过的:
function onEdit() {
//get the data from old Spreadsheet
var ss = SpreadsheetApp.openById("1bm2ia--F2b0495iTJotp4Kv1QAW-wGUGDUROwM9B-D0");
var dataRange = ss.getSheetByName("Get Data").getRange(1, 1, ss.getLastRow(), ss.getLastColumn());
var dataRangeFinalData = ss.getSheetByName("Final Data").getRange(1, 1, ss.getLastRow(), ss.getLastColumn());
var myData = dataRange.getValues();
//Open new Spreadsheet & paste the data
newSS = SpreadsheetApp.openById("1bm2ia--F2b0495iTJotp4Kv1QAW-wGUGDUROwM9B-D0");
Logger.log(newSS.getLastRow());
newSS.getSheetByName("Final Data").getRange(newSS.getLastRow()+1, 1, ss.getLastRow(), ss.getLastColumn()).setValues(myData);
//remove duplicates in the new sheet
removeDups(dataRangeFinalData)
}
function getId() {
Browser.msgBox('Spreadsheet key: ' + SpreadsheetApp.getActiveSpreadsheet().getId());
}
function removeDups(array) {
var outArray = [];
array.sort(lowerCase);
function lowerCase(a,b){
return a.toLowerCase()>b.toLowerCase() ? 1 : -1;// sort function that does not "see" letter case
}
outArray.push(array[0]);
for(var n in array){
Logger.log(outArray[outArray.length-1]+' = '+array[n]+' ?');
if(outArray[outArray.length-1].toLowerCase()!=array[n].toLowerCase()){
outArray.push(array[n]);
}
}
return outArray;
}
Below you can find the link to a sample spreadsheet: 您可以在下面找到示例电子表格的链接:
My problem is that the data does not get pasted. 我的问题是不会粘贴数据。
I appreciate your replies! 感谢您的答复!
tl;dr: See script at bottom. tl; dr:请参阅底部的脚本。
An onEdit()
function is inappropriate for your use case, as cell contents modified by spreadsheet functions are not considered "edit" events. onEdit()
函数不适合您的用例,因为由电子表格函数修改的单元格内容不视为“编辑”事件。 You can read more about that in this answer . 您可以在此答案中了解更多有关该内容的信息。 If you want this to be automated, then a timed trigger function would be appropriate.
如果您希望将其自动化,那么定时触发功能将是适当的。 Alternatively, you could manually invoke the function by a menu item, say.
或者,您可以通过菜单项手动调用该功能。 I'll leave that to you to decide, as the real meat of your problem is how to ensure row-level uniqueness in your final data set.
我将由您决定,因为问题的实质是如何确保最终数据集中的行级唯一性。
Although your original code is incomplete, it appears you were intending to first remove duplicates from the source data, utilizing case-insensitive string comparisons. 尽管原始代码不完整,但您似乎打算首先使用不区分大小写的字符串比较从源数据中删除重复项。 I'll suggest instead that some other JavaScript magic would help here.
我会建议其他JavaScript魔术在这里有所帮助。
We're interested in uniqueness in our destination data, so we need to have a way to compare new rows to what we already have. 我们对目标数据的唯一性感兴趣,因此我们需要一种将新行与已有行进行比较的方法。 If we had arrays of strings or numbers, then we could just use the techniques in How to merge two arrays in Javascript and de-duplicate items .
如果我们有字符串或数字数组,那么我们可以使用如何在Javascript中合并两个数组并删除重复项中的技术 。 However, there's a complication here, because we have an array of arrays, and arrays cannot be directly compared.
但是,这里有一个复杂问题,因为我们有一个数组数组,并且数组不能直接比较。
Fine - we could still compare rows element-by-element, which would require a simple loop over all columns in the rows we were comparing. 很好-我们仍然可以逐个元素比较行,这将需要一个简单的循环遍历正在比较的行中的所有列。 Simple, but slow, what we would call an O(n 2 ) solution (Order n-squared).
简单但缓慢,我们称之为O(n 2 )解 (阶数为n平方)。 As the number of rows to compare increased, the number of unique comparison operations would increase exponentially.
随着要比较的行数增加,唯一比较操作数将成倍增加。 So, let's not do that.
所以,我们不要那样做。
Instead, we'll create a separate data structure that mirrors our destination data but is very efficient for comparisons, a hash . 相反,我们将创建一个单独的数据结构,该结构镜像我们的目标数据,但对于比较非常有效,即hash 。
In JavaScript we can quickly access the properties of an object by their name, or key. 在JavaScript中,我们可以通过名称或键快速访问对象的属性。 Further, that key can be any string.
此外,该键可以是任何字符串。 We can create a simple hash table then, with an object whose properties are named using strings generated from the rows of our destination data.
然后,我们可以创建一个简单的哈希表,其中包含一个对象,该对象的属性使用从目标数据行生成的字符串命名。 For example, this would create a hash object, then add the array
row
to it: 例如,这将创建一个哈希对象,然后向其添加数组
row
:
var destHash = {};
destHash[row.join('')] = true; // could be anything
To create our key, we're join
ing all the values in the row
array with no separator. 要创建键,我们将不带分隔符的
row
数组中的所有值join
在一起。 Now, to test for uniqueness of a row, we just check for existence of an object property with an identically-formed key. 现在,要测试一行的唯一性,我们只需检查具有相同格式键的对象属性是否存在。 Like this:
像这样:
var alreadyExists = destHash.hasOwnProperty(row.join(''));
One additional consideration: since the source data can conceivably contain duplicate rows that aren't yet in the destination data, we need to continuously expand the hash table as unique rows are identified. 另一个注意事项:由于源数据可以包含目标数据中尚未存在的重复行,因此我们需要在标识唯一行时不断扩展哈希表。
JavaScript provides two built-in array methods that we'll use to filter out known rows, and concatenate only unique rows to our destination data. JavaScript提供了两个内置的数组方法,我们将使用它们过滤掉已知行,并将唯一的行连接到目标数据。
In its simple form, that would look like this: 用它的简单形式,看起来像这样:
// Concatentate source rows to dest rows if they satisfy a uniqueness filter
var mergedData = destData.concat(sourceData.filter(function (row) {
// Return true if given row is unique
}));
You can read that as "create an array named mergedData
that consists of the current contents of the array named destData
, with filtered rows of the sourceData
array concatenated to it." 您可以将其读为“创建一个名为
mergedData
的数组,该数组由名为destData
的数组的当前内容组成,并将sourceData
数组的过滤后的行连接在一起。”
You'll find in the final function that it's a little more complex due to the other considerations already mentioned. 由于已经提到的其他注意事项,在最终功能中您会发现它稍微复杂一些。
Once we have our mergedData
array, it just needs to be written into the destination Sheet. 一旦有了
mergedData
数组,只需将其写入目标工作表即可。
Padding rows: The source data contains rows of inconsistent width, which will be a problem when calling setValues()
, which expects all rows to be squared off. 填充行:源数据包含宽度不一致的行,这在调用
setValues()
时会出现问题,因为setValues()
期望所有行都被平方。 This will require that we examine and pad rows to avoid this sort of error: 这将要求我们检查并填充行,以避免此类错误:
Incorrect range width, was 6 but should be 5 (line ?, file "Code")
范围宽度不正确,为6,但应为5(第?行,“代码”文件)
Padding rows is done by push
ing blank "cells" at the end of the row array until it reaches the intended length. 通过
push
空白“单元格” push
行数组的末尾直到达到预期的长度来完成填充行。
for (var col=mergedData[row].length; col<mergedWidth; col++)
mergedData[row].push('');
With that taken care of for each row, we're finally ready to write out the result. 完成每一行的处理后,我们终于可以写出结果了。
function appendUniqueRows() {
var ss = SpreadsheetApp.getActive();
var sourceSheet = ss.getSheetByName('Get Data');
var destSheet = ss.getSheetByName('Final Data');
var sourceData = sourceSheet.getDataRange().getValues();
var destData = destSheet.getDataRange().getValues();
// Check whether destination sheet is empty
if (destData.length === 1 && "" === destData[0].join('')) {
// Empty, so ignore the phantom row
destData = [];
}
// Generate hash for comparisons
var destHash = {};
destData.forEach(function(row) {
destHash[row.join('')] = true; // could be anything
});
// Concatentate source rows to dest rows if they satisfy a uniqueness filter
var mergedData = destData.concat(sourceData.filter(function (row) {
var hashedRow = row.join('');
if (!destHash.hasOwnProperty(hashedRow)) {
// This row is unique
destHash[hashedRow] = true; // Add to hash for future comparisons
return true; // filter -> true
}
return false; // not unique, filter -> false
}));
// Check whether two data sets were the same width
var sourceWidth = (sourceData.length > 0) ? sourceData[0].length : 0;
var destWidth = (destData.length > 0) ? destData[0].length : 0;
if (sourceWidth !== destWidth) {
// Pad out all columns for the new row
var mergedWidth = Math.max(sourceWidth,destWidth);
for (var row=0; row<mergedData.length; row++) {
for (var col=mergedData[row].length; col<mergedWidth; col++)
mergedData[row].push('');
}
}
// Write merged data to destination sheet
destSheet.getRange(1, 1, mergedData.length, mergedData[0].length)
.setValues(mergedData);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.