エクセル雑感:情報処理試験レベルのVBA知識を問う4択クイズと詳細解説
情報処理技術者試験や、社内のITスキル認定試験において、Excel VBAの知識が問われるケースが増えています。単に「マクロが書ける」というレベルを超え、オブジェクトモデルの理解、イベント駆動型の仕組み、そしてメモリ管理や型指定の重要性を問う問題は、実務におけるコードの品質を左右する重要な指標です。
今回は、ベテランエンジニアの視点から、試験に出題されそうな「本質を突く問題」を4問厳選しました。それぞれの設問に対し、なぜその回答になるのか、背後にあるExcelの仕組みまで掘り下げて解説します。
第1問:オブジェクト参照の基本とメモリ管理
【問題】
次のVBAコードを実行した際、メモリ上のオブジェクト参照および解放について最も適切な記述はどれか。
Sub ObjectTest()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
' 何らかの処理
Set ws = Nothing
End Sub
A) Set ws = Nothing を実行しないと、Excelを終了するまでメモリが解放されず、必ずメモリリークが発生する。
B) プロシージャが終了すればローカル変数はスコープを抜けるため、Set ws = Nothing は記述しなくても自動的に解放される。
C) Set ws = Nothing を記述することで、オブジェクトそのものを即座に削除(Delete)することができる。
D) Worksheetオブジェクトはグローバル変数として扱われるため、明示的な解放が必須である。
【正解:B】
【詳細解説】
この問題は、VBAのメモリ管理とスコープの理解を問うものです。多くの初学者は「Nothingにしないとメモリリークする」という強迫観念を持っていますが、これは誤解です。VBAでは、プロシージャ内で宣言されたローカル変数は、そのプロシージャの終了とともにスコープを失い、参照カウントが減ります。Excelのガベージコレクション機能により、自動的にメモリは解放されます。
ただし、例外もあります。クラスモジュールの循環参照や、大規模なアプリケーションでオブジェクトを多用する場合、明示的なNothingの代入は「意図的に参照を切る」という点で有効なデバッグ手法となります。しかし、一般的な処理において「Nothingにしない=メモリリーク」と断定するのは間違いです。
第2問:イベント駆動の実行順序と抑制
【問題】
ワークシートの変更イベント(Worksheet_Change)内で、再びセルに値を代入する処理を行う場合、無限ループを回避するために最も推奨される手法はどれか。
A) DoEvents を使用して、イベントの処理を一時停止させる。
B) Application.EnableEvents = False を処理の前後で切り替える。
C) On Error Resume Next を使用して、エラー発生時にループを強制終了させる。
D) 変数にフラグを持たせ、If文でイベント処理をバイパスする。
【正解:B】
【詳細解説】
これは実務で最も頻繁に遭遇する「スタックオーバーフロー」の原因を問う問題です。Worksheet_Changeイベントは、セルが書き換わるたびに発火します。イベント内でセルを書き換えると、それがトリガーとなって再びイベントが走り、無限ループに陥ります。
これを防ぐための標準的な作法が Application.EnableEvents です。これを False に設定することで、Excelのイベントシステム自体を一時的に無効化できます。注意点は、処理の最後で必ず True に戻すことです。もしエラーが発生してプロシージャが途中で終了してしまうと、イベントがずっと無効のままになり、他のマクロも動かなくなります。そのため、必ずエラーハンドリング(On Error GoTo 処理)とセットで使用するのがプロの流儀です。
第3問:配列とRangeの転記速度
【問題】
1万行のデータをExcelシートから配列に読み込み、加工してシートに戻す処理において、最もパフォーマンスが高い手法はどれか。
A) For Each ループを使用して、Rangeオブジェクトを一つずつ走査して書き込む。
B) セルを一つずつ指定して、Cells(i, j).Value = … の形式で代入する。
C) Rangeオブジェクトの Value プロパティに配列を一括代入する。
D) Application.ScreenUpdating を True に設定し、画面描写を最適化する。
【正解:C】
【詳細解説】
VBAのパフォーマンスにおいて、最もコストが高いのは「VBAとExcelシート(COMインターフェース)の間の通信」です。セルを一つずつ操作する(B)は、1万回以上の通信が発生するため、非常に低速です。
一方で、Range.Value プロパティに配列を一括代入(C)すると、メモリ上のデータがシート上の領域に一気に書き込まれます。これは内部的に最適化されており、圧倒的な速度差を生みます。情報処理試験では、こうした「計算量」や「通信コスト」を意識したコーディングができるかが問われます。
第4問:変数のスコープと静的変数
【問題】
プロシージャを呼び出すたびに、呼び出し回数をカウントして保持し続けたい場合、最も適切な変数宣言はどれか。
A) Public 変数を使用し、標準モジュールの冒頭で宣言する。
B) プロシージャ内で Dim を使用し、処理の最後に値を保存する。
C) プロシージャ内で Static を使用して宣言する。
D) プロシージャ内で Const を使用して宣言する。
【正解:C】
【詳細解説】
変数の寿命(ライフタイム)に関する問題です。Dim はプロシージャが終了すると値が破棄されます。Public 変数は便利ですが、どこからでも書き換え可能であるため、バグの温床になりがちです。
Static 変数は、プロシージャ内でのみアクセス可能でありながら、プロシージャが終了しても値が保持されるという特性を持っています。特定の関数内だけで完結するカウンタや、キャッシュデータを持たせたい場合に非常に有用です。カプセル化の観点からも、必要以上にスコープを広げない「最小権限の原則」に従うことが、堅牢なプログラム作成の鍵となります。
実務アドバイス:試験と現場の境界線
試験問題は「正解」を一つに絞る必要がありますが、実務では「保守性」「可読性」「拡張性」という3つの軸が重要になります。
例えば、第2問で紹介した EnableEvents の使い方は、単にコードを書くだけでなく、エラーハンドリングをどう設計するかが問われます。現場では「コードが動くこと」はスタートラインに過ぎません。「他人が読んだときに、なぜこの設定が必要なのか分かるか?」「エラーで止まったときに、Excelの状態を正常に復帰できるか?」という視点を持つことが、シニアエンジニアへのステップアップです。
また、配列操作(第3問)は、現代のVBA開発において必須のスキルです。DictionaryオブジェクトやCollectionオブジェクトと組み合わせることで、VLOOKUP関数を何万回も叩くような非効率なコードを、一瞬で終わるロジックに書き換えることができます。
まとめ
今回取り上げた4つのテーマは、いずれもExcel VBAの根幹をなす概念です。
1. オブジェクトの参照と解放(メモリ管理)
2. イベント制御(ループ回避と安全な実装)
3. 配列を用いた高速化(通信コストの削減)
4. 変数のスコープ(Static変数の活用)
これらの概念を単なる暗記ではなく、「なぜそう動くのか」という背景(アーキテクチャ)と共に理解することで、試験問題に回答できるだけでなく、実務におけるトラブルシューティング能力も飛躍的に向上します。
VBAはレガシーな言語だと揶揄されることもありますが、Excelという強力なプラットフォーム上で動作する以上、その仕様を深く理解しているエンジニアは、どのような現場でも重宝されます。ぜひ、今回紹介したコードを実際にVBE(Visual Basic Editor)に貼り付け、ステップ実行しながら挙動を確認してみてください。座学だけで終わらせず、自分の手でロジックを動かすことこそが、最強の学習法です。
