【VBA】行の追加・削除に対応した自動連番を振る方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

検査データに通し番号を振っている。データ数が毎日変わる。昨日は50件、今日は73件。毎回最終行を確認して、次の番号を手入力する。1つずれると以降全部ずれる。しかも月が変わると番号体系もリセットしたい。「2026-04-001」「2026-04-002」のように年月付きの連番にしているが、月初に手動で「001」に戻すのを忘れて先月の続きから振ってしまったことがある。

VBAで自動連番にしてからは、データを追加するたびに自動で次の番号が振られる。月が変われば自動でリセット。番号のずれも重複もゼロ。

  • 対象:行を追加・削除するたびに連番を手作業で振り直している人、VBAが初めての人
  • 所要時間:コピペ → 動作確認まで約5分(目安)

どんな場面で使う?

  • 品質管理 — 検査データに「2026-04-001」形式の通し番号を振っている。データ数が毎日変わるので手入力だとずれる。月替わりのリセットも自動にしたい
  • 事務 — 管理台帳や顧客リストで行を追加・削除するたびに連番を手で振り直している。報告書に番号を振っているが、行削除で抜け番が発生して指摘される
  • 経理 — 伝票番号や受付番号を001形式の書式付き連番で自動採番したい。手入力だと重複や抜けが発生する
  • 製造 — 製造ロット番号をシート上でデータを編集するたびに自動で更新してほしい

最終行の取得(Cells.End(xlUp).Row)の仕組みが分からない場合は、先に最終行を取得する方法を読んでおくと理解がスムーズ。

完成イメージ(Before / After)

Before(実行前)

Before(実行前)のExcel画面

行の削除後、A列の連番が飛んでいる(3番が抜けている)。

A(No.) B(名前) C(部署)
1 No. 名前 部署
2 1 田中 営業部
3 2 鈴木 総務部
4 4 佐藤 製造部
5 5 山田 品質管理部

After(実行後)

After(実行後)のExcel画面

連番が1から振り直され、抜け番がなくなった。

A(No.) B(名前) C(部署)
1 No. 名前 部署
2 1 田中 営業部
3 2 鈴木 総務部
4 3 佐藤 製造部
5 4 山田 品質管理部

実行前の準備

バックアップを取る

既存のデータが入っているExcelファイルで試す場合は、先にファイルをコピーしてバックアップを取ること。連番の上書きは元に戻せない。

Excelをマクロ有効ブック(.xlsm)で保存する

  1. Excelを開く(新規でも既存でもOK)
  2. 「ファイル」→「名前を付けて保存」
  3. ファイルの種類を 「Excel マクロ有効ブック (*.xlsm)」 に変更して保存

.xlsx のままだとマクロが保存されない。必ず .xlsm にすること。

シートのレイアウトを確認する

A B C
1 No. 名前 部署
2 (連番が入る) 田中 営業部
  • A列: 連番を入れる列
  • B列: データが入っている列(この列で最終行を判定する)
  • 1行目: ヘッダー行(連番の対象外)

手順(コピペ → 動作確認まで約5分)

VBE(コードを書く画面)を開く

Alt + F11 キーを押すとVBE(Visual Basic Editor)が開く。

一般的にはAlt + F11で開けるが、企業のセキュリティ設定でVBAが無効化されている場合は、IT部門に確認すること。

標準モジュールを作成する(最小版・実務版の場合)

  1. VBE のメニューから「挿入」→「標準モジュール」をクリック
  2. 右側にコードウィンドウが開く → ここにコードを貼り付ける

コードを貼り付ける

下の「コード(最小版)」をコピーして、標準モジュールのコードウィンドウに貼り付ける。

動作を確認する

  1. VBEからExcelの画面に戻る(Alt + F11 または タスクバーでExcelをクリック)
  2. Alt + F8 を押してマクロ一覧を表示
  3. 「連番を振る」を選択して「実行」をクリック
  4. A列に連番が振られ、MsgBox で件数が表示されれば成功

コード(最小版)– シンプルなFor文で連番を振る

まずはこれだけで動く。A列の2行目からB列の最終行まで、1, 2, 3… と連番を振る。

貼り付け先は標準モジュール


Sub 連番を振る()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    For i = 2 To lastRow
        ws.Cells(i, 1).Value = i - 1
    Next i

    MsgBox (lastRow - 1) & " 件に連番を振りました。"
End Sub

