セルに入力した数式は、参照しているセルの値が変わると自動的に再計算されます。しかし、ユーザー定義関数(UDF)の中には「引数として渡していないセル」や「関数の外側の状態」を参照するものがあり、その場合は値が変わっても再計算されず、古い結果が表示されたままになることがあります。
この記事では、Application.Volatileを使ってUDFを常に再計算させる方法と、多用するとワークブックが重くなる注意点、パフォーマンスを抑えた使い方まで解説します。
なぜUDFが再計算されないのか
Excelは通常、セルの数式が参照している「引数のセル」が変化したときだけ再計算を行います。これは、ワークブック全体を毎回すべて再計算すると重くなるため、依存関係を追跡して必要な部分だけを効率的に更新する仕組みになっているためです。
ところが、以下のようなUDFは引数にないセルや状態を参照しているため、Excelが依存関係を認識できず、値が変わっても自動では再計算されません。
NowやDateのように、時間の経過で値が変わる関数- 引数として渡さずに
Rangeで直接参照しているセル - 外部ファイルやAPIなど、ワークシート上に存在しない情報を参照する関数
Application.Volatileの基本構文
Application.Volatileをプロシージャの先頭で呼び出すと、そのUDFは「ワークブック内のどこかが再計算されるたびに、必ず再計算対象になる」揮発性関数(Volatile Function)になります。
Function 関数名(引数) As データ型
Application.Volatile
' 計算処理
End Function
引数を省略した場合はTrueを指定したことになり、常に揮発性がオンになります。
使用例:現在時刻を返す関数
セルに現在時刻を表示し、シートが再計算されるたびに更新したい場合の例です。
Function NowTimestamp() As String
Application.Volatile
NowTimestamp = Format(Now, "yyyy/mm/dd hh:nn:ss")
End Function
Application.Volatileがない場合、この関数は一度計算された後、他のセルが変化しても値が更新されません。Volatileを付けることで、F9キーによる再計算やセル入力のたびに最新の時刻が反映されます。
使用例:引数にないセルを参照する関数
「設定」シートのB1セルに入力した為替レートを、引数を使わずに直接参照する関数の例です。
Function GetExchangeRate() As Double
Application.Volatile
GetExchangeRate = ThisWorkbook.Worksheets("設定").Range("B1").Value
End Function
この関数はGetExchangeRate()という引数なしの形でセルに入力されるため、Excelは「設定シートのB1を参照している」という依存関係を認識できません。Application.Volatileを付けておくことで、B1セルの値を変更した際にも正しく再計算されるようになります。
パフォーマンスを抑えた使い方(条件付きVolatile)
Application.Volatileの引数にFalseを渡すと、揮発性を解除して通常のUDF(引数が変化したときだけ再計算)に戻せます。この性質を利用して、特定の条件のときだけ揮発性を有効にすることも可能です。
Function ConditionalRandom(autoRecalc As Boolean) As Double
Application.Volatile autoRecalc
ConditionalRandom = Rnd()
End Function
セルに=ConditionalRandom(TRUE)と入力すれば再計算のたびに値が更新され、=ConditionalRandom(FALSE)にすれば通常のUDFと同じ挙動(引数autoRecalc自体が変化しない限り再計算されない)に切り替わります。大量に使う関数では、必要な範囲だけ揮発性をオンにすることでワークブック全体の負荷を抑えられます。
Volatileを使う際の注意点
揮発性関数は、ワークブック内のどこか1箇所でも再計算が発生すると、そのたびに毎回実行し直されます。そのため、以下のような点に注意が必要です。
- 多用すると重くなる:シート内に数百件のVolatile関数があると、セル1つを変更しただけでも全件が再計算され、動作が遅くなります
- 手動計算モードでも自動では動かない:
Application.CalculationがxlManual(手動)になっている場合、Volatile関数であってもF9キーなどで明示的に再計算するまで更新されません - 他の負荷が高い処理と組み合わせない:Volatile関数の中でセル書き込みやファイルアクセスなど重い処理を行うと、再計算のたびにその処理が走るため、動作が極端に遅くなることがあります
よくあるトラブルと対処法
- Volatileを付けたのに値が更新されない:計算方法が「手動」になっていないか
Application.Calculationの値を確認してください。手動の場合はF9キーで再計算する必要があります - ワークブックを開くたびに動作が重い:Volatile関数の数を見直し、
ConditionalRandomの例のように必要なときだけ揮発性をオンにする設計に変更してください Application.VolatileをSubプロシージャに書いてもエラーにならないが効果がない:このメソッドはFunctionプロシージャ(UDF)専用です。Subの中で呼び出しても意味を持たないため、UDFの先頭に記述してください
まとめ
Application.Volatileを使うことで、引数の変化だけでは検知できないUDFの再計算漏れを防げます。
- 引数にないセルや時間経過で変わる値を返すUDFには
Application.Volatileを付ける Application.Volatile Falseで揮発性を解除でき、条件付きで使い分けることでパフォーマンスへの影響を抑えられる- 揮発性関数は再計算のたびに実行されるため、多用するとワークブック全体の動作が重くなる点に注意する
現在時刻の表示や外部シート参照など、通常のUDFでは更新されない処理を組み込む際にぜひ活用してみてください。


コメント