目标
防止脚本将导致错误的空白(空(行从源复制到目标。
错误详细信息:
谷歌应用程序脚本:类型错误:无法读取未定义(行*,文件"代码"(的属性"长度">
此错误指的是以下行:dstSheet.getRange(dstLastRow + 1, 1, values.length, values[0].length).setValues(values);
完整代码
我使用的是来自HERE的以下代码,该代码经过了轻微修改。无论是否进行修改,都会出现错误。代码的逻辑是:如果目标工作表不包含ID,则导入ID和从源到目标的特定列。
function importNewEmployeeIds() {
const srcSheetName = 'Source';
const dstSheetName = 'Destination';
const srcSheet = SpreadsheetApp.openById("SpreadsheetID1").getSheetByName(srcSheetName);
const dstSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dstSheetName);
// Retrieve values from source sheet.
var headerRowNumber = 1;
const srcValues = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues();
// Retrieve values from destination sheet and create an object for searching the ID.
const dstLastRow = dstSheet.getLastRow();
const dstObj = dstLastRow == 0 ? {} : dstSheet.getRange("A1:A" + dstLastRow).getValues().reduce((o, [a]) => (o[a] = true, o), {});
// Create an array for putting to the destination sheet.
const values = srcValues.filter(r => !dstObj[r[1]]).map(r => [r[1], r[19], "", r[18]]);
// Put the values to the destination sheet.
dstSheet.getRange(dstLastRow + 1, 1, values.length, values[0].length).setValues(values);
}
故障排除
[Source]在运行脚本之前。
| A |B| C | D |
|200001| |Email2|Email1|
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
| | | | |
[目的地]运行脚本之前。
| A |B| C | D |
|200001| |Email2|Email1|
[目的地]运行脚本后。
| A |B| C | D |
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
| | | | | <-- Notice the blank row. I don't want the blank row.
一旦脚本运行,它就会将行数据从源复制到目标。问题是,脚本还会将空白(空(行复制到源工作表中。
[目的地]预期结果-无空白行
| A |B| C | D |
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
我能想到的新手解决方案:
选项A(在脚本开始时,我可以首先删除目标中的所有空行。这效率较低,并不能解决问题的根源,但至少它解决了我的问题。
function removeEmptyRows(){
var sh = SpreadsheetApp.getActiveSheet();
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
if (maxRows-lastRow != 0){
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
}
找到的代码:HERE
选项B(更新原始代码,使其不会复制空白行。
之前
const srcValues = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues();
之后
const srcValuesAndBlankRows = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues();
const srcValues = srcValuesAndBlankRows.filter(String); //Removes Blank Rows
找到的代码:HERE
例如,在您的情况下,以下修改如何?我修改了剧本中的两个部分。
修改的脚本:
function Q70718274_importNewEmployeeIds() {
const srcSheetName = 'Source';
const dstSheetName = 'Destination';
const srcSheet = SpreadsheetApp.openById("SpreadsheetID1").getSheetByName(srcSheetName);
const dstSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dstSheetName);
// Retrieve values from source sheet.
var headerRowNumber = 1;
const srcValues = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues().filter(r => r.join("") != ""); // <--- Modified
// Retrieve values from destination sheet and create an object for searching the ID.
const dstLastRow = dstSheet.getLastRow();
const dstObj = dstLastRow == 0 ? {} : dstSheet.getRange("A1:A" + dstLastRow).getValues().reduce((o, [a]) => (o[a] = true, o), {});
// Create an array for putting to the destination sheet.
const values = srcValues.filter(r => !dstObj[r[1]]).map(r => [r[1], r[19], "", r[18]]);
// Put the values to the destination sheet.
if (values.length > 0) { // <--- Added
dstSheet.getRange(dstLastRow + 1, 1, values.length, values[0].length).setValues(values);
}
}
- 通过
const srcValues = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues().filter(r => r.join("") != "");
,删除空行 - 通过
if (values.length > 0) {}
,当values
没有值时,不会发生错误
添加:
根据您的以下附加信息,
[Source]在运行脚本之前。
| A |B| C | D |
|200001| |Email2|Email1|
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
| | | | |
[目的地]运行脚本之前。
| A |B| C | D |
|200001| |Email2|Email1|
[目的地]运行脚本后。
| A |B| C | D |
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
| | | | | <-- Notice the blank row. I don't want the blank row.
一旦脚本运行,它就会将行数据从源复制到目标。问题是,脚本还会将空白(空(行复制到源工作表中。
[目的地]预期结果-无空白行
| A |B| C | D |
|200001| |Email2|Email1|
|200006| |Email4|Email3|
|200007| |Email6|Email5|
我知道你想从最上面的两张表中获得最下面的一张表。根据您提供的脚本,我认为您想要使用const values = srcValues.filter(r => !dstObj[r[1]]).map(r => [r[1], r[19], "", r[18]]);
。但是,从你的其他情况来看,我明白我的理解是不正确的。对于您的其他示例情况,下面的脚本如何?
示例脚本:
function importNewEmployeeIds2() {
const srcSheetName = 'Source';
const dstSheetName = 'Destination';
const srcSheet = SpreadsheetApp.openById("SpreadsheetID1").getSheetByName(srcSheetName);
const dstSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(dstSheetName);
// Retrieve values from source sheet.
var headerRowNumber = 1;
const srcValues = srcSheet.getDataRange().offset(headerRowNumber, 0, srcSheet.getLastRow() - headerRowNumber).getValues().filter(r => r.join("") != ""); // <--- Modified
// Retrieve values from destination sheet and create an object for searching the ID.
const dstLastRow = dstSheet.getLastRow();
const dstObj = dstLastRow == 0 ? {} : dstSheet.getRange("A1:A" + dstLastRow).getValues().reduce((o, [a]) => (o[a] = true, o), {});
// Create an array for putting to the destination sheet.
// const values = srcValues.filter(r => !dstObj[r[1]]).map(r => [r[1], r[19], "", r[18]]);
const values = srcValues.filter(r => !dstObj[r[0]]).map(r => [r[0], "", r[2], r[3]]); // <--- Modified
// Put the values to the destination sheet.
if (values.length > 0) { // <--- Added
dstSheet.getRange(dstLastRow + 1, 1, values.length, values[0].length).setValues(values);
}
}