Google Apps Script重命名工作表时报Invalid argument: name错误
问题原因与修复方案
核心报错原因
你触发Exception: Invalid argument : name错误的根本原因有两个:
getValues()返回的是二维数组结构,ref[i]本质是数组而非字符串,直接传给setName时隐式类型转换不稳定,就会出现部分编号正常、部分报错的情况- 谷歌工作表命名有强制规则,你没有做前置校验:
- 名称长度不能超过31个字符
- 不能包含
:、/、\、?、*、[、]这些特殊字符 - 同一文档内工作表名称不能重复
- 不能为空字符串
另外你的代码还存在两个逻辑漏洞会放大这个问题:
- 复制工作表后靠索引取表的逻辑不可靠,
duplicateActiveSheet生成的新表默认会插在当前激活表的后方,索引顺序和你预期可能不一致 getFirstEmptyRowByColumnArray返回的行数计算错误,你从第3行开始遍历,最终返回的偏移量需要加3才是真实的行号,否则会多取很多空行,空值传入setName直接触发报错
修复后的完整代码
function onOpen(e) { SpreadsheetApp.getUi() .createMenu('Fiche Produit') .addItem('Créer une fiche produit','creaficheproduit') .addSeparator() .addToUi(); } function creaficheproduit() { var tss = SpreadsheetApp.getActiveSpreadsheet(); var sheets = tss.getSheets(); // 清理多余工作表 for (i = 0; i < sheets.length-1; i++) { tss.deleteSheet(sheets[i+1]); } var tsh = tss.getSheets()[0]; var ui = SpreadsheetApp.getUi(); var prompt = ui.prompt('Indiquer le lien de la Fiche CS source', 'lien',ui.ButtonSet.OK_CANCEL) var response = prompt.getResponseText(); var button = prompt.getSelectedButton(); if (button == ui.Button.OK) { var sss = SpreadsheetApp.openByUrl(response); var ssh = sss.getSheetByName('Fiche_eclate_CS'); // 修复空行计算逻辑 var lrow = getFirstEmptyRowByColumnArray(ssh,"D"); var ref = ssh.getRange("D3:D"+lrow).getValues(); var gamme = ssh.getRange(7,3).getValue(); tsh.getRange(2,6).setValue(gamme); var dtotal = ssh.getRange(6,7).getValue(); var htotal = ssh.getRange(7,7).getValue(); var dAJ = ssh.getRange(9,7).getValue(); var hAJ = ssh.getRange(10,7).getValue(); tsh.getRange(4,7).setValue(dtotal + " - h" + htotal); tsh.getRange(5,7).setValue(dAJ + " - h" + hAJ); // 已存在的表名集合,用于查重 var existNames = new Set(); for (var i = 0; i < ref.length; i++){ // 取二维数组里的真实值,同时预处理非法字符 var rawName = ref[i][0].toString().trim(); var safeName = rawName.replace(/[:\/\\?*\[\]]/g, '').slice(0,31); // 重名处理 let suffix = 1; let finalName = safeName; while(existNames.has(finalName)) { finalName = `${safeName}_${suffix}`; suffix++; } existNames.add(finalName); if(i == 0){ tss.getSheets()[0].setName(finalName); } else { // 直接获取新复制的工作表引用,不用索引避免拿错 var newSheet = tss.duplicateActiveSheet(); newSheet.setName(finalName); } // 直接写入参考编号,不需要再开一次循环 tss.getActiveSheet().getRange(3,6).setValue(rawName); } } } function getFirstEmptyRowByColumnArray(sheet, col) { var column = sheet.getRange(col + "3:" + col); var values = column.getValues(); var ct = 0; while (values[ct] && values[ct][0] != "") { ct++; } // 从第3行开始计数,返回真实行号 return (ct + 2); }
优化说明
- 新增了工作表名称预处理逻辑,自动过滤非法字符、截断超长名称、处理重名问题
- 修正了空行计算逻辑,不会再读取到空的参考编号
- 复制工作表后直接获取新表引用,避免索引错位拿错表
- 合并了写入参考编号的逻辑,减少了一次不必要的循环
内容的提问来源于stack exchange,提问作者mat
相关产品推荐
相关产品推荐

