【问题标题】:Grouping rows by day and month. Error by month between days 9 and 10 on every month按天和月对行进行分组。每月第 9 天到第 10 天之间的错误
【发布时间】:2021-10-30 10:53:08
【问题描述】:

所以我得到了这个脚本,它将读取我有日期的第 1 列,并将按月对所有行进行分组,并在其中按天对行进行分组。这是因为在每一天中,我每小时或 4 小时左右都有一排。

当脚本执行时,它将首先按天分组,然后按月分组。 执行月份分组部分时,当某个月份内有第9天和第10天时,将第9天的最后2行和第10天的前2行进行分组,不按月份分组。

如果列不包含第 9 天和第 10 天。假设我只有 16 到 31 天之间的数据,则不会发生此错误。

无法确定此脚本的问题所在。当有一个月的 9 号和 10 号时,如何防止月份分组出现此错误?

function groupRow() {

    const timeZone = "GMT+1";
    const sheet = SpreadsheetApp.getActiveSheet();
    const rowStart = 5;
    const rows = sheet.getLastRow() - rowStart + 1;
    const values = sheet.getRange(rowStart, 1, rows, 1).getValues().flat();
    const o = [];

    values.forEach((date, i) => {
        const [m, d] = Utilities.formatDate(date, timeZone, "yyyyMM,dd").split(",");
        if (!o[m]) {
            o[m] = [];
        }
        if (!o[m][d]) {
            o[m][d] = [];
        }
        o[m][d].push(rowStart + i);
    });

    var collator = new Intl.Collator([], {numeric: true});

    for (var m in o) {
     o[m] = Object.values(o[m]).sort((a,b) => parseInt(a) - parseInt(b));
    }

    Object.values(o).forEach(m => {
        for (const d of m) {
            if (d.length === 1) {
            continue;
            }
            const range = `${ d[1] }:${ d.slice(-1)[0] }`;
            sheet.getRange(range).shiftRowGroupDepth(1);
        }
        const a = m.flat();
        if (a.length === 1) {
            return;
        }
        const range = `${ a[1] }:${ a.slice(-1)[0] }`;
        sheet.getRange(range).shiftRowGroupDepth(1);
    });
}

这是虚拟文件的链接: https://docs.google.com/spreadsheets/d/1ExXtmQ8nyuV1o_UtabVJ-TifIbORItFMWjtN6ZlruWc/edit?usp=sharing

编辑: 实际上,如果我删除第 9 行的所有行,第 8 和第 10 仍然会发生错误。如果我删除了 10 日的所有行,则不会发生错误。好像是第10天连接到第一行的。

编辑2: 更新了代码,下面是 Yuri Khristich 给出的答案。

【问题讨论】:

    标签: google-apps-script google-sheets


    【解决方案1】:

    尝试以这种方式对您的 o 对象/数组进行排序:

    var collator = new Intl.Collator([], {numeric: true});
        
    for (var m in o) {
     o[m] = Object.values(o[m]).sort((a, b) => collator.compare(a, b));
    }
    

    代替:

    for (const m in o) {
      o[m] = Object.values(o[m]);
    }
    

    https://stackoverflow.com/a/57255344/14265469

    【讨论】:

    • 解决了问题!谢谢。
    • 其实更简单。它甚至不需要花哨的collator。你可以用更常用的方式对其进行排序:o[m] = Object.values(o[m]).sort((a,b) => parseInt(a) - parseInt(b));
    • 顺便说一句,我试图让这个脚本也按年分组。你知道我该怎么做吗?尝试添加 [y] 也 yyy,MM,dd 等,但似乎不起作用。也许我应该为此再问一个问题?
    • 老实说,您的算法相当复杂。我几乎无法猜出排序的事情。因此,我无法立即回答如何将其扩展到按年分组。我认为这个问题值得提出一个新问题。这里有比我更有经验的编码人员。并且可能添加标签JavaScript 是有意义的,因为代码的这个特定部分是纯JS,甚至不是GAS。并且标签 JavaScript 是一个相当热门的标签。
    【解决方案2】:

    您的电子表格设置(文件>设置)将时区设置为 GMT+00:00,并且您在 Utilities.formatDate 中使用 GMT+1

    【讨论】:

    • 我知道,但由于某种原因,如果我更改设置中的时区以匹配脚本中的时区,反之亦然,一天的第一行将与前一天分组。但这是另一个问题。如果我更改时区以匹配 9 日和 10 日的问题仍然存在。
    猜你喜欢
    • 1970-01-01
    • 2020-10-02
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    相关资源
    最近更新 更多