概要
Excel VBAを用いたデータ加工において、不規則に並んだ数値群の中から「連続する数値」を抽出し、それらを「1-3, 5, 8-10」のような形式で連結する処理は、在庫管理や工程管理、あるいはログデータの集計などで頻出する非常に重要なテクニックです。本記事では、この「連続数値のグループ化と連結」という課題に対する効率的なアルゴリズムを解説します。初心者から中級者へステップアップするために必要な、配列の操作、ループの制御、そして文字列連結の最適化について深く掘り下げていきます。
詳細解説:ロジックの核心
連続する数値を扱う際、最も重要になるのは「前の数値と今の数値を比較する」という条件分岐の視点です。単に数値を並べるだけでなく、その数値が「前の数値+1」であるか否かを判定することで、グループの開始と終了を特定できます。
このロジックを実装する上で、以下の3つのステップが不可欠です。
1. 数値のソート(整列):データがバラバラだと比較が不可能です。あらかじめ昇順に並べ替える処理を組み込む必要があります。
2. グループ判定:現在の値が「直前の値 + 1」であるかを確認します。一致していればグループ継続、一致しなければ新しいグループの開始とみなします。
3. 文字列の動的生成:連続の長さによって「1-3」のようにハイフンを入れるか、単独で「5」とするかを制御します。
特に、ループ処理における境界値(最初の要素と最後の要素)の取り扱いはバグの温床になりやすいため、フラグ管理やインデックスの制御には細心の注意を払う必要があります。
サンプルコード
以下に、シート上のA列にある数値リストを読み込み、連続する数値をハイフンで連結してB1セルに出力するサンプルコードを提示します。
Sub JoinConsecutiveNumbers()
Dim ws As Worksheet
Dim rng As Range
Dim dataArr As Variant
Dim i As Long, j As Long
Dim temp As Double
Dim result As String
Dim startNum As Double, endNum As Double
Set ws = ActiveSheet
' A列のデータを配列に格納
dataArr = ws.Range("A1:A" & ws.Cells(ws.Rows.Count, 1).End(xlUp).Row).Value
' バブルソート(簡易的な昇順並び替え)
For i = LBound(dataArr) To UBound(dataArr) - 1
For j = i + 1 To UBound(dataArr)
If dataArr(i, 1) > dataArr(j, 1) Then
temp = dataArr(i, 1)
dataArr(i, 1) = dataArr(j, 1)
dataArr(j, 1) = temp
End If
Next j
Next i
' 連続数値の抽出と文字列生成
startNum = dataArr(LBound(dataArr), 1)
endNum = dataArr(LBound(dataArr), 1)
For i = LBound(dataArr) + 1 To UBound(dataArr)
If dataArr(i, 1) = endNum + 1 Then
' 連続している場合は終了値を更新
endNum = dataArr(i, 1)
Else
' 連続が途切れたら文字列に追加
If startNum = endNum Then
result = result & startNum & ", "
Else
result = result & startNum & "-" & endNum & ", "
End If
startNum = dataArr(i, 1)
endNum = dataArr(i, 1)
End If
Next i
' 最後のグループの処理
If startNum = endNum Then
result = result & startNum
Else
result = result & startNum & "-" & endNum
End If
' 結果を出力
ws.Range("B1").Value = result
End Sub
実務アドバイス:パフォーマンスと保守性
実務において、このコードをより堅牢にするためのポイントをいくつか伝授します。
第一に「データの重複排除」です。入力データに同じ数値が含まれている場合、上記のコードでは意図しない動作(例:1, 1, 2 とあると1-2-2のようになる)を引き起こす可能性があります。実務では、あらかじめ「Scripting.Dictionary」オブジェクトを使用してユニークな値のみを抽出してからソートする工程を挟むのが定石です。
第二に「配列処理の活用」です。セルを直接操作するのではなく、一度配列に格納してメモリ上で処理を行うことは、VBAの実行速度を劇的に向上させます。数千件のデータを取り扱う場合、セルへのアクセス回数を減らすことがプロフェッショナルの条件です。
第三に「例外処理」です。データが空の場合や、数値以外の文字列が含まれている場合にエラーで停止しないよう、`IsNumeric` 関数を用いたチェックをループの冒頭に組み込んでください。これにより、予期せぬデータ入力に対しても「止まらないマクロ」を実現できます。
まとめ
連続する数値をハイフンで連結するこの課題は、単なるパズルのような練習問題ではなく、VBAプログラミングの基礎である「データの読み込み」「並び替え」「条件判定」「動的出力」という4つの構成要素を網羅した、非常に教育効果の高いテーマです。
コードを書く際には、常に「この処理は別のデータセットでも機能するか?」という汎用性を意識してください。特定のシート構成に依存せず、引数として配列を受け取るような関数形式(Function)にリファクタリングすることで、あなたのマクロ資産はより強力なツールへと進化します。
今回の解答を参考に、ぜひご自身の手でコードを打ち込み、ステップ実行を行いながら、内部の変数がどのように変化していくかを観察してみてください。VBAの理解を深める唯一の道は、自分の手でコードを動かし、論理のバグと格闘する経験そのものです。この一歩が、あなたの事務作業を劇的に変える自動化への確実なステップとなります。
