Google 应用脚本:类型错误:无法读取未定义的属性'length'(行 *,文件 "Code" )



目标

防止脚本将导致错误的空白(空(行从源复制到目标。


错误详细信息:

谷歌应用程序脚本:类型错误:无法读取未定义(行*,文件"代码"(的属性"长度">

此错误指的是以下行: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);
}
}

相关内容

最新更新