[英]How to count consecutive values in Excel?
此时我有这个计算连续值的公式:
=IF(AB5=0;0;IF(OR(AND(AB4>=100;AB5>=100);AND(AB4<=-100;AB5<=-100));AC4+1;1))
基本上这样做:
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
但我希望它能做到这一点:
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
或这个:
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
使这成为可能的公式是什么?
我不想添加更多列,因为文件已经很大...
仅使用公式来做这件事是最好的事情。
谢谢。
您可以尝试这样的匹配公式:
=IF(AND(ABS(AB5)>=100,AB4=0),MATCH(0,AB6:AB$1048576,0),0)
编辑
显然,1,000,000个细胞的速度很慢。 不精确的匹配更快:
=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))
讨论
为什么Match在表面上这么慢,它应该只搜索前面几个单元格来匹配? 我想知道是否因为Match将要搜索的整个范围复制到临时数组? 通常这可能是一个很好的策略,但在特定情况下,当匹配值接近范围的开头并且范围非常大时,它是一个糟糕的策略。
另一种可能的方法是使用频率确定最长的序列(这很快),然后使用索引来限制要搜索的范围,例如:
=MAX(FREQUENCY(IF(ABS(A:A)>=100,ROW(A:A)),IF(A:A=0,ROW(A:A))))
然后在B1
...MATCH(0,AB6:INDEX(A:A,ROW()+B$1),0)
我不知道如何用excel解决你的问题,它可能是用一些数组公式来完成的,这会大大减慢你现在速度很慢的工作簿。 因此我写了一个VBA版本。
在使用它之前,您应该仔细更改前三个变量的值以满足您的需要。
将以下代码放入模块中 :
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
然后将以下代码放在工作表的代码窗口中 :
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
代码会自动更改目标列中单元格的值,而在结果单元格中没有任何公式应该使它非常快。 如果不是这种情况,可以编写一个数组版本,这将使代码速度提高几十倍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.