EXCEL 求教大神,解析一下这个公式的含义,越详细越好

=IFERROR(SMALL(IF(TEXT(ROW(INDIRECT(DATE(LEFT(P7,4),1,1)&":"&DATE(LEFT(P7,4),12,31))),"[$-130000]YYYY-M-D")=P7,ROW(INDIRECT(DATE(LEFT(P7,4),1,1)&":"&DATE(LEFT(P7,4),12,31))),""),1),SMALL(IF(TEXT(ROW(INDIRECT(DATE(LEFT(P7,4)+1,1,1)&":"&DATE(LEFT(P7,4)+1,12,31))),"[$-130000]YYYY-M-D")=P7,ROW(INDIRECT(DATE(LEFT(P7,4)+1,1,1)&":"&DATE(LEFT(P7,4)+1,12,31))),""),1)),这是一个数组公式,P7内容是文本1999-12-7

这是一个农历转公历的公式,但因为农历的复杂性,特别是润月的存在,更加难以用较简单的公式来完成。

TEXT配合"[$-130000]YYYY-M-D",就是把公历转换为农历。但这个特定的[$-130000]参数存在有局限性,转换结果可能出错。
公式的思路是这样的:取出P7中的年份,用DATE配合ROW形成从该年的1月1日到12月31日的数组:
ROW(INDIRECT(DATE(LEFT(P7,4),1,1)&":"&DATE(LEFT(P7,4),12,31)))
再用TEXT配合参数[$-130000]YYYY-M-D",将该年的所有日期转换为农历。
IF来判断转换后的农历日期是否有与P7相等的,如果P7中的农历日期不是接近年底,那么必有一个,也只有一个年份与农历相同的公历日期转换为农历后与P7中的农历日期是相同的。相同的就取得这个公历日期。其余所有不相同的日期就都取空。
所以,IF的结果是:一个数字(公历日期数)和364(润年为365)个空(“”),然后用SMALL的第1个来提取这个唯一的数字,其实用MIN可能好理解些。
而如果农历是接近年底的日期,如提问中的十二月初七日,转换为公历后,年份就到下一年了,针对于提问,就是到2000年。那么1999年的365天转换为农历后就是1998年十二月到199年十一月的日期了,没有与P7相同的日期。上面所说的SMALL就取不到数据,结果为#NUM!,所以公式用了IFERROR,用第2个SMALL来求这个公历日期,显然,这种情况下年份到了下一年,于是公式与第1个SMALL基本相同,只是把P7中的年份数加上1,来看2000年的哪一天转换为农历后与P7相同。由此可见,第2个SMALL是没必要从1月1日到12月31日全年来转换后比较的,最多到2月底就够了,最极端的情况,公历的月份也会不超过农历2个月的。
根据上面的分析,用下面的公式不仅要简单得太多,而且也更容易理解:
=LOOKUP(--P7,--TEXT(P7+ROW(10:60),"[$-130000]yyyy-m-d"),P7+ROW(10:60))
公式的思路就是从P7中的日期开始,往后推10到60天,将此范围内的日期转换为农历日期,再用LOOKUP查找P7在这些转换后日期中的位置,返回对应的公历日期。无论如何,公历日期不可能比农历只后10天以内或在60天以外的,所以公式可以确保不会出现#NUM!。公式计算量仅计算日期就不到原公式的1/12,再加上原公式用IF、SMALL嵌套,都相当消耗资源,而本公式用LOOKUP,是二分法查找。所以本公式的效率比原公式提高至少两个数量级以上。
附带说一下,网上有很多介绍公历和农历互转的,本问题的公式中用的方法是其中之一,也是相对比较简单的,仅一个TEXT的格式参数。但准确性也是难以保证的。本人所看到的方法中,比较可靠的是:在可能要转换的若干年份内,用一个工作表列出每个农历年十二个月或十三个月(有润月的年)初一对应的公历日期,这样用VLOOKUP配合其他函数来查询,就能保证查询的结果准确。
希望上面的分析能帮助你来解读公式。当然上面的分析,是假设你对DATE、SMALL、TEXT等函数有最基本的了解,就没有一步一步去详细分析DATE等函数了。追问

跪了,大神!拜读,受益良多。日后望多多指教。

温馨提示:答案为网友推荐,仅供参考
相似回答