LET関数とは、いわば「数式内で使える変数」みたいな仕組みです。簡単な例をご紹介します。
LET関数の引数は、まず「変数名」と「変数に入れるモノ」の"2つ1組"で記述します。上記では「変数aに10を入れる」と「変数bに20を入れる」を指定しています。そして最後に"1つだけ"の引数を指定します。上記では「a+b」です。このボッチの引数が、セルに表示されます。上記では、変数に数値を代入していますが、ほかにも"関数など数式の結果"や"セルまたはセル範囲"なども格納可能です。上記の動作をVBA的に表現するのなら、こんな感じですかね。
a = 10 b = 20 MsgBox a + b
LET関数についての詳しい解説は、下記ページをご覧ください。
このLET関数は、おおむね次のような用途で使われます。
ここでいう"構造化"とは、厳密な意味ではなく「可読性を高める」程度にお考えください。
LET関数で使用可能な"変数名"は、おおむねVBAの命名ルールと一緒です。
ルールに反した変数名を使うとエラーになりますので、怒られたら別の変数名を使ってください。
なお、私はよく、LET(a,10,b,20,a+b) のように1文字の変数名を使いますが、それは私自身が「その方が読みやすい(可読性が高い)」と感じているからです。ほとんどの場合、LET関数を使った数式は長くなります。そうした長い数式の中で、文字数の多い変数名を乱用すると、逆に分かりにくくなるって感じます。これはVBAでも同じで、だからここ数年のマイブームは、短い変数名です。あまり重要ではない、どうでもいい変数は、1文字など簡素な方がいいんじゃね?って思います。ただ、これはあくまで私の感覚なので「英単語のように意味のある変数名の方がいい」と感じる方は、ご自身の判断に沿ってください。私だって、超複雑な数式を作るときは、意味のある変数名を使っています。
えっと"スコープ(有効範囲)"というか何というか、ちょっと複雑なケースの検証です。
上図では、LET関数を2つ使っています。1つめのLET関数で「変数aに10」を代入しています。そして、最終的な計算で2つめのLET関数を使い、その中で変数aを計算してみました。結果は次のとおり。
LET関数の引数は、数式全体で使える、いわば"グローバル(広域)変数"であることが分かります。なので、次のように書き換えることもできます。
では、同じ変数名をLET関数ではない別の関数で使ったら、どうなるのでしょう。そもそも引数を扱える関数というのが、ほとんどないのですが、たとえばLAMBDA関数には受け取る引数を使用できます。ちょっと複雑になりますが、次のように試してみました。
MAP関数で使用している変数aは、LET関数で定義した変数aです。つまり、MAP関数はセル範囲A1:A3の3セルを順番にLAMBDA関数へ渡します。さて、そのLAMBDA関数では、MAP関数から受け取る引数名に、同じaを指定しました。結果的に、両者のaはバッティングしていません。バッティングはしませんが、あまり良い書き方とは言えませんね。いや、私も面倒くさいときは、こうした手抜きもしますけどw
前述したように、私はaとかbなど1文字の変数名を、よく使っています。それはもちろん私の主義ですので、他の人に強制するつもりはありません。さらに、これから解説する"落とし穴"に関しても、しっかり認識しているので、無用なトラブルも回避しています。では、その"落とし穴"をご紹介しましょう。
冒頭に記述したとおり、LET関数の引数には、数値や文字列などの値や、数式や関数の結果だけでなく、セルやセル範囲も格納できます。簡単なケースで解説します。
変数topに「セルA1」を入れ、変数bottomに「セルA4」を入れました。注目していただきたいのはSUM関数の引数「top:bottom」です。これは、言うまでもなく「A1:A4」です。ちゃんと計算されていますよね。つまり変数topは「セルA1の値」である"1"が入っているのではなく、「セルA1そのもの」が格納されている訳です。VBA的に表現するのなら、こんな感じでしょうか。
Dim top As Range Dim bottom As Range Set top = Range("A1") Set bottom = Range("A4") Range(top, bottom).Select ''SUM関数の代わり(意味はない)
では、変数名topと変数名bottomを、AとBに置き換えてみましょう。
Excelのセル参照で「A:B」は「A列からB列」を表します。であるなら、上図の「SUM(A:B)」では、セルB1の100も合計されなければおかしいです。セルB1の100が計算されていないということは、この「A:B」は「A1:A4」であると分かります。ややこしいですか?そう、ややこしいんです。ここでは分かりやすくAとBを大文字で表記しましたが、もちろんaとbでも同様です。
もちろん上図は超分かりやすい例です。結論をいうと「aやbなどの1文字変数を使うときは、A:Cのような"列単位の指定"をしてはいけない」ということです。最後に具体例をひとつご紹介します。
上図のようなことをしたいとします。列Aから列Cまで、何らかの値が入力されています。データの件数は分かりません。なのでトリム参照を使います。さて、このリストの左端に連番を振ります。連番はSEQUENCE関数で作り、元のデータと結合します。結合にはHSTACK関数を使いましょう。まずは、SEQUENCE関数の結果を変数に入れます。
この変数Aと、A列:C列(トリム参照)をHSTACK関数で結合します。
Enterキーを押すとエラーです。
エラーの原因は、お分かりですね。トリム参照「A:.C」のAは、SEQUENCE関数によって作られた数値の配列です。A列という列文字とは認識してくれません。ここは、別の変数名を使います。
言われてみれば納得しますけど、この件を誰も言ってくれていないので、初めてエラーに遭遇すると混乱することでしょうね。お気をつけください。