Excelのデータへ連番（1,2,3…）をふるべき理由とマクロ紹介

# 1 . 連番を振る理由

## 1-1. データを一意に識別するため

データベース形式のデータでは、各行が1つのレコードを表します。このレコードを一意に識別するためには、各行にユニークなIDが必要です。連番は、最も簡単で確実な方法として活用できます。

たとえば、以下のようなデータがあるとします：

|No  |名前  |年齢 |職業 |
|:-:|---|:-:|---|
|1  |山田太郎|30|会社員|
|2  |鈴木花子|25|デザイナー|
|3  |高橋一郎  |38  |エンジニア  |

このように連番を振ることで、データを一意に管理しやすくなります。

## 1-2. フィルターや並び替え後の混乱を防ぐ

Excel等でデータをフィルターや並び替えを行った際、元のデータの順序が分からなくなることがあります。しかし、連番があれば、簡単に元の順序に戻すことができます。
（ただし、元に戻せるためには連番が直値で、振られていることが前提となります。ExcelではROW関数で動的に連番を振ることもでき、これはこれで便利なのですが、並び替えによって番号が変更してしまうので、ROW関数を利用して連番を振っている場合には、元に戻せないため注意です。）

## 1-3. 部分的なデータ抽出でも一貫性を保つ

データベース形式のデータを分析や処理のために部分的に抽出することがあります。このとき、連番があれば、抽出元データとの対応関係が明確になります。

# 2.データに飛びがある場合の課題

Excelでは、データに空白行や不要なデータが混在している場合があります。このようなデータに対して連番を振らずに処理を行うと、次のような問題が発生します。

## 2-1. フィルター対象から外れるケース

たとえば、以下のようなデータを考えてみましょう：

|名前  |年齢 |職業 |
|---|:-:|---|
|山田太郎|30|会社員|
|　||
|鈴木花子|25|デザイナー|
|高橋一郎  |38  |エンジニア  |

このデータに対してフィルターを適用した場合、空白行が原因で結果に飛びが発生することがあります。

![スクリーンショット 2025-01-23 174935.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/88fca634-b2f1-8d0a-393b-b96d776f0430.png)

このときに名前列のフィルターを確認してみると、空行以降にあるデータの『高橋一郎』は出てきません。つまり、フィルターの対象から外れているということになります。

![スクリーンショット 2025-01-23 175228.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/899f04a3-8103-ddf3-ed89-fabe50b351b7.png)

これは、基本的には、選択している行を含むデータが存在している行までを対象に、自動的にフィルター設定が行われているためです。

データベース形式のデータに空行があることが本来おかしいのですが、実務では完全なデータベース形式ではないデータを取り扱うことなんで、結構ありますよね。

このような空行があるデータで、本来フィルター範囲に含まれて欲しい部分を含めるには、左側に連番を振っておけば、空白行以降のデータも、フィルター範囲に含めることができます。

先ほどのデータの左に連番を追加すると・・・。

![スクリーンショット 2025-01-23 175537.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/ec09c71b-b64d-f279-80e5-946e3c4c9fd5.png)

今度は、空白以降のデータも、フィルターの範囲に含まれました！

![スクリーンショット 2025-01-23 175724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/39a4e801-669c-7606-52f9-08cbf40f8e45.png)

# 3. 連番を振る具体的な方法

連番をふるべき理由は理解できたかと思いますので、実際に連番をふる方法を2つ紹介します。

## 3-1. 手動で連番を入力する
手動とはいえ、手入力ですべての数値を入力するのはミスの原因になるので、そんなことはしません。実際にはExcelの連番データ機能を利用します。
連番を振りたいセルに1と入力し、ドラッグする。
オートフィルを実行した時に表示される「オートフィル オプション」を右クリックし、「連続データ」を選択します。

オートフィルが動作せず、単なるコピーとなる場合は、フィルターがかかっていることがあります。フィルターを解除してから、オートフィルをやり直しましょう。

