在excel中查找一个值的范围
我有两个不同的工作表在Excel中有30万个数据。 第一张纸包含:
S2_Symbol Start_Pos End Position STE 254857 267891 PRI 748578 758962 ILA 852741 963369 VIS 789456 796325
第二:
S1_Location 789460 852898 748678
我的输出应该是这样的:
S1_Location Symbol 789460 VIS 852898 ILA 748678 PRI
我必须findS1_location
属于哪个S2_location
及其相应的符号。 我在Excel中使用了INDEX公式,但是对于每个单元格,我必须手动更改参考单元格。 我无法做到300,000个数据。
我如何在Excel中做或者我应该使用脚本?
该解决scheme假定如下:
-
每个
S2 Symbol
开始和结束位置是唯一的(即,分配给每个符号的范围之间不存在交集) -
第一张数据位于
A1:D17
(根据需要调整公式范围) - 第二张表格中的数据位于
A1:B300010
(根据需要调整公式中的范围)
解决scheme需要:
-
在工作表1中添加工作列。 在
D2
input该公式并复制到最后一个logging。=ROWS($A$1:$A2)
图。1
-
然后在第二张工作表中input这个公式,并复制到最后一个logging。
=INDEX( Sheet1!$A$1:$A$17, SUMIFS( Sheet1!$D$1:$D$17, Sheet1!$B$1:$B$17, "<=" & $A2, Sheet1!$C$1:$C$17, ">=" & $A2 ) )
图2
它采取了aprox。 小于14秒钟向下复制并计算表2中的公式。从图1和2中可以看出,没有任何表格需要sorting。
假设两张纸都以A1开始,而第一张纸栏B按升序sorting,在第二张纸B2中,请尝试:
=INDEX(First!A:A,MATCH(A2,First!B:B))
复制下来以适应。 它依赖于不精确的匹配。
假设我们有这样的Sheet1
:
请注意, Sheet1
按升序顺序按Start_Pos
, End_Pos
sorting。
和这样的Sheet2
:
那么Sheet2!B2
的公式可以是:
=INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-(10^-10),Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
请参阅MATCH
: https : //support.office.com/en-us/article/MATCH-function-e8dffd45-c762-47d6-bf89-533f4a37673a
这个想法是:没有精确匹配的匹配(没有参数match_type
)得到小于或等于search值的最大值的行。 所以在Start_Pos
列中将会得到我们可以获得S2_Symbol
。 但是,如果该值不在给定范围之外,则应该从End_Pos
列预先获得一行。
只有一个例外。 如果值是End_Pos
列中的值,则它将返回与Start_Pos
列中相同的行。 考虑到这个例外,我们可以在End_Pos
列中search一个稍小的值。 感谢Tom Sharpe对他的评论。
Sheet2!D2
的公式是:
{=INDEX(Sheet1!A:A,MIN(IF($A2>=Sheet1!$B$2:$B$300000,IF($A2<=Sheet1!$C$2:$C$300000,ROW(Sheet1!$A$2:$A$300000),2^20+1))))}
这是一个完全按照要求制定的数组公式。 但是,在许多单元中使用它的性能是非常糟糕的。 但是使用这个, Sheet1
不需要sorting。
基准testing:
有以下Sheet1
:
公式:
A2:A300002
: ="S"&(ROW(A1)-1)*10&"-"&(ROW(A1)-1)*10+7
B2:B300002
: =(ROW(A1)-1)*10
C2:C300002
: =B2+7
和下面的Sheet2
:
公式:
A2:A300002
: =RANDBETWEEN(0,3000007)
B2:B300002
: =INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-10^-9,Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
注意-10^-9
而不是-10^-10
在以前的版本。 这是因为我们只有16位数字的精度。 在以前的版本中,这是最多6位整数部分,然后是10位小数部分。 现在是最多7位整数部分,然后是9位数的小数部分。
在Sheet2
按F9
之后的计算需要约。 2秒。 (Excel 2007,Windows 7,4核心处理器)。
如果有的话,我会去这样的事情给你第一场比赛: –
=INDEX(First!A:A,MATCH(1,(First!B:B<=A2)*(First!C:C>=A2),0))
假设键和开始和结束值在名为First的表中,并且查找值以A2开始。
必须使用Ctrl Shift Enterinput的数组公式
针对@pnuts关于需要多长时间的问题,我已经在每张表中设置了一个30万行的类似基准,90分钟后达到了1%,所以要花费150个小时达到100%大概一个星期。 这是可以预料的,因为所需的计算次数是(表1中的行)X(表2中的行)
300,000 X 300,000
但事实上,因为乘法适用于完整的列,我相信它是更正确的
300,000 X 1,048,576
即> 300亿美元。
一个实际的版本,对较小的范围给予了很好的回应,如下所示:
我定义了三个命名范围Range1,Range2和Range3
=First!$A$1:INDEX(First!$A:$A,MATCH("ZZZ",First!$A:$A)) =First!$B$1:INDEX(First!$B:$B,MATCH(9.9E+307,First!$B:$B)) =First!$C$1:INDEX(First!$C:$C,MATCH(9.9E+307,First!$C:$C))
并修改公式是
=INDEX(Range1,MATCH(1,(Range2<=A2)*(Range3>=A2),0))
我正在考虑删除这个答案,但宁愿作为一个反例。