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

如何使用GAS按PO号时间戳从二维数组提取最新条目?

如何提取每个OrderPO对应的最新时间戳行?

问题描述

需要依据表格A列(OrderPO)的时间戳,提取每个PO号对应的最新行(时间戳最晚的行),尝试使用sort()方法实现但未成功,以下是数据集和当前代码,求解决方法。

数据集

OrderPOTimeStampUnit
TTL-2202188/17/2022 20:47:55Print
TTL-2202188/18/2022 7:49:49Print
TTL-2202208/17/2022 18:00:55Print
TTL-2202208/18/2022 9:49:49Print
TTL-2202198/17/2022 20:47:55Print
TTL-2202198/18/2022 7:49:49Print
TTL-2202198/17/2022 20:47:59Print
TTL-2202168/18/2022 8:30:49Print

当前代码

function getLastestEntries() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Sheet28');
  let pos = sheet.getDataRange().getValues();

  let uniquePos = pos.map(e => e[0]);
  uniquePos = [...new Set(uniquePos)];

  let latests = [];
  uniquePos.forEach(function (record) {
    let filteredPo = pos.filter(e => e[0] == record);
    filteredPo.sort(function (a, b) {
      let latest = a[1] > b[1] ? 1 : -1;
      latests.push(latest)
    });
  })
  console.log('POS: ' + JSON.stringify(latests))
}

问题分析

当前代码存在几个关键问题:

  • sort()用法错误:sort()的回调函数需要返回比较值,但你把返回值直接push到latests数组,没有实际完成排序后的行提取。
  • 字符串时间比较不可靠:直接比较时间字符串可能导致错误(比如"8/18/2022 7:49:49"和"8/17/2022 20:47:59"字符串比较会认为前者更小,但实际时间更晚),必须转为Date对象比较。
  • 未提取排序后的最新行:即使排序正确,也没有将排序后的最后一行(最新行)加入结果数组。
  • 未排除表头:getDataRange()会包含表头,导致uniquePos里包含表头字段,后续处理出错。

修正方案

方案1:高效的对象映射法(推荐)

遍历所有行,用对象存储每个PO的最新行,无需多次过滤排序,性能更优:

function getLastestEntries() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Sheet28');
  const [header, ...rows] = sheet.getDataRange().getValues(); // 分离表头和数据行

  const poLatestMap = {};
  rows.forEach(row => {
    const po = row[0];
    const currentDate = new Date(row[1]);
    // 如果当前PO不存在,或当前行时间比已存的更新,就替换
    if (!poLatestMap[po] || currentDate > new Date(poLatestMap[po][1])) {
      poLatestMap[po] = row;
    }
  });

  // 将对象转为数组,包含表头+最新行
  const latests = [header, ...Object.values(poLatestMap)];
  console.log('最新行数据:', latests);
  // 可选:将结果写入新表或覆盖原表
  // const targetSheet = ss.getSheetByName('LatestEntries');
  // targetSheet.clearContents();
  // targetSheet.getRange(1, 1, latests.length, latests[0].length).setValues(latests);
}

方案2:修正sort()用法

如果坚持用sort(),调整逻辑如下:

function getLastestEntries() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Sheet28');
  const [header, ...rows] = sheet.getDataRange().getValues();

  const uniquePos = [...new Set(rows.map(row => row[0]))];
  const latests = [header]; // 先加入表头

  uniquePos.forEach(po => {
    const filteredPo = rows.filter(row => row[0] === po);
    // 按时间戳降序排序,转为Date对象比较
    filteredPo.sort((a, b) => new Date(b[1]) - new Date(a[1]));
    // 取排序后的第一行(最新行)加入结果
    latests.push(filteredPo[0]);
  });

  console.log('最新行数据:', latests);
}

说明

  • 两种方案都先分离了表头,避免处理表头数据。
  • 时间比较都转为Date对象,确保比较逻辑正确。
  • 方案1只需遍历一次数据,比方案2的多次过滤排序更高效,数据量大时差异明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:54:28