:::note warn
ただし、直値の連番の場合に、途中に行を挿入して追加した場合には、改めて連番を振りなおす必要があります。途中から最終行まで連番を振りな直す必要があるのが、この方法のデメリットです。
![スクリーンショット 2025-01-23 183346.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/c62d5b99-3887-6c26-8564-8ecabb3684d0.png)
:::

:::note info
しかし、フィルターや並び替えを行った際、元のデータの順序が分からなっても、簡単に元の順序に戻すことができるのが良い点です。
:::

## 3-2. ROW関数を利用する

Excelの関数「ROW」を使用して連番を自動生成することも可能です。

![スクリーンショット 2025-01-23 181321.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/086e8f5f-13bb-1d60-9499-dc969d9079ef.png)

:::note info
この方法の場合は、途中に行を挿入しても、最終行まで連番を振りなおす必要はありません。
:::

:::note warn
ただし、ROW関数を利用した場合は、並び替えによって番号が変更してしまうので、ROW関数を利用して連番を振っている場合には、元に戻せないため注意です。

【並び替え前】（山田→鈴木→高橋の順番）

![スクリーンショット 2025-01-23 181652.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/ad2dd384-9167-d26d-64fd-038c8eb53326.png)

【年齢列を昇順する】（鈴木→高橋→山田の順番）

![スクリーンショット 2025-01-23 181828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/ccdc38b1-68be-eba9-683f-79903d714f49.png)
鈴木→高橋→山田の順番に変更したがNOが自動で振り直されている。
:::

ちなみに、同じ関数を利用するのでもROW関数ではなく、上のセルを参照して「+1」としていく方法もあります。

![スクリーンショット 2025-01-23 183916.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/5ecf0701-f934-246b-faff-eeecaa4db7c1.png)

この方法は入力も簡単で良いのですが、並び替えると下記のようになってしまって、ROW関数以上に支障がありました。（このようになるのは、Excelのバージョンにもよるかもしれません。）

![11_スクリーンショット 2025-01-23 184033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/9087692d-07aa-a416-5a84-2898f14aa6dc.png)


# 4. 連番を振るマクロの紹介

それぞれの連番の振り方のメリットとデメリットは理解したと思うので、連番を振るのに便利なマクロを紹介します。

## 4‐1.直値の連番を途中に行挿入した際に振り直すのを便利にするマクロ

アクティブセルからInputBoxへ入力した指定数値から最終行まで連番を振るマクロです。
1から振るようにしていないのは、途中に行挿入した際に振り直すのを便利にするマクロであるためです。

