最長不倒関数

電算関係の古いファイルを整理していたら,面白い(懐かしい?)資料を発掘しました。
 ここのところ,技術から少し離れた内容が続いていますが,今回は一応 Excel ネタです


確か Windows3.1 Windows95 が主流の時代だったので,1996〜1997年頃の事だったと思います。
Excel でいえば Version5.0 辺りの時代ですね。

細かな経緯は忘れてしまったのですが,会社の女の子に” Excel でこういう処理はできないか?”と相談されて,”できない”とは言えず,意地になって作ったのが今回の関数です。
 まず,ワークシート上に以下のようにデータが並んでいるとします。

行7
列A
列B
列C
行8
5
10
805
行9
4
20
109
行10
3
30
301
行11
2
40
604
行12
1
50
701
行13
9
60
204
行14
8
70
111
行15
7
80
901
行16
6
90
16
行17
---
---
7

ここで,セルC17には次のような関数が入力されています。

=INDIRECT(ADDRESS(MATCH(MAX(C8:C16),C8:C16,FALSE)-10,-2,4,FALSE),FALSE)

この関数がどのような処理をしているかすぐに分かりますか?
 処理の手順を以下に解説します。

 まず, MAX(C8:C16) で列Cの行8から行16の範囲の最大値を探していますので,これに対応する数値は901です。

 次に, MATCH(MAX(C8:C16),C8:C16,FALSE) で列Cで901となる配列の位置を探しています。901は上から8番目になるので,これに対応する数値は8です。

 そして, ADDRESS(MATCH(MAX(C8:C16),C8:C16,FALSE)-10,-2,4,FALSE) で,901のある行15の列Aのセル位置を,関数の入力セルであるC17から見た相対オフセット量として求めています。自分からの相対位置にするために,行のオフセット値に-10を加えているところがミソです。これに対応する数値は,R[-2]C[-2]となり,C17から見て2行上の2列左となります。
 なお,末尾の数字の4は,行,列とも相対値で表示させることを指示するためのインデックスです。

 最後に INDIRECT(ADDRESS(MATCH(MAX(C8:C16),C8:C16,FALSE)-10,-2,4,FALSE),FALSE) で,オフセットされた位置にあるセルの内容を表示しています。C17から見て2行上の2列左はA15なので,これに対応する数値は7となります。

 以上の処理を単純に言ってしまえば,列Cの最大値に対応している列Aの数値を求めているだけのことです。
 でも,これを上記の関数の組み合わせで実現するのには,随分と悩んだ記憶があります。あーでもない,こーでもないと,確か半日位は掛かったと思います。

悩んだ記憶はあるのですが,これが実際にどう使われたのかは実は良く憶えていません。確か何かの事務処理だったような気はするのですが,半日も掛ける価値が本当にあったのか...


 何故かって? 実は,列Aと列Cをひっくり返せば,同じ処理は以下の関数で簡単に実現できてしまいます。

=VLOOKUP(MAX(A8:A16),A8:C16,3,FALSE)

どうしてこうしなかったかというと,”列の位置関係を換えるのはイヤ!”という,その女の子の単なるワガママ。。。


単に長ければ良いのであれば,様々な計算公式やif文を深くネストすれば,幾らでも長い式は作れます。実際に,数式バーで2行とか3行に跨る式はザラにあります。

 例えば,鉄筋径とピッチに応じて鉄筋量を求めるセルでは,D13からD32までの分でもこんな長さの式になります。

=((E15*10)/E20)*IF(E19=13,1.267,IF(E19=16,1.986,IF(E19=19,2.865,IF(E19=22,3.871,IF(E19=25,5.067,IF(E19=29,6.424,IF(E19=32,7.942,0))))))),0)

しかし単一項の組み合わせ関数としては,ほとんど実用的な意味がないのが悲しいのですが,私が作ったものの中では今のところこれが最長不倒です。

 ちなみに,その時の女の子K嬢は,今ではT夫人として幸せに暮らしているそうです。