本帖最后由 aaaaaa123459 于 2011-10-11 23:24 编辑
由于几位反对我的网友批判我解析的很烂,所以想把公式都删除了,但想起来对不起方版,所以此公式解析保留一个吧!
版主给出的第一个公式是附件中原问题第1问的公式,用来返回第n个“人”字的单元格,公式为:
=ADDRESS(1,LOOKUP(ROW(A1)-1,COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),COLUMN(A:AK))+1)
公式解读:
首先,确定行标:
我们求的单元格地址都在第一行,所以行标是1,用ADDRESS(1,列标),中的1是固定的,关于列标,通过下面的过程求出。
其二、求列标的过程
⑴其中COLUMN(A:AK)产生A列到AK列的列数形成的数组{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}。
⑵OFFSET(数据源!A$1,,,,COLUMN(A:AK)) 返回由37个向量a1,a1:b1,a1:c1……a1:AK1.
我需要说明一下,我对三维引用的理解就是多个向量组合。至少我认为两者是等效的。
⑶COUNTIF()查找37个向量中包含“人”字的个数,形成37个数组元素,组成新的以每个向量包含“人”字个数的新数组:
{0,1,1,1,2,2,2,2,3,4,4,4,5,6,7,8,9,10,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12},也就是第一个向量A1中包含着0个“人”字,第二个向量A1:B1包含着1个“人”字,……到第5个向量A1:E1时才开始包含有2个“人字”……最后一个向量a1:ak1中包含12个“人”字,这样,第n个向量与对应包含“人”个数的关系,我们把两个数组对应起来就好说了,
{0,1,1,1,2,2,2,2,3,4, 4, 4, 5, 6, 7, 8, 9, 10,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12}→人数
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}→第n向量
上面为了一一对应,我把“人”个数数组的空间进行了调整,不能直接引用到公式中的。
我们可以看出,“人数”数组中的元素大小每发生变动的时候的元素x,其对应“第n向量"数组的对应元素y所代表的数就是包含第x个“人”字的单元格的列标。所以下面的任务就是找到“人数”数组中元素发生变化(+1)后的元素,毫无疑问,LOOKUP()有这个功能,在第一个数组中COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),寻找“人”字对应的位置,然后返回对应数组COLUMN(A:AK)中对应的列标,不过等一下,LOOKUP()在寻找的时候,要求第一数组升序,这个没有问题,COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),就是按升序排列的,接着看LOOKUP()的第二个特点,搜寻……,这样说没有针对性,我把问题作一个特殊情况具体化一下,通过案例理解可能会更好,如LOOKUP(2,{0,1,1,1,2,2,2,2,3,4,4,4,5,6,7,8,9,10,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12},{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}),LOOKUP()
首先在{0,1,1,1,2,2,2,2,3,4,4,4,5,6,7,8,9,10,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12}寻找2,它会按升序检查完数组,返回小于等于2的最后一个元素的位置,也就是下一个将不再是小于等于2的前一个数的位置,这也是LOOKUP()
函数需要参数中第一数组升序的原因,我们看到数组中有4个2,它会返回最后一个2的位置8,而不是第一个2的位置5,所以返回的位置后面的元素正好开始+1,也就是对应又一个“人”字的位置,也就是第3个“人字的位置”,受此特点要求,我们要搜索第n个“人”字的位置就得先在“人数”数组中搜寻n-1的位置,然后把位置+1就是第n个“人字的位置”,当然这个位置的返回由第二个数组来完成,也就是由数组{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37}返回n-1的位置,即LOOKUP(ROW(A1)-1,COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),COLUMN(A:AK)),再把LOOKUP()的返回值+1即可,也就是用LOOKUP(ROW(A1)-1,COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),COLUMN(A:AK))+1返回第n个“人”字的列标,那么n怎么来设定,我们想到了把row(a1)当成n,公式向下拉就可以返回从1,2,3……12,当然这是n,我们要搜寻n-1,所以LOOKUP()的第一个参数自然就是row(a1)-1,这样就可以把第n个包含“人”字的列标数求出了。
第三、返回地址文本。
知道了行标(固定为1)和列标(⑶中的结果)最后,通过ADDRESS()函数返回第n个“人”字所在单元格地址的文本。
所以最后的公式就是:
=ADDRESS(1,LOOKUP(ROW(A1)-1,COUNTIF(OFFSET(数据源!A$1,,,,COLUMN(A:AK)),"*人*"),COLUMN(A:AK))+1)
这样细化不知道哆嗦不!
其它类似的求 第n个“数字、英文、空格……”单元格地址的公式不再解读,请大家思考!
|