Google Sheets类VLookup Apps Script脚本误清空非匹配行数据问题
问题根因
原脚本仅读取了目标表中用于ID匹配的列数据,没有读取待更新列的原有内容,匹配失败时无法获取单元格原本存储的值,才会出现数据被清空、错把ID值写入名称列的问题。
修正代码
直接替换原有Refresh函数即可,核心逻辑是同时读取目标表匹配列、待更新列的现有数据,匹配成功时写入源表拉取的新值,匹配失败时保留原单元格内容:
const ss = SpreadsheetApp.getActive(); /** * @param {GoogleAppsScript.Spreadsheet.Sheet} fromSht - 数据来源工作表 * @param {GoogleAppsScript.Spreadsheet.Sheet} toSht - 待更新目标工作表 * @param {Number} fromCompCol - 源表用于匹配的列号 * @param {Number} toCompCol - 目标表用于匹配的列号 * @param {Number} fromCol - 源表要拉取的内容列号 * @param {Number} toCol - 目标表要写入的内容列号 */ function Refresh( fromSht = ss.getSheetByName('Sheet1'), toSht = ss.getSheetByName('Sheet2'), fromCompCol = 2, toCompCol = 2, fromCol = 1, toCol = 1 ) { const dataStartRow = 2; const toShtLr = toSht.getLastRow(); const rowCount = toShtLr - dataStartRow + 1; // 一次性读取目标表涉及的两列数据,减少API调用 const colStart = Math.min(toCompCol, toCol); const colTotal = Math.abs(toCompCol - toCol) + 1; const toData = toSht.getRange(dataStartRow, colStart, rowCount, colTotal).getValues(); const fromArr = fromSht.getDataRange().getValues(); // 表格列号转数组0基索引 const fromCompColIdx = fromCompCol - 1; const fromColIdx = fromCol - 1; const toCompColOffset = toCompCol - colStart; const toColOffset = toCol - colStart; // 构建源表ID与目标内容的哈希映射,提升匹配效率 const sourceMap = fromArr.reduce((map, row) => { const matchKey = row[fromCompColIdx]; if (!(matchKey in map)) map[matchKey] = row[fromColIdx]; return map; }, {}); // 构造最终写入的数组:匹配到ID用源表新值,未匹配保留原有值 const outputArr = toData.map(row => { const currentId = row[toCompColOffset]; return currentId in sourceMap ? [sourceMap[currentId]] : [row[toColOffset]]; }); // 批量写入目标列 toSht.getRange(dataStartRow, toCol, rowCount, 1).setValues(outputArr); }
运行效果
使用提供的测试数据运行脚本后:
- ID为101的行,名称列会更新为源表的「新名称1」
- ID为102、103的行因为源表无匹配ID,会保留原有「名称2」「名称3」的内容,和预期结果完全一致。
内容的提问来源于stack exchange,提问作者qtreboux
相关产品推荐
相关产品推荐

