【VBAリファレンス】VBA練習問題VBA100本ノック 22本目:FizzBuzz発展問題

スポンサーリンク

Excel VBAで挑むFizzBuzz発展問題:実務に活きるループと条件分岐の極意

Excel VBAのスキルを向上させるための登竜門として有名な「VBA100本ノック」。その中でも、第22本目として提示される「FizzBuzz発展問題」は、単なるプログラミングの基礎練習を超えた、論理的思考とコードの柔軟性を問う重要な課題です。

FizzBuzzとは、本来「1から100までの数字を順に出力し、3の倍数ならFizz、5の倍数ならBuzz、両方の倍数ならFizzBuzzと表示する」というアルゴリズムの定番問題です。しかし、発展問題では、単なる表示にとどまらず、シートへの書き込み処理、動的な範囲指定、あるいは条件の変更に対するメンテナンス性までが求められます。本稿では、この課題をプロフェッショナルレベルの視点で解き明かし、実務で「保守性の高いコード」を書くための考え方を解説します。

FizzBuzz発展問題の詳細解説

この課題の本質は、「条件分岐の順序」と「データの出力効率」にあります。多くの初心者が陥る罠は、3の倍数と5の倍数の判定を個別に記述し、最後に「15の倍数」の判定を忘れる、あるいは冗長なコードを書いてしまうことです。

実務レベルのVBAコードにおいては、以下の3点を意識する必要があります。

1. 条件の優先順位:15の倍数(3と5の最小公倍数)は、単独の3や5よりも先に判定しなければなりません。これを後回しにすると、条件分岐が複雑化し、バグの温床となります。
2. セル操作の最小化:VBAにおいて、セルへの書き込みは非常にコストの高い処理です。1セルずつ書き込むのではなく、配列(Array)やメモリ上で処理を完結させ、最後に一括でシートへ出力することで、実行速度を劇的に向上させることができます。
3. 可変性への対応:将来的に「7の倍数でBazzを追加したい」といった仕様変更があった際、コードを書き換えやすい設計にしておくことが重要です。

サンプルコード:配列を活用した高速FizzBuzz処理

以下に、実務での利用を想定した、効率的かつ可変性の高いサンプルコードを提示します。このコードでは、Variant型の配列を使用してメモリ上で計算を行い、最後にワークシートへ一括転送する手法を採用しています。


Sub ExecuteFizzBuzz()
    ' 定数定義でメンテナンス性を向上
    Const MAX_NUM As Long = 100
    Dim resultArr() As Variant
    Dim i As Long
    
    ' 配列のサイズを定義(1から100まで)
    ReDim resultArr(1 To MAX_NUM, 1 To 1)
    
    ' メモリ上での計算ループ
    For i = 1 To MAX_NUM
        If i Mod 15 = 0 Then
            resultArr(i, 1) = "FizzBuzz"
        ElseIf i Mod 3 = 0 Then
            resultArr(i, 1) = "Fizz"
        ElseIf i Mod 5 = 0 Then
            resultArr(i, 1) = "Buzz"
        Else
            resultArr(i, 1) = i
        End If
    Next i
    
    ' ワークシートへの一括出力
    With ThisWorkbook.Sheets(1)
        .Range("A1").Resize(MAX_NUM, 1).Value = resultArr
    End With
    
    MsgBox "FizzBuzz処理が完了しました。"
End Sub

このコードのポイントは、`Range(“A1”).Resize(MAX_NUM, 1).Value = resultArr` の部分です。セルを一つずつループで書き込むのではなく、配列を一度に流し込むことで、Excelの再描画回数を抑え、数ミリ秒単位での高速処理を実現しています。

実務アドバイス:コードの保守性と拡張性

プロフェッショナルなエンジニアとして、単に動くコードを書くだけでは不十分です。実務環境では、要件は常に変化します。例えば、上記のFizzBuzzにおいて、「判定条件を外部から変更したい」「出力先を動的に変更したい」といった要望が出るのは日常茶飯事です。

このような状況に対応するために、以下の設計指針を推奨します。

1. マジックナンバーの排除:コードの中に直接「3」や「5」を書き込むのではなく、定数(Const)や変数として定義しましょう。これにより、値が変わった際に修正箇所が一箇所で済みます。
2. 処理と出力の分離:計算ロジック(FizzBuzzの判定)と、出力ロジック(どのセルに書き込むか)を別のプロシージャに分けることを検討してください。そうすることで、テストが容易になり、将来的な機能拡張にも耐えうる堅牢なコードになります。
3. エラーハンドリングの導入:今回は単純なループですが、実際の業務ではシートが存在しない、あるいは書き込み権限がないといった例外が発生する可能性があります。`On Error GoTo` を適切に使用し、予期せぬ停止を防ぐ実装を心がけましょう。

また、FizzBuzzは「Mod演算子(剰余演算子)」の練習に最適です。`i Mod 3 = 0` という記述は、VBAにおける条件分岐の基本中の基本ですが、これを応用することで、行の交互色付けや、特定の周期でのデータ集計など、実務での複雑なタスクを簡潔に記述できるようになります。

まとめ

VBA100本ノックの22本目である「FizzBuzz発展問題」は、基礎的なループと条件分岐の理解を深め、さらには「処理効率」というエンジニアの視点を養うための優れた教材です。

本稿で解説した「配列を用いた高速化」と「定数によるメンテナンス性の向上」は、どのような規模のVBA開発においても共通して適用できる重要なスキルです。FizzBuzzを単なるパズルとして解くのではなく、いかにして「美しく、速く、変更に強いコード」を書くかという視点を持って取り組んでください。

Excel VBAは、習熟すればするほど、業務の自動化において強力な武器となります。今回学んだFizzBuzzのロジックを、ぜひ自身の業務におけるデータ加工や条件判定の現場に応用してみてください。プロフェッショナルへの道は、こうした小さな課題を徹底的に突き詰めることから始まります。妥協のないコードを書き続けることこそが、エンジニアとしての価値を高める唯一の方法です。

タイトルとURLをコピーしました