【VBAリファレンス】生成AI活用研究Geminiと100本ノック 10本目:行の削除

スポンサーリンク

生成AI活用研究Geminiと100本ノック 10本目:行の削除を極める

Excel VBAにおける「行の削除」は、一見単純な操作のように思えます。しかし、実務で数万行のデータを扱う際、不用意なコードを書くと処理速度が劇的に低下したり、意図しない行がスキップされたりする問題に直面します。本記事では、生成AI「Gemini」をペアプログラミングのパートナーとして活用し、VBAにおける「行削除のベストプラクティス」を深く掘り下げます。100本ノックの第10弾として、効率的かつ堅牢なロジックを習得しましょう。

なぜ「行の削除」は奥が深いのか

VBAで特定の条件に合致する行を削除する際、初心者が最も陥りやすい罠が「上から順に削除する」という手法です。

For i = 1 To LastRow
If Cells(i, 1).Value = “削除対象” Then
Rows(i).Delete
End If
Next i

このコードは一見正しく見えますが、致命的な欠陥があります。例えば、1行目を削除すると、本来2行目だったデータが1行目に繰り上がります。しかし、次のループではカウンタが2になるため、繰り上がったデータがスキップされてしまうのです。

この問題を解決するには、「下から上へ(逆順で)ループさせる」というアルゴリズムが基本となります。しかし、データ量が多い場合、ループ内でDeleteメソッドを何度も呼び出すと、Excelの再計算や再描画がその都度発生し、パフォーマンスが著しく低下します。プロフェッショナルなエンジニアは、これらの課題をどのように解決しているのでしょうか。

実務で求められる「高速削除」のアルゴリズム

大規模データに対応するためのアプローチには、大きく分けて3つのレベルがあります。

1. 逆順ループ処理(小~中規模データ向け)
2. Rangeオブジェクトの結合による一括削除(中~大規模データ向け)
3. 配列への取り込みと再出力(超大規模データ向け)

Geminiを活用する際は、「単にコードを書いて」と頼むのではなく、「メモリ消費を抑え、かつ処理速度を最大化するアルゴリズムを選択してほしい」という指示を出すことが重要です。

サンプルコード:Rangeオブジェクトを用いた一括削除

以下は、条件に一致する行をRangeオブジェクトに蓄積し、最後に一括で削除するテクニックです。この手法は、ループ内でDeleteを繰り返さないため、メモリ効率と実行速度のバランスが非常に優れています。


Sub DeleteRowsEfficiently()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim deleteRange As Range
    
    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    ' 画面更新と自動計算を停止して高速化
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    For i = 1 To lastRow
        ' A列が"削除"という文字列なら対象にする
        If ws.Cells(i, 1).Value = "削除" Then
            If deleteRange Is Nothing Then
                Set deleteRange = ws.Rows(i)
            Else
                Set deleteRange = Union(deleteRange, ws.Rows(i))
            End If
        End If
    Next i
    
    ' まとめて削除実行
    If Not deleteRange Is Nothing Then
        deleteRange.Delete
    End If
    
    ' 設定を元に戻す
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    
    MsgBox "削除処理が完了しました。"
End Sub

詳細解説:Unionメソッドの役割と注意点

上記のコードで鍵となるのが「Unionメソッド」です。Unionは複数のRangeオブジェクトを1つのRangeオブジェクトに結合します。これにより、ループ内では「削除対象をマークする」作業のみを行い、最後に一度だけDeleteメソッドを叩くことで、Excelの負荷を最小限に抑えています。

ただし、注意点もあります。Unionで結合するRangeがあまりにも膨大(数万箇所を超えるなど)になると、今度はメモリ不足エラーが発生する可能性があります。また、結合された範囲が離れすぎている場合、処理効率が落ちることもあります。実務では、データの特性に応じて「フィルタ機能で絞り込んで削除する」という手法と使い分けるのが正解です。

実務アドバイス:Geminiを「コードレビュー」に使う

Geminiを活用する際、コードを生成させるだけでなく、「このコードのボトルネックはどこか?」「より高速な代替案はあるか?」と問いかけることで、スキルの底上げが可能です。

例えば、以下のようにプロンプトを投げてみてください。
「このVBAコードは、1万行のデータに対して実行すると5秒かかります。これを1秒以内に短縮するためのリファクタリング案を提示してください。特に、配列処理(Variant型の配列)を用いたアプローチを含めて検討してください。」

このように、具体的な制約条件を提示することで、Geminiはより高度な「配列を用いた高速化ロジック」を提案してくれます。配列処理は、セルを直接操作せずメモリ上でデータの有無を判定するため、数万行規模であっても瞬時に処理が終わるという圧倒的なメリットがあります。

まとめ:プロフェッショナルなVBAエンジニアになるために

Excel VBAにおける行削除は、単なる削除操作ではなく「いかにExcelの計算負荷を制御するか」というエンジニアリングの試金石です。

1. 上から削除してはいけない(逆順か、一括かを選択する)。
2. Application.ScreenUpdatingを制御し、無駄な描画を止める。
3. Unionメソッドを活用して削除回数を最小化する。
4. 大規模データには配列(Array)を用いたメモリ内処理を検討する。

これら4つの原則を徹底するだけで、あなたの作成するマクロの品質は見違えるほど向上します。Geminiはあくまでツールです。そのツールを使って「なぜそのコードが最適なのか」を理解し、言語化できる能力こそが、真のベテランエンジニアの証です。

次回の11本目では、さらに一歩進んで「複雑な条件分岐を伴うデータ抽出と削除の組み合わせ」について解説します。日々の業務における自動化の質を、Geminiと共に高めていきましょう。

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