You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Apps脚本:如何检查数组任意位置的Unique ID以避免重复复制行

解决Unique ID遍历校验的问题

我完全理解你的困扰——原脚本的ID重复校验逻辑依赖两个工作表的行顺序一致,一旦「3 Months」表重新排序或者新增行不在末尾,校验就会失效。咱们来重构这部分逻辑,改成遍历整个已存在的Unique ID列表来判断是否重复,同时优化脚本的执行效率。

原代码的核心问题

原脚本里的ID校验部分有两个关键错误:

  • 使用j(当前匹配到的到期行计数)来索引CallOffIDs数组,这完全依赖行顺序一致,逻辑不成立
  • for (test in CallOffIDs)的遍历写法不符合需求,而且内部的break逻辑会导致只检查第一个元素就退出

修改后的完整代码

function contractSearch2() {
  // 获取工作表对象
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const dataSheet = ss.getSheetByName("Data");
  const threeMonthsSheet = ss.getSheetByName("3 Months");

  // 批量读取Data表的所有数据(避免循环内多次调用API)
  const dataLastRow = dataSheet.getLastRow();
  const dataAllValues = dataSheet.getRange(1, 1, dataLastRow, 44).getValues();
  // 提取Data表的到期日期列(第11列,索引从0开始是第10位)
  const endDates = dataAllValues.map(row => row[10]);

  // 计算三个月后的日期
  const today = new Date();
  const threeMonthsOut = new Date(today);
  threeMonthsOut.setMonth(today.getMonth() + 3);

  // 批量读取3 Months表的Unique ID列(第4列,索引3),并转换成Set用于快速查重
  const threeMonthsLastRow = threeMonthsSheet.getLastRow();
  let existingIds = new Set();
  if (threeMonthsLastRow > 0) {
    const idValues = threeMonthsSheet.getRange(1, 4, threeMonthsLastRow).getValues();
    // 将二维数组转成一维数组,再存入Set
    existingIds = new Set(idValues.flat());
  }

  // 遍历Data表的每一行,筛选符合条件的行
  const rowsToAdd = [];
  for (let i = 0; i < dataAllValues.length; i++) {
    const row = dataAllValues[i];
    const endDate = new Date(endDates[i]);
    
    // 校验到期日期是否在三个月后的当月(保留原逻辑)
    if (endDate.getMonth() === threeMonthsOut.getMonth() && endDate.getFullYear() === threeMonthsOut.getFullYear()) {
      const uniqueId = row[3]; // Unique ID在第4列,索引3
      
      // 检查ID是否已存在于3 Months表中
      if (!existingIds.has(uniqueId)) {
        rowsToAdd.push(row);
        // 将新增的ID加入Set,避免同一轮遍历中重复添加
        existingIds.add(uniqueId);
      }
    }
  }

  // 批量写入符合条件的行(比逐行写入高效很多)
  if (rowsToAdd.length > 0) {
    const nextEmptyRow = threeMonthsLastRow + 1;
    threeMonthsSheet.getRange(nextEmptyRow, 1, rowsToAdd.length, 44).setValues(rowsToAdd);
  }
}

关键修改点说明

  1. 用Set存储已存在的Unique ID

    • Set是一种无序的集合,has()方法可以快速判断元素是否存在(时间复杂度O(1)),比遍历数组效率高得多,而且完全不依赖行顺序
    • 先把「3 Months」表的所有ID提取出来转成Set,后续直接通过!existingIds.has(uniqueId)判断是否重复
  2. 批量读取/写入数据

    • 原脚本在循环内多次调用getRange()和getValues(),这会频繁触发Google Sheets API调用,导致脚本变慢
    • 修改后一次性读取整个Data表和ID列的数据,最后批量写入符合条件的行,大幅提升执行效率
  3. 修正日期判断逻辑(可选优化)

    • 保留了你原有的“匹配三个月后的当月和当年”的逻辑,如果需要更精确的判断(比如到期日在今天到三个月后之间),可以把条件改成:
      if (endDate >= today && endDate <= threeMonthsOut)
      
  4. 避免同一轮遍历重复添加

    • 把新增的ID即时加入Set,防止Data表中同一ID出现多次时被重复添加到「3 Months」表

这样修改后,不管「3 Months」表的行怎么排序,都能准确校验Unique ID是否存在,而且脚本的执行效率也会提升不少,适合频繁运行的场景。

内容的提问来源于stack exchange,提问作者Dan Howard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:24:22