コードの動作:

  1. B列の最終行を取得する(A列ではなくB列で取るのがポイント。最終行の取得についてはこちら(/032)
  2. 2行目から最終行までFor文でループ
  3. A列に i - 1(= 1, 2, 3…)を代入
  4. MsgBox(/035)で処理件数を表示

注意: B列にデータがない行にも連番が振られる。空白行をスキップしたい場合は、次の実務版を使う。

コード(実務版)– 空白行スキップ + 書式付き連番(001形式)

自分はこの実務版を管理台帳で使ってから、台帳番号の振り直し作業がゼロになった。空白行をスキップして、001, 002, 003… の書式付き連番を振る。

貼り付け先は標準モジュール


Sub 連番を振る_実務版()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim num As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    If lastRow < 2 Then
        MsgBox "データがありません。", vbExclamation
        Exit Sub
    End If

    num = 0
    For i = 2 To lastRow
        If ws.Cells(i, 2).Value <> "" Then
            num = num + 1
            ws.Cells(i, 1).Value = Format(num, "000")
        Else
            ws.Cells(i, 1).ClearContents
        End If
    Next i

    MsgBox num & " 件に連番を振りました。"
End Sub

追加ポイント:

  • B列が空白の行はスキップし、A列の連番もクリアする
  • Format(num, "000") で3桁の書式付き連番(001, 002, 003…)を生成
  • データが1件もない場合はMsgBoxで通知して終了(ガード処理)
  • カウンタ num を別に持つことで、空白行があっても連番が飛ばない

書式を変えたい場合: Format(num, "000")"000" を変更する。4桁なら "0000"、接頭辞付きなら "A-" & Format(num, "000")

コード(自動版)– Worksheet_Changeイベントで行追加・削除に自動対応

ここからが本題。B列の値が変わるたびに、自動でA列の連番を振り直す。行を追加・削除しても、B列のどこかを編集すれば連番が自動で整う

Worksheet_Changeイベントの基本はセルの値が変わったら自動実行(/008)で解説しているので、初めての場合は先に読んでおくと理解しやすい。

★ 貼り付け先はシートモジュール(標準モジュールではない)

  1. VBE の左側のツリーで、対象のシート名(例:Sheet1 (Sheet1))をダブルクリック
  2. 右側にコードウィンドウが開く → ここに貼り付ける
  3. 「挿入」→「標準モジュール」は使わない

' シートモジュールに貼り付け
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim lastRow As Long
    Dim i As Long
    Dim num As Long

    ' B列の変更時のみ実行
    If Intersect(Target, Me.Columns(2)) Is Nothing Then Exit Sub

    On Error GoTo ErrHandler
    Application.EnableEvents = False

    lastRow = Me.Cells(Me.Rows.Count, 2).End(xlUp).Row

    num = 0
    For i = 2 To lastRow
        If Me.Cells(i, 2).Value <> "" Then
            num = num + 1
            Me.Cells(i, 1).Value = num
        Else
            Me.Cells(i, 1).ClearContents
        End If
    Next i

    Application.EnableEvents = True
    Exit Sub

ErrHandler:
    Application.EnableEvents = True
    MsgBox "連番の処理中にエラーが発生しました。" & vbCrLf & Err.Description, vbExclamation
End Sub

重要:EnableEvents について

Application.EnableEvents = False は、イベントの発火を一時的に止める命令。これがないとA列への書き込みで再びWorksheet_Changeが発火し、無限ループになる。処理が終わったら必ず True に戻すこと。上記コードでは On Error GoTo ErrHandler を入れているため、エラーが発生しても EnableEvents は確実に True に戻る。万が一無限ループに入った場合の対処法は次のセクションで解説する。

コードの動作:

  1. B列のセルが変更される → Worksheet_Change が自動で実行される
  2. B列以外の変更は無視(Intersect で判定)
  3. EnableEvents を False にして無限ループを防止
  4. B列にデータがある行だけにA列で連番を振る
  5. B列が空の行はA列もクリア
  6. EnableEvents を True に戻して終了

注意: 行を削除しただけではB列の値は変更されないため、Worksheet_Changeは発火しない。行を削除した後、B列のどこかのセルを編集すれば連番が自動で振り直される。

もし無限ループに入ったら(対処法)

EnableEvents を書き忘れた場合、Excelがフリーズすることがある。

対処手順:

  1. Ctrl + Break を押す(多くのキーボードで中断できる)
  2. Ctrl + Break が効かない場合(ノートPCでBreakキーがない等)→ Ctrl + Alt + Delete →「タスク マネージャー」→ Excel を選択 →「タスクの終了」
  3. Excelを再起動し、ファイルを開き直す
  4. VBE(Alt+F11)を開き、「表示」→「イミディエイト ウィンドウ」(Ctrl+G)で以下を入力して Enter:

Application.EnableEvents = True

これでイベントが復旧する。

よくある落とし穴5選

# 症状 原因 対策
1 Excelがフリーズする(無限ループ) Worksheet_ChangeでA列に値を書き込むが、EnableEvents = False を書いていない コードの先頭に Application.EnableEvents = False、末尾に True を必ず書く。自分もこれで30分溶かした
2 Worksheet_Changeのコードを貼り付けたのに動かない 標準モジュールに貼り付けている。Worksheet_Changeはシートモジュール専用 VBEの左ツリーで対象シート(例:Sheet1)をダブルクリックして、そこに貼り付ける。最小版・実務版とは貼り付け場所が違う
3 連番が001なのにSUMやVLOOKUPで使えない Format("000") の戻り値は文字列。数値として認識されない 数値計算に使いたい場合は Format を使わず数値のまま振る。表示だけ3桁にしたい場合はセルの表示形式で NumberFormat = "000" を設定すれば、数値のまま3桁表示できる(例:ws.Cells(i, 1).NumberFormat = "000"
4 行を挿入しても連番が振り直されない 行を挿入しただけではB列に値が入らず、Worksheet_Changeが発火しない 行を挿入した後にB列に値を入力すれば発火する。またはWorksheet_SelectionChangeイベントの併用も検討
5 保護シートで連番が振られない シート保護中はVBAからの書き込みもブロックされる Protect 時に UserInterfaceOnly:=True を指定すれば、VBAからの書き込みは許可される。詳しくはシート保護の方法(/027)

VBAで連番を振ったのに番号が飛ぶときの対処法

「連番マクロを実行したのに番号が飛ぶ」という場合、原因はA列(連番列)で最終行を取得していることだ。A列に古い連番が残っていると、B列のデータより多い行数を拾ってしまう。対処法は、最終行の取得をB列(データ列)に変更すること。コード内の Cells(ws.Rows.Count, 2)2 がB列を指している。

VBAのWorksheet_Changeが動かないときの対処法

「コードを貼り付けたのにWorksheet_Changeが動かない」という場合、原因は貼り付け先が標準モジュールになっていることだ。Worksheet_Changeはシートモジュール専用のイベントなので、VBEの左ツリーで対象シート(例:Sheet1)をダブルクリックして開くコードウィンドウに貼り付ける必要がある。

FAQ

Q1: 連番の開始番号を100からにしたい

実務版・Worksheet_Change版では、連番を代入している部分を num + 99 に変更する。たとえば実務版なら ws.Cells(i, 1).Value = Format(num + 99, "000") とすれば、100, 101, 102… のように振られる。最小版の場合は ws.Cells(i, 1).Value = i - 1 + 99 でも同じ結果になる。

Q2: 連番に接頭辞を付けたい(A-001, B-002など)

Format(num, "000")"A-" & Format(num, "000") に変更する。ただし文字列になるので数値計算には使えない。

Q3: B列以外のデータ列で最終行を判定したい

Cells(ws.Rows.Count, 2)2 を変更する。C列なら 3、D列なら 4。Worksheet_Change版は Me.Columns(2)2 も同様に変更する。

Q4: Worksheet_Changeが突然動かなくなった

EnableEventsがFalseのまま残っている可能性が高い。VBEを開き、「表示」→「イミディエイト ウィンドウ」(Ctrl+G)で Application.EnableEvents = True と入力してEnter。これで復旧する。

Q5: 複数シートに同じ連番処理をしたい

シートモジュールのWorksheet_Changeコードを、各シートのシートモジュールにそれぞれコピペする。標準モジュールの実務版なら、複数シートに一括処理する方法(/015)の手法で全シートにループ実行できる。

まとめ

この記事で、VBAで自動連番を振り、行の追加・削除にも対応できるようになった。

  • 最小版:For文でA列に1, 2, 3…と連番を振る
  • 実務版:空白行スキップ + 書式付き連番(001形式)
  • 自動版:Worksheet_Changeイベントで、B列変更のたびに連番を自動で振り直す

重要なのは以下の2点:

  1. 最終行の取得はB列(データ列)で行う(A列で取ると連番が残っている行を拾ってしまう)
  2. Worksheet_Change版は EnableEvents = False を必ず書く(無限ループ防止)

関連記事

次にやりたくなること

もっとカスタマイズしたい場合

「複数シートに一括で設定したい」「採番ルールが複雑(年度+連番など)」「特定の条件のときだけ連番を振りたい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できます。

相談時に以下の情報があるとスムーズです:

  • Excel のバージョン / OS
  • 連番のフォーマット(001形式、A-001形式など)
  • データの列構成(どの列に連番を振るか、最終行の判定列はどこか)
  • 行の追加・削除の頻度と運用方法

コメント

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