简体   繁体   English

如何计算Excel中的连续值?

[英]How to count consecutive values in Excel?

At this moment I have this formula that counts consecutive values: 此时我有这个计算连续值的公式:

=IF(AB5=0;0;IF(OR(AND(AB4>=100;AB5>=100);AND(AB4<=-100;AB5<=-100));AC4+1;1))

Basically it does this: 基本上这样做:

0           0
0           0
-110        1
-110        2
-110        3
-100        4
0           0
0           0
0           0
130         1
150         2
0           0
0           0
-100        1
0           0
0           0
0           0
0           0
-110        1
0           0
0           0
0           0
-220        1
-150        2
0           0
0           0

But I want it to do this: 但我希望它能做到这一点:

0           0
0           0
-110        0
-110        0
-110        0
-100        4
0           0
0           0
0           0
130         0
150         2
0           0
0           0
-100        1
0           0
0           0
0           0
0           0
-110        1
0           0
0           0
0           0
-220        0
-150        2
0           0
0           0

Or this: 或这个:

0           0
0           0
-110        4
-110        0
-110        0
-100        0
0           0
0           0
0           0
130         2
150         0
0           0
0           0
-100        1
0           0
0           0
0           0
0           0
-110        1
0           0
0           0
0           0
-220        2
-150        0
0           0
0           0

What is the formula to make this possible ? 使这成为可能的公式是什么?

I prefer not to have to add more columns since the file is already big... 我不想添加更多列,因为文件已经很大...

Using only a formula to do this would be the best thing to do. 仅使用公式来做这件事是最好的事情。

Thanks. 谢谢。

You could try a match formula like this: 您可以尝试这样的匹配公式:

=IF(AND(ABS(AB5)>=100,AB4=0),MATCH(0,AB6:AB$1048576,0),0)

EDIT 编辑

Clearly this is slow for 1,000,000 cells. 显然,1,000,000个细胞的速度很慢。 The inexact match is faster: 不精确的匹配更快:

=IF(AND(AB5>=100,AB4=0),MATCH(0,AB6:AB$1048576,-1),IF(AND(AB5<=-100,AB4=0),MATCH(-100,AB5:AB$1048576,1),0))

在此输入图像描述

Discussion 讨论

Why is Match so slow when on the face of it, it should be only searching a few cells ahead for a match? 为什么Match在表面上这么慢,它应该只搜索前面几个单元格来匹配? I am wondering if it is because Match copies the whole range to be searched to a temporary array? 我想知道是否因为Match将要搜索的整个范围复制到临时数组? Generally this might be a good strategy, but in the particular case when the matching value is near the beginning of the range and the range is very large, it is a bad one. 通常这可能是一个很好的策略,但在特定情况下,当匹配值接近范围的开头并且范围非常大时,它是一个糟糕的策略。

One more possible approach would be to determine the longest sequence using Frequency (this is fast), then limit the range to be searched using Index, something like: 另一种可能的方法是使用频率确定最长的序列(这很快),然后使用索引来限制要搜索的范围,例如:

=MAX(FREQUENCY(IF(ABS(A:A)>=100,ROW(A:A)),IF(A:A=0,ROW(A:A))))

in B1 then 然后在B1

...MATCH(0,AB6:INDEX(A:A,ROW()+B$1),0)

Consecutive counting Version 1 连续计数版本1

I don't know how to solve your problem with excel, it could be probably done with some array formula which would drastically slow down your even now slow workbook. 我不知道如何用excel解决你的问题,它可能是用一些数组公式来完成的,这会大大减慢你现在速度很慢的工作簿。 Therefore I have written a VBA version. 因此我写了一个VBA版本。
Before you use it you should carefully change the values of the first three variables to fit your needs. 在使用它之前,您应该仔细更改前三个变量的值以满足您的需要。
Put the following code into a module : 将以下代码放入模块中

Option Explicit
'-- Customize BEGIN --------------------

  'Read data from this column, and write to the next, e.g.
  'The AB column is column 28: Read from 28 and write to 29
  Public Const ciCol As Integer = 6

  'The first row of data
  Public Const cLoFirstRow As Long = 5

  'cLoRow is an approximate value e.g. you have 200 rows of data and you
  'estimate that you won't have more than a 1000 in a year, than 1000 is enough,
  'if you have a million then put in a million. The smaller this number the
  'faster the code.
  Public Const cLoRow As Long = 1000
'-- Customize END ----------------------

Sub ConsecutiveCounting1()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'-- Customize BEGIN --------------------
  'The Abs function eliminates the need for a negative value variable.
  Const cLoLimit As Long = 100
'-- Customize END ----------------------
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  Dim oRng As Range
  Dim loLastRow As Long
  Dim loTemp As Long
  Dim loF1 As Long 'Row Counter
  loLastRow = Cells(Rows.Count, ciCol).End(xlUp).Row
  Set oRng = Range(Cells(cLoFirstRow, ciCol), Cells(loLastRow, ciCol))
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  loTemp = 0
  For loF1 = 1 To oRng.Rows.Count
    If loF1 <> oRng.Rows.Count Then
      If Abs(oRng(loF1, 1)) >= cLoLimit Then
        loTemp = loTemp + 1
        If Abs(oRng(loF1 + 1, 1)) >= cLoLimit Then
          oRng(loF1, 2) = 0
         Else
          oRng(loF1, 2) = loTemp
          loTemp = 0
        End If
       Else
        oRng(loF1, 2) = 0
      End If
     Else 'Last Value
      If Abs(oRng(loF1, 1)) >= cLoLimit Then
        loTemp = loTemp + 1
        oRng(loF1, 2) = loTemp
       Else
        oRng(loF1, 2) = 0
      End If
    End If
  Next
End Sub

And then put the following code in the sheet's code window : 然后将以下代码放在工作表的代码窗口中

Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim ColumnNumber As Long
  Dim RowNumber As Long
    ColumnNumber = Target.Column
    RowNumber = Target.Row
    If ColumnNumber <> ciCol Then Exit Sub
    If RowNumber > cLoRow Then Exit Sub
  ConsecutiveCounting1
End Sub

The code automatically changes the value of the cell in the target column without any formula in the resulting cells what should make it very fast. 代码会自动更改目标列中单元格的值,而在结果单元格中没有任何公式应该使它非常快。 If this isn't the case, an array version could be written, which would make the code dozens of times faster. 如果不是这种情况,可以编写一个数组版本,这将使代码速度提高几十倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM