【问题标题】:Can change shape of range with ARRAYFORMULA() in Google Sheets?可以在 Google 表格中使用 ARRAYFORMULA() 更改范围的形状吗?
【发布时间】:2021-06-01 16:24:26
【问题描述】:

我的目的是将单行数据转换为由 Google 表格中特定数量的列组成的行。

例如,从原始数据开始:

A B C D E F
1 id1 attr1-1 attr2-1 id2 attr2-1 attr2-2

而预期的结果是: (将列除以三)

A B C
1 id1 attr1-1 attr1-2
2 id2 attr2-1 attr2-2

我已经知道可以手动进行一些操作,例如: =数组公式({A1:C1;D1:F1})

但是每次移动目标范围或需要更改子集大小(在上面的情况下是三个)时,我都必须重新开始!

所以我想会有一种更优雅的方式(即公式不需要手动更新)来做同样的事情,并且怀疑 ARRAYFORMULA() 是关键。

任何帮助将不胜感激!

【问题讨论】:

  • 关于您的实际应用程序甚至您的帖子示例的详细信息仍然不清楚。例如,您说您想要一个不需要手动更新的公式。但是,除非您在某处手动输入该信息,否则您现有的公式如何“知道”它应该将示例数据分成 3 列而不是 2 列(或 6 列)?原始数据是否总是只有一行?是否有一些“规则”应该适用于任何和所有尺寸的范围?该公式需要适应哪些不同的场景?了解现实世界的应用程序目标总是有帮助的。
  • 更多:“每次移动目标范围”是什么意思?它会如何移动?为什么?
  • @ErikTyler 非常感谢您的评论和建议! 1. 说“没有手动更新”我的意思是我想避免将参考范围 {A1:C1;D1:F1} 更改为 {A1:D1;E1:G1} 以防列数增加。 (而只是想知道是否可以将 3 或 4 作为公式中的参数。)
  • 2.如更新示例所示,原始数据是 id + 属性对。虽然 example 只包含其中的几个,但属性的总数不固定,并且没有可以与 split() 一起使用的分隔符。无论如何,数据将始终在一行中,并且可以水平扩展(取决于使用 importXML() 函数动态获取的记录数)。我想这个解释解决了你发布的其他问题!
  • 获得帮助的最有效和最有效的方法是分享指向您的电子表格的链接(或其副本,或包含足以传达问题的真实数据的模拟版本),确保将链接的共享权限设置为“知道链接的任何人...”和“编辑者”。这样,我们就可以亲眼看到数据和布局的真实样子。

标签: google-sheets


【解决方案1】:

我添加了一个新工作表(“Erik 帮助”),其中我将您手动输入的参数从两个减少到一个(在 A2 中只留下要输入的列数)。

重塑网格的公式:

=ArrayFormula(IFERROR(VLOOKUP(SEQUENCE(ROUNDUP(COUNTA(7:7)/A2),A2),{SEQUENCE(COUNTA(7:7),1),FLATTEN(FILTER(7:7,7:7<>""))},2,FALSE)))

SEQUENCE 用于根据在A2 中输入的任何内容来塑造网格。行数将是第 7 行中的项目数除以A2 中的数字(四舍五入到最接近的整数);列就是A2 中输入的任何数字。

示例:如果第 7 行有 11 项,并且您需要 4 列,则 ROUNDUP(11/4)=3 行到 SEQUENCE 和您请求的 4 列。

然后,网格中的每个数字都是VLOOKUP'ed 在一个虚拟数组中,该数组由与第 7 行(第 1 列)中的数据块数匹配的有序数字的垂直序列和一个 FLATTENed第 7 行数据本身的(垂直)版本(在第 2 列中)。匹配项被填充到原始的 SEQUENCE 网格中,而非匹配项由IFERROR留空

【讨论】:

    【解决方案2】:

    虽然有点乱,但无论如何都要感谢 SEQUENCE() 函数。 它通过接受行数/列数输入来构造一个网格,这正是我想要的。

    在此处设置包含示例数据的工作表以供参考: https://docs.google.com/spreadsheets/d/1p972tYlsPvC6nM39qLNjYRZZWGZYsUnGaA7kXyfJ8F4/edit#gid=0

    【讨论】:

      【解决方案3】:

      使用自定义公式

      虽然你已经解决了这个问题。如果您经常做这种事情,那么查看 Apps 脚本和自定义公式可能会有所帮助。

      在这种情况下,您可以使用以下内容:

      function transposeSingleRow(range, size) {
        // initialize new range
        let newRange = []
        // initialize counter to keep track
        let count = 0;
        // start while loop to go through row (range[0])
        while (count < range[0].length){
          // add a slice of the original range to the new range
          newRange.push(
            range[0].slice(count, count + size)
            );
          // increment counter
          count += size;
        }
        return newRange;
      }
      

      像这样工作:

      这里的公式的好处是您可以选择范围,然后输入一个数字来表示它的投掷,或者有多少元素组成一个完整的行。所以如果你有 4 个属性而不是 3 个属性,而不是调用:

      =transposeSingleRow(A7:L7, 3)
      

      你可以这样做:

      =transposeSingleRow(A7:L7, 4)
      

      此外,如果您希望此转换是永久性的,并且不依赖于公式重新计算。在不使用公式的情况下使其完全在 Apps 脚本中运行是必要的。

      参考

      【讨论】:

      • 非常感谢代码和示例!我肯定会考虑在我未来的项目中使用它,而我更愿意为此实例坚持基于公式的解决方案,因为它必须跨多个工作表使用。 (是的,我知道自定义公式也可以作为库发布,但现在已经足够了。)
      猜你喜欢
      • 2020-12-07
      • 2020-04-09
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多