【问题标题】:Selecting the last value of a column选择列的最后一个值
【发布时间】:2011-05-09 08:49:29
【问题描述】:

我有一个电子表格,其中 G 列中有一些值。一些单元格之间是空的,我需要将该列中的最后一个值获取到另一个单元格中。

类似:

=LAST(G2:G9999)

除了 LAST 不是函数。

【问题讨论】:

    标签: google-apps-script google-sheets google-sheets-formula array-formulas custom-function


    【解决方案1】:

    与caligari's answer 类似,但我们可以通过指定完整的列范围来整理它:

    =INDEX(G2:G, COUNT(G2:G))
    

    【讨论】:

    • 只要数据集中没有空格,这似乎就可以工作
    • 另一个很好的资源是productforums.google.com/forum/#!topic/docs/p3t3feg7Jic 的选定答案,它显示了如何获取FILTER()ed 范围内的第一行、最后一行或第n 行,类似于@Geta's answer。
    • 这个答案stackoverflow.com/a/8161172/418111 有一个支持空白单元格的公式。
    • 正如@KeithSirmons 提到的。如果您的列中有空格,它不起作用,因为COUNT(G2:G) 返回 0。而是使用COUNTA(G2:G),它只计算数据集中值的数量。 COUNTA 仅在与 INDEX 结合使用时才能在您的值之间没有一个空格时获得最后一个值。
    • 另请注意,如果您的值不是数字,则需要COUNTA。 COUNT 只计算数值:给定时它将返回 0,例如文本单元格。
    【解决方案2】:

    所以这个解决方案将一个字符串作为它的参数。它找出工作表中有多少行。它获取指定列中的所有值。它从末尾到开头循环遍历值,直到找到一个不是空字符串的值。最后它返回值。

    脚本:

    function lastValue(column) {
      var lastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
      var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + lastRow).getValues();
    
      for (; values[lastRow - 1] == "" && lastRow > 0; lastRow--) {}
      return values[lastRow - 1];
    }
    

    用法:

    =lastValue("G")
    

    编辑:

    回应要求自动更新功能的评论:

    我能找到的最好方法是使用上面的代码:

    function onEdit(event) {
      SpreadsheetApp.getActiveSheet().getRange("A1").setValue(lastValue("G"));
    }
    

    不再需要像 Usage 部分所述在单元格中使用该函数。相反,您对要更新的单元格和要跟踪的列进行硬编码。可能有一种更雄辩的方式来实现这一点(希望不是硬编码的),但这是我目前能找到的最好的方式。

    请注意,如果您如前所述在单元格中使用该功能,它将在重新加载时更新。也许有一种方法可以连接到onEdit() 并强制单元格函数更新。我只是在文档中找不到它。

    【讨论】:

    • 这是一个 Google 电子表格脚本。你可以在Tools -> Scripts -> Script editor...下新建一个脚本
    • :哦,太棒了!我不知道谷歌已经实现了脚本。非常感谢,效果很好
    • 知道如何在我更改工作表中的数据时使其自动更新吗?
    • 我用一些应该有帮助的信息编辑了我的答案。编码愉快!
    • 我已对此脚本进行了编辑,因此您可以将命名的工作表传递给它,例如 lastValue("Sheet1!A") gist.github.com/2701061
    【解决方案3】:

    其实我在这里找到了一个更简单的解决方案:

    http://www.google.com/support/forum/p/Google+Docs/thread?tid=20f1741a2e663bca&hl=en

    看起来像这样:

    =FILTER( A10:A100 , ROW(A10:A100) =MAX( FILTER( ArrayFormula(ROW(A10:A100)) , NOT(ISBLANK(A10:A100)))))
    

    【讨论】:

    • 哇,这太干净了。你能解释一下它是如何工作的吗?
    • 并非如此:仅当源范围已排序时才正确。
    • 解释:ROW返回行号,所以FILTER( ROW(A10:A100), NOT(ISBLANK(A10:A100) )返回所有非空行号(不是它们的值)的数组,例如[1,2,3,7, 12、14]。然后MAX 给我们最后的行号。然后应用第二个FILTER 过滤掉行号与MAX 中的值不匹配的所有行(即最后一个非空白行的值)。
    • ROW 的两个实例都可以用 COLUMN 替换,以返回特定行中的最后一个值(而不是特定列中的最后一个值)。
    • 如果我只想要列的最后一个值的行号怎么办?
    【解决方案4】:

    LAST() 函数目前未实现以选择范围内的最后一个单元格。但是,按照您的示例:

    =LAST(G2:G9999)
    

    我们可以通过这种方式使用 INDEX() 和 COUNT() 这两个函数来获取最后一个单元格:

    =INDEX(G2:G; COUNT(G2:G))
    

    在电子表格中有一个 live example,我发现(并解决了)同样的问题(表格Orzamentos,单元格I5)。请注意,即使引用文档中的其他工作表,它也能完美运行。

    【讨论】:

    • 这很好用,并且会随着工作表的变化而自动更新。谢谢!
    • 我喜欢这个建议的简洁性,但是当目标范围包含一些空白单元格时(如上面原始问题中所述),它似乎不起作用,因为 COUNT() 不计算在内空白单元格。
    • @JonSchneider 如果您确定列中的值之间没有一个空格,则可以在这种情况下使用COUNTA。请参阅我的 cmets 以了解 dohmoose 的答案。
    • 为什么:G 表示最后一个元素?这有记录吗?
    【解决方案5】:

    总结:

    =INDEX( FILTER( G2:G , NOT(ISBLANK(G2:G))) , COUNTA(G2:G) )
    

    详情:

    我已经查看并尝试了几个答案,这就是我发现的: 如果没有空格,最简单的解决方案(请参阅Dohmoose' answer)有效:

    =INDEX(G2:G; COUNT(G2:G))
    

    如果有空格,则失败。

    您只需将COUNT 更改为COUNTA 即可处理一个空白(参见user3280071's answer):

    =INDEX(G2:G; COUNTA(G2:G))
    

    但是,对于某些空白组合,这将失败。 (1 blank 1 blank 1 对我来说失败了。)

    以下代码有效(参见Nader's answer 和jason's comment):

    =INDEX( FILTER( G2:G , NOT(ISBLANK(G2:G))) , ROWS( FILTER( G2:G , NOT(ISBLANK(G2:G)) ) ) )
    

    但这需要考虑是否要在给定范围内使用COLUMNS 或ROWS。

    但是,如果将COLUMNS 替换为COUNT,我似乎得到了LAST 的可靠、无空白的实现:

    =INDEX( FILTER( G2:G , NOT(ISBLANK(G2:G))) , COUNT( FILTER( G2:G , NOT(ISBLANK(G2:G)) ) ) ) 
    

    由于COUNTA 内置了过滤器,我们可以进一步简化使用

    =INDEX( FILTER( G2:G , NOT(ISBLANK(G2:G))) , COUNTA(G2:G) )
    

    这有点简单,而且是正确的。而且您不必担心是否计算行数或列数。与脚本解决方案不同,它会随着电子表格的更改自动更新。

    如果要获取一行中的最后一个值,只需更改数据范围即可:

    =INDEX( FILTER( A2:2 , NOT(ISBLANK(A2:2))) , COUNTA(A2:2) )
    

    【讨论】:

    • 对遍历每个迭代的步骤和功能+限制非常有帮助。我需要获取每行中的最后一个值,其中一些包含多个空格。这就像一个魅力。谢谢!
    【解决方案6】:

    为了从一列文本值中返回最后一个值,您需要使用 COUNTA,因此您需要以下公式:

    =INDEX(G2:G; COUNTA(G2:G))
    

    【讨论】:

    • 但前提是您的值之间没有一个空格。如果有,COUNTA 结合 INDEX 将不会返回列中的最后一个值。
    【解决方案7】:

    这个对我有用:

    =INDEX(I:I;MAX((I:I<>"")*(ROW(I:I))))
    

    【讨论】:

    • 一个很好的解决方案,它也适用于空单元格。
    【解决方案8】:

    试试这个: =INDIRECT("B"&amp;arrayformula(max((B3:B&lt;&gt;"")*row(B3:B))))

    假设您要在其中查找最后一个值的列是 B。

    是的,它适用于空白。

    【讨论】:

      【解决方案9】:

      Google Apps 脚本现在似乎支持范围作为函数参数。此解决方案接受一个范围:

      // Returns row number with the last non-blank value in a column, or the first row
      //   number if all are blank.
      // Example: =rowWithLastValue(a2:a, 2)
      // Arguments
      //   range: Spreadsheet range.
      //   firstRow: Row number of first row. It would be nice to pull this out of
      //     the range parameter, but the information is not available.
      function rowWithLastValue(range, firstRow) {
        // range is passed as an array of values from the indicated spreadsheet cells.
        for (var i = range.length - 1;  i >= 0;  -- i) {
          if (range[i] != "")  return i + firstRow;
        }
        return firstRow;
      }
      

      另请参阅 Google Apps 脚本帮助论坛中的讨论:How do I force formulas to recalculate?

      【讨论】:

        【解决方案10】:

        我看了以前的答案,他们似乎工作太努力了。也许脚本支持只是简单地改进了。我认为函数是这样表达的:

        function lastValue(myRange) {
            lastRow = myRange.length;
            for (; myRange[lastRow - 1] == "" && lastRow > 0; lastRow--)
            { /*nothing to do*/ }
            return myRange[lastRow - 1];
        }
        

        然后在我的电子表格中使用:

        = lastValue(E17:E999)
        

        在函数中,我得到一个值数组,每个引用的单元格都有一个值,这只是从数组的末尾向后迭代,直到找到一个非空值或用完元素。在将数据传递给函数之前,应解释工作表引用。也不够花哨,无法处理多维度。这个问题确实要求单列中的最后一个单元格,所以它似乎很合适。如果您也用完数据,它可能会死掉。

        您的里程可能会有所不同,但这对我有用。

        【讨论】:

          【解决方案11】:
          function lastRow(column){
            var sheet = SpreadsheetApp.getActiveSpreadsheet();
            var lastRow = sheet.getLastRow();
            var lastRowRange=sheet.getRange(column+startRow);
            return lastRowRange.getValue();
          }
          

          没有硬编码。

          【讨论】:

            【解决方案12】:

            这会获取最后一个值并处理空值:

            =INDEX(  FILTER( H:H ; NOT(ISBLANK(H:H))) ; ROWS( FILTER( H:H ; NOT(ISBLANK(H:H)) ) ) )
            

            【讨论】:

            • 也适用于列。我只是替换了一些东西。 =INDEX( FILTER( 88:88 , NOT(ISBLANK(88:88))) , columns( FILTER( 88:88 , NOT(ISBLANK(88:88)) ) ) )
            • 通用解决方案:=INDEX( FILTER( indirect(row()&amp;":"&amp;row()) , NOT(ISBLANK(indirect(row()&amp;":"&amp;row())))) , columns( FILTER( indirect(row()&amp;":"&amp;row()) , NOT(ISBLANK(indirect(row()&amp;":"&amp;row()))) ) ) )
            • 对我来说,这是“正确”的答案。相当紧凑且易于理解,并且适用于空白。
            【解决方案13】:

            在有空格的列中,可以用

            获取最后一个值
            =+sort(G:G,row(G:G)*(G:G<>""),)
            

            【讨论】:

            • 一个不错的解决方案。不过,我怀疑@Pedro 的变体(使用 INDEX 和 MAX)可能比使用 SORT 更有效。
            【解决方案14】:

            答案

            $ =INDEX(G2:G; COUNT(G2:G))
            

            在 LibreOffice 中无法正常工作。不过,只要稍加改动,就可以完美运行。

            $ =INDEX(G2:G100000; COUNT(G2:G100000))
            

            只有当真实范围小于(G2:G10000)时它总是有效的

            【讨论】:

            • 这篇文章被标记为“Google 电子表格”和“Google Apps 脚本”,与 Libre Office 无关……你跑题了
            • 问题的标题,选择列的最后一个值,并不十分离题,很容易被一些使用 LibreOffice 或 Numbers 的可怜人找到。我是一个电子表格爱好者,知道足够危险。我可以收集到的是,谷歌已经做到了,如果你对一个范围的第二个参数只是一个列,它会选择该列的其余部分,这样人们就不必使用你发现的非常大的数字。跨度>
            【解决方案15】:

            用严格的题外话回答原始问题是否可以接受:) 您可以在电子表格中编写一个公式来执行此操作。也许丑?但对电子表格的正常操作有效。

            =indirect("R"&ArrayFormula(max((G:G<>"")*row(G:G)))&"C"&7)
            
            
            (G:G<>"") gives an array of true false values representing non-empty/empty cells
            (G:G<>"")*row(G:G) gives an array of row numbers with zeros where cell is empty
            max((G:G<>"")*row(G:G)) is the last non-empty cell in G
            

            这是对脚本领域中一系列问题的思考,这些问题可以使用数组公式可靠地传递,这些公式的优点是经常在 excel 和 openoffice 中以类似的方式工作。 p>

            【讨论】:

              【解决方案16】:
              function getDashboardSheet(spreadsheet) {
                var sheetName = 'Name';
                return spreadsheet.getSheetByName(sheetName);
              }
                    var spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);  
                    var dashboardSheet = getDashboardSheet(spreadsheet);
                    Logger.log('see:'+dashboardSheet.getLastRow());
              

              【讨论】:

                【解决方案17】:

                我正在使用@tinfini 提供的代码,并认为人们可能会从我认为稍微更优雅的解决方案中受益(请注意,当他创建原始答案时,我认为脚本的工作方式并不完全相同)。 ..

                //Note that this function assumes a single column of values, it will 
                //not  function properly if given a multi-dimensional array (if the 
                //cells that are captured are not in a single row).
                
                function LastInRange(values) 
                {
                  for (index = values.length - 1; values[index] == "" && index > 0; index--) {}
                  return String(values[index]);
                }
                

                在使用中它看起来像这样:

                =LastInRange(D2:D)
                

                【讨论】:

                  【解决方案18】:

                  关于@Jon_Schneider 的评论,如果该列有空白单元格,请使用 COUNTA()

                  =INDEX(G2:G; COUNT**A**(G2:G))
                  

                  【讨论】:

                  • 不,这也不起作用。 COUNT 和 COUNTA 的区别在于数字和文本的区别,这里不相关。
                  【解决方案19】:

                  我找到了另一种方法可能对你有帮助

                  =INDEX( SORT( A5:D ; 1 ; FALSE) ; 1 ) - 将返回最后一行

                  来自 anab 的更多信息: https://groups.google.com/forum/?fromgroups=#!topic/How-to-Documents/if0_fGVINmI

                  【讨论】:

                  • 并非如此:仅当源范围已排序时才正确。
                  【解决方案20】:

                  发现了一个细微的变化,可以消除表格底部的空白。 =index(G2:G,COUNTIF(G2:G,""))

                  【讨论】:

                    【解决方案21】:

                    我很惊讶以前没有人给出过这个答案。但这应该是最短的,甚至可以在 excel 中使用:

                    =ARRAYFORMULA(LOOKUP(2,1/(G2:G<>""),G2:G))
                    

                    G2:G&lt;&gt;"" 创建一个由 1/true(1) 和 1/false(0) 组成的数组。由于LOOKUP 采用自上而下的方法来查找2,并且由于它永远不会找到2,所以它会到达最后一个非空白行并给出它的位置。

                    正如其他人可能提到的那样,另一种方法是:

                    =INDEX(G2:G,MAX((ISBLANK(G2:G)-1)*-ROW(G2:G))-1)
                    

                    找到非空白行的MAXimum ROW并将其提供给INDEX

                    在零空白中断数组中,使用INDIRECT RC 符号和COUNTBLANK 是另一种选择。如果 V4:V6 被条目占用,那么,

                    V18:

                    =INDIRECT("R[-"&COUNTBLANK(V4:V17)+1&"]C",0)
                    

                    会给出V6的位置。

                    【讨论】:

                      【解决方案22】:

                      要从列中获取最后一个值,您还可以使用 MAX 函数和 IF 函数

                      =ARRAYFORMULA(INDIRECT("G"&MAX(IF(G:G<>"", ROW(G:G), )), 4)))
                      

                      【讨论】:

                        【解决方案23】:

                        对于特定列,我已经经历了太多最后一行的实现。许多解决方案都有效,但对于大型或多个数据集来说速度很慢。我的一个用例要求我检查多个电子表格中特定列的最后一行。我发现将整个列作为一个范围然后迭代它太慢了,将其中的一些加在一起会使脚本变得迟缓。

                        我的“hack”是这个公式:

                        =ROW(index(sheet!A2:A,max(row(sheet!A2:A)*(sheet!A2:A<>""))))-1
                        
                        • 示例:将此添加到单元格 A1,以查找 A 列中的最后一行。可以添加到任何地方,只需确保根据放置公式的行来管理末尾的“-1”。您也可以将其放置为另一个列,而不是您要计数的列,并且您不需要管理 -1。您还可以从起始行开始计数,例如“C16:C” - 将从 C16 开始计数值

                        • 这个公式可靠地给了我最后一行,包括数据集中间的空白

                        • 要在我的 GS 代码中使用这个值,我只是从 A1 中读取单元格值。我知道 Google 很清楚读/写等电子表格功能很繁重(耗时),但根据我的经验(对于大型数据集),这比列计数最后一行方法快得多

                        • 为了提高效率,我在 col 中获取最后一行,然后将其保存为全局变量并在我的代码中递增以跟踪我应该更新哪些行。每次循环需要进行更新时读取单元格的效率太低了。读取一次,迭代值,A1 单元格公式(上图)将“存储”更新后的值以供下次函数运行时使用

                        如果这对您有帮助,请告诉我!如果我遇到任何问题,我会对此答案发表评论。

                        【讨论】:

                        • 我认为使用辅助单元格是一种节省时间的好方法,无需重新计算昂贵的操作。
                        • 我很好奇公式本身的性能。我想知道使用更多的内置函数是否比算术运算更高效。例如,我想知道这在性能方面如何比较:=MATCH(1, ARRAYFORMULA(IF(ISBLANK(sheet!A2:A), #N/A, 0)))
                        • 我的想法是 MAX 需要检查每个单元格,而 MATCH 可能会在其输入范围已排序的假设下短路(如果它只有零,因为#N/A 在我观察到的比赛中不考虑错误)。我假设ARRAYFORMULA 评估是懒惰地完成的,MATCH 会进行某种二进制搜索扫描,相当早地测试行/列的最后一个条目,但我不知道这些假设是否正确。跨度>
                        猜你喜欢
                        • 1970-01-01
                        • 2012-05-14
                        • 2013-08-22
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-12-07
                        • 1970-01-01
                        相关资源
                        最近更新 更多