```vb:ExcelVBA
Sub sbアクティブセルから最終行までの連番作成()
 
   Dim baseNum As Variant     '連番を開始するアクティブセルの番号をInputBoxで入力するための変数（キャンセル時にFalseとなるためVariant型）
   Dim tgtRow As Long         'アクティブセルの行番号取得
   Dim tgtCol As Long         'アクティブセルの列番号取得
   Dim lastRow As Long        '最終行の行数を取得する用の変数
 
   Dim i As Long 'カウンター用変数
   Dim num As Long 'カウンター用変数
   Dim myMsg As String 'メッセージボックス用変数
 
   Dim targetSheet As Worksheet '対象シート
   Set targetSheet = ActiveSheet
   Dim zMessageResult As VbMsgBoxResult 'vbYesNoの戻り値は『はい』が6、『いいえ』が7（VbMsgBoxResult列挙型）
           
    'フィルター時には正しく挙動しないため、フィルターがかかっているか判定してから作業
    If targetSheet.FilterMode = True Then
   
         'フィルターを解除してマクロ実行するかどうかの選択肢：はい、いいえ、キャンセル
         zMessageResult = MsgBox( _
                PROMPT:="現在フィルターがかかっている状態です。。" & vbCrLf & _
                      "フィルターを解除しますか？", _
                TITLE:="注意", _
                Buttons:=vbYesNo + vbQuestion)
         If zMessageResult = vbYes Then  'vbYes＝『はい（6）』
            targetSheet.ShowAllData  'フィルター解除
         Else
            MsgBox "マクロ実行をキャンセルします"
            Exit Sub
         End If
    End If
   
    baseNum = Application.InputBox( _
              PROMPT:="アクティブセルに入力する番号（1以上の整数）を入力してください。" & vbCrLf & _
                      "（入力された番号から連番を開始して最終行まで連番を入力します。）", _
              TITLE:="連番開始数値入力", _
              Type:=1)
    If TypeName(baseNum) = "Boolean" Then
        MsgBox "マクロ実行をキャンセルします"
        Exit Sub
    End If
   
    '入力された数値が整数か判定（小数点があるならマクロ実行キャンセル）
    If Int(baseNum) <> baseNum Then
        MsgBox "入力された数値が小数点であるためマクロ実行をキャンセルします"
        Exit Sub
    End If
  
   If baseNum < 1 Then baseNum = 1 '入力された連番開始Noが2未満の場合のみ見出し行数を1として取り扱う（通常、1行目はヘッダと想定）
       tgtRow = ActiveCell.Row                 'アクティブセルの行番号取得
       tgtCol = ActiveCell.Column              'アクティブセルの列番号取得
       lastRow = ActiveCell.End(xlDown).Row    'アクティブセルを起点としてCTRL+↓した場合の最終行数を取得(データ
       num = baseNum 'num変数の初期値（開始番号）設定
      
       For i = tgtRow To lastRow   'アクティブセルから最終行まで連番を入力
         Cells(i, tgtCol).Value = num
         num = num + 1
       Next i

   myMsg = "処理が終了しました。" & vbCrLf + myMsg
   MsgBox myMsg, , "処理結果通知"
 
End Sub
```

## 4‐2.ROW関数をアクティブセルに利用して「1」を入力
１を入力するのが、必ずしも１行目とは限らないので、アクティブセルにROW関数を利用して「1」を表示する計算式を作成します。
リボンにマクロを登録して利用すると便利です。

```vb:ExcelVBA
Sub sbアクティブセルへROW関数で1を入力()
'- アクティブセルに1と表示されるように、ROW関数を入力する
'- 例：B4セルがアクティブなとき　→=ROW()-ROW(B$3)
 
    ' 変数の宣言
    Dim currentCell As Range              ' アクティブセルを表す変数
    Dim referenceCellAddress As String    ' 参照セルのアドレスを格納する文字列変数
    Dim formulaText As String             ' 入力する数式を格納する文字列変数
    Dim referenceRow As Long              ' 参照セルの行番号を表す変数
 
    ' アクティブセルを取得
    Set currentCell = ActiveCell  ' アクティブセルをcurrentCellに設定
 
    ' アクティブセルが1行目の場合のエラーハンドリング
    If currentCell.Row = 1 Then
        formulaText = "=ROW() "
        GoTo jump
    End If
 
    ' 参照セルの行番号を取得（アクティブセルの1つ上）
    referenceRow = currentCell.Row - 1  ' アクティブセルの1つ上の行番号を取得
 
    ' 参照セルのアドレスを取得（同じ列、列は絶対参照、行は相対参照）
    referenceCellAddress = currentCell.Parent.Cells(referenceRow, currentCell.Column).Address(RowAbsolute:=True, ColumnAbsolute:=False)  ' アドレスを取得
 
    ' 入力する数式を作成
    formulaText = "=ROW()-ROW(" & referenceCellAddress & ")"  ' 数式を作成

jump:
    ' 数式をアクティブセルに入力
    currentCell.formula = formulaText  ' 数式を設定
    
    Dim myMsg As String 'メッセージボックス用変数
    myMsg = "処理が終了しました。"
    MsgBox myMsg, , "処理結果通知"
End Sub
```

以上、いかがでしたでしょうか。
何かのお役に立てましたら、幸いです。