【2025/10/17訂正】エクセルexcelの関数LOOKUP(1,0/FIND(….))で仕訳インポートをする上での論点は?
問題の所在
当事務所では、摘要欄の文字列から、科目名をヒット(抽出)させるため、excelの関数LOOKUP(1,0/FIND(….))を重用している。
この使い方でやや不安な点が、以下の2つ:
- LOOKUP(1,0/FIND(….)) と LOOKUP(0,0/FIND(….)) の違い
- 「lookupの文字列は、文字コード順になっていないとうまくヒットしない」と解説される点
1.は、以下の書籍では、LOOKUP(1,0/FIND(….)) の方が表記され、この点にフォーカスした解説は無い。
2.は、仕訳取込の元データ(例 預金データ等)は、文字コードなど意識しない、順不同である。
1.も2.も今までトラブルになっていないのであるが、現状を整理しておく。
結論
上の1.
→ LOOKUP(1,0/FIND(….)) と LOOKUP(0,0/FIND(….)) はどちらでも許容であるが、(0,0/FIND(...)の方が、やや安心ではある
【2022/9/26訂正】
4つヒットする事例で、
0,0/FIND(...)だと2つしかヒットしなかったが、
1,0/FIND(...)だと4つともヒットした。
ので、1.0/FIND(...)の方がベターと考え直します。
【2025/10/17追記】
copilot に質問しても、同様。その内容は以下の補足に記載。
上の2.
→ 2点課題があり、2つ目の「科目の入り繰りリスク」は注意する。
理由
1.について
まず、FIND(…) で算出される値は 自然数。
仕訳取込を想定すると、
- 検査範囲の1行目なら1だし、
- 300行目なら300だし、
- 過去に用意した単語にヒットしなければ、#value である。
そして、補足の★にある記事中で、
>◆ 0/FIND(…) にすることで、検索値の「1」より小さくしています
ということだから、LOOKUP(1,0/FIND(….)) LOOKUP(0,0/FIND(….)) のカッコ内がとる値は、0/1、0/2、0/3.。。。0/300 か #value であり、結局、意味がある値は0のみである。
そして、補足の★の記事にあるとおり、lookup関数は、
>5)検査範囲に、検査値が無い場合は「検査値に一致する値がないと、検査値以下の値の最大値を検査結果とします。
ので、0 であっても 1 であっても、以下のように同じ結果になる。(参考に、自然数nの場合も付記する)
- LOOKUP(0,0/FIND(….)) なら、0=0 となる行がドンピシャでヒットする。OK。
- LOOKUP(1,0/FIND(….)) なら、0 →0に近い値を探し、近似値である1の行をヒットする。OK
- LOOKUP(n,0/FIND(….)) なら、0 →0に近い値を探し、近似値であるn行目をヒットする。OK
数字の1の場合でも、vlookup関数のように、絶対参照(=完全一致)を実現することが不要であるから、問題ないことになる。
2.について
まず、
>2.lookupの文字列は、文字コード順になっていないとうまくヒットしないと解説される点
に伴うリスクは、
1)ヒットしない
2)誤って別の科目がヒットしない
のいずれかである。以下で順に検討する・
1)ヒットしない
これは実害がない。
検索値テーブルの一番下の行に、当該摘要の検索値候補を追記すればよい。
2)誤って別の科目がヒットしない
例えば、摘要欄に、「ビックカメラ ノートパソコン」とあり、テーブル中、
- (検索値)ノートパソコン (検索範囲) 消耗品費
- (検索値)パソコン (検索範囲) 消耗品費
- (検索値)ノート (検索範囲) 事務用消耗品費
となっている場合、少なくとも、仕訳取込上では、
- lookup関数が、1.と2.を混同しても、仕訳科目は 消耗品費a/cなので、問題ない
- lookup関数が、1.と3.を混同すると、仕訳科目が変わってしまうため、問題である
という課題があることを指す。(この点、vlookup関数であれば、「ノートパソコン」のカタカナ7文字で抽出してくれる)
このため、実務上は、「1.を使わない」、つまり、2.や3.のように検索語を短い単語にする必要がある。
このリスクがあるため、仕訳取込で、〇〇〇a/cが検索されていても、ざっと通査する必要はある。
(しかし、この弱点は、クラウド会計ソフト等で自動読み取りと言われている機能でも同様である)
補足
★参考記事:
Excelの関数LOOKUP(1,0/FIND(….))の意味
https://oshiete.goo.ne.jp/qa/2473771.html
(以下、一部抜粋)
1)式=LOOKUP(1,0/FIND($A$15:$A$20,A1),$B$15:$B$20) が入力されているセルを指定します
2)数式バーで、「0/FIND($A$15:$A$20,A1)」を選択して、「F9」を押します
3)表示が、「{#VALUE!;#VALUE!;0;#VALUE!;#VALUE!;#VALUE!}」になります
4)LOOKUP関数は、LOOKUP(検査値,検査範囲,対応範囲) です
5)検査範囲に、検査値が無い場合は「検査値に一致する値がないと、検査値以下の値の最大値を検査結果とします。
6)ということで、3番目の0を検索し、対応範囲の3番目の「300」を表示します
◆ 0/FIND(…) にすることで、検索値の「1」より小さくしています
===========
また、copilotの回答は以下:
ご提示いただいた2つの数式のうち、部分一致(ワイルドカード検索)で最後の行のデータを取得するという目的においては、通常は前者の数式が正しい動作をします。
- 正しい数式:
=LOOKUP(0,0/FIND(テーブル!$B$3:$B$100,S3),テーブル!$C$3:$C$100)
- 目的と異なる数式:
=LOOKUP(1,0/FIND(テーブル!$B$3:$B$100,S3),テーブル!$C$3:$C$100)
違いの解説
このテクニックの動作原理は、LOOKUP
関数の特性を利用して、検索配列の中に含まれる「エラーを無視した最後の数値」を取得することにあります。
1. 正しい数式: 検索値が $\mathbf{0}$ の場合
式の評価結果 | 0/FIND(…) の配列 |
一致した場合 | $0/(\text{数値}) = \mathbf{0}$ |
不一致の場合 | $\mathbf{\#VALUE!}$ エラー |
- 検索する値(第1引数): $0$
- 検索対象の配列(第2引数): $0$ または $\#VALUE!$ エラーの配列
LOOKUP関数は、検索配列の中から検索値 0 以下の最も大きな数値を探します。この配列には**0**という数値しか存在しないため、最後に現れる 0 を見つけ、その位置に対応する結果を返します。
部分一致したデータの中で、最も行番号の大きい(最後にある)データを取得できます。
2. 目的と異なる数式: 検索値が $\mathbf{1}$ の場合
- 検索する値(第1引数): $1$
- 検索対象の配列(第2引数): $0$ または $\#VALUE!$ エラーの配列
LOOKUP
関数は、検索配列の中から検索値 $1$ 以下の最も大きな数値を探します。
- 検索配列に含まれる数値は**$0$**のみです。
- $0$ は $1$ 以下です。
したがって、LOOKUP
関数は配列の最後に現れる $0$ を見つけ、その位置の結果を返します。
❌ なぜ $1$ は避けるべきか
この場合、偶然にも検索値 $1$ を使っても結果は $0$ の場合と同じになります。しかし、このテクニックが成立するのは、検索配列に**$0$以外の数値が入らないこと**が前提です。
- もし将来的にこのテクニックを応用し、検索配列に $0$ よりも大きく $1$ 以下の数値(例: $0.5$)が発生するような数式を組んだ場合、
LOOKUP(1, ...)
は $0$ ではなく $0.5$ を探し、想定外の結果を返すことになります。
このテクニックの目的が「エラーを無視して $0$ という数値だけを抜き出す」ことであるため、検索値と検索配列中の数値を一致させる $0$ を使うのが、最も論理的で安定した正しい書き方とされています。
=================
■