TL;DR —
Application.WorksheetFunctionは、VBA から Excel の 450 を超える組み込み関数に 手を伸ばす方法です。だからSUM、VLOOKUP、COUNTIFを手書きのループで書き直す必要は ありません。呼び出し方は 2 通り あり、その違いこそがすべてです。Application.WorksheetFunction.VLookup(...)は一致がない瞬間に 実行時エラーを発生させます — 成功が期待でき、取りこぼしは大きく騒ぐべきときに使いましょう。Application.VLookup(...)(.WorksheetFunctionを外す)はIsErrorでテストできる エラー値を返します — 取りこぼしが 普通に起きるときに使いましょう。そしてApplication.Xの結果を受ける変数はVariantで なければなりません。さもないと、テストする前に error 13 で落ちます。
' "West" は B 列に何回現れる? 1 行で、ループなし。
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sales")
Dim n As Long
n = Application.WorksheetFunction.CountIf(ws.Columns("B"), "West")
MsgBox "West appears " & n & " times"
列を合計するため、あるいは値を引くために For Each ループに手を伸ばすこと — それが、VBA が
遅さとバグを同時に抱え込む最もよくある道筋です。Excel にはすでに計算エンジンが載っていて —
何百もの磨き上げられた関数が — WorksheetFunction はその扉です。身につけるべき技術は、より
多くのコードを書くことではありません。Excel がすでにその関数を持っていると気づいて、それを
呼ぶことです。本記事は、誰もがつまずくたった 1 つの事実 — 呼び出し方は 2 通りあり、正反対の
仕方で失敗する — を軸に組み立てられています。
この記事で学べること
- 考え方の軸 — Excel のエンジンを借りる。ループで作り直さない
- 最も大事なルール —
WorksheetFunction.Xは失敗でクラッシュし、Application.Xはテストできるエラーを返す - 型の罠 — なぜ結果を受ける変数は
Variantでなければならないのか - 呼べる関数、呼べない関数、そして呼ぶ べきでない 関数
- 1 セルずつループする代わりに範囲全体を渡す
WorksheetFunctionと、セルに数式文字列を書き込むこと
考え方の軸:エンジンを借りる。作り直さない
あなたが知っているワークシート関数はすべて — SUM、AVERAGE、VLOOKUP、MATCH、COUNTIF、
SUMIF、MAX、TRIM、PROPER — Application.WorksheetFunction を通して VBA から使えます。
呼んでいるのは関数の VBA 版コピーではありません。シートが使うのと同じエンジン を呼んで
いるので、結果は数式とまったく一致します。
これが大事なのは、代わりの手段がほぼ必ずより悪いからです。列を合計する、一致を数える、
ルックアップのために走査する For Each ループは、Excel がすでに最適化した 1 つの関数よりも、
書くのが長く、走るのが遅く、間違えやすいものです。WorksheetFunction.Sum(ws.Range("B2:B100000"))
は 1 回の走査で返りますが、ループでの等価物は 10 万回の反復を解釈実行の VBA ですり潰して
いきます。このイメージ — Excel がその関数を持っている、私はただ呼べばいい — を頭に置いて
おけば、「VBA で X を計算するには?」という質問のほとんどはひとりでに答えが出ます。
最も大事なルール:2 つの呼び出し方、2 つの失敗モード
持ち帰るべきはこの 1 点です。同じ 関数を 2 通りで呼べますが、操作が 失敗 したとき — たとえばルックアップが何も見つけられなかったとき — 両者はまるで違う振る舞いをします。
' スタイル 1: WorksheetFunction.X - 一致なしでクラッシュする。
Dim price As Double
price = Application.WorksheetFunction.VLookup("Widget", ws.Range("A:C"), 3, False)
' "Widget" がなければ: 実行時エラー 1004 が出て、実行が止まる。
' スタイル 2: Application.X(.WorksheetFunction なし)- テストできるエラーを返す。
Dim result As Variant
result = Application.VLookup("Widget", ws.Range("A:C"), 3, False)
If IsError(result) Then
MsgBox "Widget not found" ' きれいに処理、クラッシュなし
Else
MsgBox "Price is " & result
End If
同じ関数、同じ引数 — なのに WorksheetFunction.VLookup は一致がないと 例外を投げ、
Application.VLookup は IsError が捕まえる #N/A エラー値を 返します。どちらが「正しい」
ということはありません。両者は違う意図のためのものです。
- 操作が成功すると 期待 でき、失敗が本当に何かおかしいことを意味するなら
WorksheetFunction.Xを使いましょう。クラッシュは機能です — 悪い値を下流に流す代わりに、 マクロを止めてくれます。 - 取りこぼしが処理したい普通の結果なら
Application.Xを使いましょう — キーが見つかるとは 限らないルックアップ、たいていは存在する値。IsErrorでテストして分岐します。
このトピック全体で第 1 位のバグは、何かが存在するか どうかを調べる ために
WorksheetFunction.Match を使い、存在しないときに error 1004 に驚くことです。存在チェックこそ、
Application.Match + IsError の出番です。
型の罠:結果は Variant でなければならない
スタイル 2 が働くのは、結果を受ける変数がエラー値を 保持 できるときだけです。VBA では
Variant だけがそれをできます。それより狭い型で宣言すると、代入そのものが吹き飛びます。
Dim result As Double
result = Application.VLookup("Widget", ws.Range("A:C"), 3, False)
' 見つからなければ: error 13「型が一致しません」- Double は #N/A を保持できないから
直し方は単純に Dim result As Variant です。そうすれば IsError(result) を安全に呼べ、
成功時には値をそのまま使えます。これは「エラーを返す」パターンの、静かな後半です。
Application.X の結果は、必ず Variant に入れる。 これを忘れると、型の不一致が、まさに
組もうとしていたエラー処理そのものを覆い隠してしまいます。
呼べる関数 — そして呼ぶべきでない関数
ライブラリのほとんどは使えますが、知っておく価値のある 3 つの縁があります。
- すべてが公開されているわけではありません。 新しめの、あるいは揮発性の関数のいくつかは
WorksheetFunctionに現れません。名前が見当たらないときは、たいていApplication.Evaluateに 頼るか、数式をセルに書き込めます(後述)。 - VBA がすでにネイティブで持つ関数もあります — そちらを使いましょう。
WorksheetFunction.Left、Mid、Right、Trim、Upper、Lowerは 呼んではいけません。 VBA には自前のLeft、Mid、Right、Trim、UCase、LCaseがあり、より速く、Excel への 往復もありません。(1 つ微妙な点。VBA のTrimは先頭と末尾の空白だけを取り除きますが、WorksheetFunction.Trimは内部の連続空白もまとめます — なので両者は同一ではなく、ときには 本当に ワークシート版が欲しいこともあります。) - 名前が違うこともあります。 VBA のメンバー名はたいてい関数と一致しますが、いくつかは
Excel の古い内部表記を引きずっています。迷ったら
Application.WorksheetFunction.と打って、 IntelliSense に実際にあるものを並べさせましょう。
目安はこうです。ルックアップ、条件付きの集計や合計、統計といった、Excel が得意な重量級の
分析関数には WorksheetFunction に手を伸ばし、基本的な文字列や数値の作業には VBA 自前の
キーワードを使う。
1 セルずつループせず、範囲全体を渡す
最大の速度向上は、同時に最も見落としやすいものでもあります。WorksheetFunction の関数は
範囲 を取るので、ループして 1 セルずつ呼ぶ代わりに、範囲全体を一度に手渡しましょう。
' 遅い - 行ごとに 1 回エンジンを呼ぶ。
Dim i As Long, total As Double
For i = 2 To lastRow
total = total + ws.Cells(i, "B").Value
Next i
' 速い - 呼び出しは 1 回、ループはエンジンが内部でやる。
total = Application.WorksheetFunction.Sum(ws.Range("B2:B" & lastRow))
速い版は単に短いだけではありません。反復を、解釈実行の VBA で回す代わりに、Excel の
コンパイル済みエンジンへ押し下げます。同じことが CountIf、SumIf、Average、Max、Min にも
当てはまります — 範囲を渡して、数える仕事は任せましょう。ループの中で合計を積み上げている
自分に気づいたら、それはほぼ必ず、呼ばれるのを待っているワークシート関数です。
WorksheetFunction と、セルに数式を書き込むこと
3 つ目の選択肢があり、いつそれを選ぶべきかを知っておくと、コードが正直なままでいられます。
WorksheetFunction は コードの中で値を一度だけ計算します — シートは変わらず、データが
変わっても答えは再計算されません。セルに数式文字列を書き込むこと
(ws.Range("D2").Formula = "=SUM(B2:B100)")は、永遠に更新され続ける 生きた数式を残します。
ロジックの中で いま 数値が必要なとき — 比較するしきい値、分岐の判断に使うカウント、
レポートに刻む合計 — には WorksheetFunction を使いましょう。ユーザーが編集しても正しいまま
であるべき結果を見せたいときは、セルに数式を書き込みましょう。WorksheetFunction に手を伸ばして、
その静的な答えを、本来数式があるべき場所に貼り付けること — それは、レポートが静かに古びて
いくよくある道筋です。
ExcelMaster の活用
WorksheetFunction は、驚くほど多くの判断を 1 回の呼び出しに詰め込みます — 2 つのスタイルの
どちらを使うか、結果に Variant が要るか、ネイティブの VBA キーワードのほうが良いか、値を
一度だけ計算すべきか生きた数式として残すべきか。そのどの選択にも、間違った答えを返す —
あるいはテストしていないデータでクラッシュする — 失敗モードが潜んでいます。
ExcelMaster なら、
計算を説明するだけで済みます。「West 地域からの注文が何件あるか数えて」「各商品の価格を引いて、
在庫にないものにフラグを立てて」と言えば、正しい呼び出し方を選び — 取りこぼしが本当のエラーに
なるクラッシュする方、取りこぼしが想定内のテストできる方 — 必要なときは結果を Variant で宣言し、
ループせずに範囲全体を渡します。ブックもコードもあなたの手元に残り、処理されなかった error 1004 が
レポートの途中でマクロを止める、あの一幕だけを飛ばせます。
よくある質問
VBA の WorksheetFunction と Application の違いは?
どちらも同じ Excel 関数を呼びますが、失敗の仕方が違います。Application.WorksheetFunction.X は、
一致のないルックアップのように関数が結果を返せないとき、実行時エラー(たいてい 1004)を発生
させます。Application.X — .WorksheetFunction なし — は代わりに #N/A のような Excel の
エラー値を返し、これを IsError でテストします。失敗がマクロを止めるべきときは前者を、
取りこぼしが処理すべき普通のケースのときは後者を使いましょう。
WorksheetFunction.VLookup で error 1004 が出るのはなぜ?
WorksheetFunction.VLookup が、値が見つからないときに #N/A を返すのではなく実行時エラーを
投げるからです。そこでの error 1004 は、壊れた数式ではなく、ほぼ必ず「一致なし」を意味します。
いくつかのルックアップが外れると見込むなら、Application.VLookup を Variant に呼び入れて
IsError(result) でテストするか、WorksheetFunction の呼び出しを On Error 処理で包みましょう。
Application.VLookup で型の不一致(error 13)が出るのはなぜ?
Application.VLookup はエラー値を返しうるのに、それを保持できるのは Variant だけだからです。
受け取る変数を Double、Long、String で宣言すると、結果が #N/A になった瞬間に error 13 が
起きます。As Variant で宣言し、値を使う前に IsError を呼びましょう。
WorksheetFunction を通せば、どんな Excel 関数でも VBA で使える?
ほとんどは使えますが、すべてではありません。よく使う分析関数 — VLOOKUP、MATCH、COUNTIF、
SUMIF、SUM、AVERAGE、統計系 — はすべてそろっています。新しめの、あるいは揮発性の関数の
いくつかは公開されていません。それらには Application.Evaluate を使うか、数式をセルに書き込み
ましょう。そして基本的な文字列や数値には、ワークシート版よりも VBA 自前の Left、Mid、Trim、
UCase や演算子を選びましょう。
WorksheetFunction.Sum は VBA でループするより速い?
はい、大きな範囲でははっきりと。範囲全体を WorksheetFunction.Sum に渡すと、反復は 1 回の
呼び出しで Excel のコンパイル済みエンジンの中で走りますが、For Each や For のループは解釈
実行の VBA で 1 セルずつ走ります。ループの中で合計やカウントを積み上げているときはいつでも、
範囲全体に対して呼ぶワークシート関数のほうが、たいてい短くて速いのです。
検証環境
動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-10。
関連ガイド: VBA VLOOKUP · VBA Remove Duplicates · VBA Advanced Filter · VBA For Loop · VBA Range
