【VBA】見出し行の固定とスクロール領域をVBAで制御する方法(コピペOK)

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

この記事でわかること

  • VBAで見出し行を固定できる(FreezePanes)
  • 複数シートのウィンドウ枠を一括で固定できる
  • ScrollAreaでスクロール範囲を制限して、入力・閲覧領域をコントロールできる

対象: Excel 2016以降 / Microsoft 365、Windows 10/11

どんな場面で使う?

  • 月次報告ブックの全シートでヘッダー行を一括固定したいとき
  • スクロール範囲を制限してユーザーが余計な領域に迷い込まないようにしたいとき
  • 行と列の両方を同時に固定して大きな表を見やすくしたいとき
  • ブックを開くたびに自動でウィンドウ枠を固定する仕組みを作りたいとき

完成イメージ(Before / After)

Before(手作業でウィンドウ枠を固定):

操作 所要時間
各シートで「表示」→「ウィンドウ枠の固定」 約10秒/シート
シートが10枚あると1つずつ繰り返し 約2分
固定位置を間違えてやり直し さらに数分
スクロール範囲の制限は手作業では限界 対応困難

After(VBAで自動設定):

操作 所要時間
マクロ実行で全シートの見出しを一括固定 数秒
行列同時固定+スクロール制限も自動 数秒
ブックを開くたびに自動で設定 0秒

自分も以前、月次報告用のブックでシートが12枚(月ごと)あって、毎回フォーマットを整えるたびに1枚ずつウィンドウ枠の固定をやり直していた。地味にストレスだった。しかも急いでいるとスクロールして見出しが見えなくなって「この列って何だっけ?」と毎回迷う。VBAで全シートの見出し固定を一括設定するようにしてからは、新しいシートを追加してもマクロ1回で完了するようになった。この記事で、同じ手間に悩んでいる人が一瞬で解決できるようになればうれしい。

見出し行の固定は地味だけど、やっておかないとデータ確認のたびにストレスになる。VBAでまとめて設定するのが正解。

なお、ウィンドウ枠の固定・解除の基本は ウィンドウ枠の固定・解除をVBAで自動化する方法 でも解説している。

実行前の準備

バックアップを取る

ウィンドウ枠の固定自体はデータを壊す操作ではないが、ScrollAreaを設定するとスクロール可能な範囲が制限される。 意図しない範囲を設定すると操作が制限されるため、必ずファイルのコピーを別フォルダに保存してから実行する。

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

拡張子が .xlsx のままだとマクロが保存できない。

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

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

  1. Alt + F11 でVBEを開く
  2. 「挿入」→「標準モジュール」をクリック
  3. 表示された白い画面にコードを貼り付ける

手順

ステップ1:コードを貼り付ける

下のコード(最小版)をVBEの標準モジュールに貼り付ける。

ステップ2:マクロを実行する

Alt + F8 →「FreezeTopRow」を選択 →「実行」。アクティブシートの1行目が見出しとして固定される。

ステップ3:確認する

シートを下にスクロールして、1行目(見出し行)が常に表示されていればOK。

コード(最小版):1行目を見出しとして固定する


Sub FreezeTopRow()
    '--- アクティブシートの1行目を固定する ---
    '貼り付け場所:標準モジュール
    '実行方法:Alt + F8 → FreezeTopRow → 実行

    '既存の固定を解除
    ActiveWindow.FreezePanes = False

    '2行目の左端を選択してから固定(1行目が固定される)
    ActiveSheet.Range("A2").Select
    ActiveWindow.FreezePanes = True

    MsgBox "1行目を固定しました。", vbInformation
End Sub

ポイント:

  • FreezePanes = True を実行する前に、固定したい行の1つ下のセルを選択する
  • 1行目を固定したい場合 → A2を選択してからFreezePanes
  • 既存の固定を先に解除しないと、意図しない位置で固定される

コード(実務版):複数シート一括設定+行列同時固定+ScrollArea制限

自分はこの実務版を導入してから、新しい月次ブックを作るたびに「全シートの見出し固定+スクロール範囲制限」をマクロ1回で済ませている。入力担当者に渡すブックにScrollAreaを設定しておくと、「関係ないセルを触ってしまった」事故が減った。

実務版コード(標準モジュール)


Sub SetupAllSheets()
    '--- 全シートに見出し固定+スクロール範囲制限を一括設定する ---
    '貼り付け場所:標準モジュール
    '実行方法:Alt + F8 → SetupAllSheets → 実行

    Dim ws As Worksheet
    Dim currentSheet As Worksheet
    Dim freezeRow As Long
    Dim freezeCol As Long
    Dim lastRow As Long
    Dim lastCol As Long
    Dim processedCount As Long

    '★設定値(環境に合わせて変更)
    freezeRow = 2  '固定する行の位置(2=1行目を固定、3=2行目まで固定)
    freezeCol = 2  '固定する列の位置(2=A列を固定、1=列固定なし)

    Application.ScreenUpdating = False

    Set currentSheet = ActiveSheet '元のシートを記録

    processedCount = 0
    For Each ws In ThisWorkbook.Worksheets
        '非表示シートはスキップ
        If ws.Visible = xlSheetVisible Then
            ws.Activate

            '--- ここが追加:既存の固定を解除 ---
            ActiveWindow.FreezePanes = False

            '--- ここが追加:行列同時固定 ---
            'SplitRowとSplitColumnで分割位置を指定してからFreeze
            ActiveWindow.SplitRow = freezeRow - 1  '固定する行数
            ActiveWindow.SplitColumn = freezeCol - 1 '固定する列数
            ActiveWindow.FreezePanes = True

            '--- ここが追加:ScrollAreaでスクロール範囲を制限 ---
            'データがある範囲+余白を自動検出して制限する
            lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
            lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column

            'データがある場合のみScrollAreaを設定(余白として+10行、+2列)
            If lastRow >= 2 And lastCol >= 1 Then
                ws.ScrollArea = ws.Range( _
                    ws.Cells(1, 1), _
                    ws.Cells(lastRow + 10, lastCol + 2) _
                ).Address
            End If

            processedCount = processedCount + 1
        End If
    Next ws

    '元のシートに戻る
    currentSheet.Activate

    Application.ScreenUpdating = True

    MsgBox processedCount & " シートに見出し固定+スクロール範囲制限を設定しました。", vbInformation
End Sub

ScrollAreaを解除するコード(標準モジュール)


Sub ClearAllScrollArea()
    '--- 全シートのScrollArea制限を解除する ---
    '貼り付け場所:標準モジュール

    Dim ws As Worksheet

    For Each ws In ThisWorkbook.Worksheets
        ws.ScrollArea = "" '空文字で解除
    Next ws

    MsgBox "全シートのスクロール範囲制限を解除しました。", vbInformation
End Sub

実務版のポイント:

  • SplitRowSplitColumn を使うと、行と列を同時に固定できる
  • ScrollArea にセル範囲を指定すると、その範囲外にスクロールできなくなる
  • ScrollAreaはブックを閉じると解除される(保存されない)。永続化したい場合は Workbook_Open イベントで再設定する
  • 複数シートに同じ処理を一括実行する方法 のパターンで全シートをループしている

ScrollAreaの注意: ScrollAreaを設定すると、指定範囲外のセルに移動できなくなる。解除したい場合は ClearAllScrollArea を実行するか、VBEのイミディエイトウィンドウで ActiveSheet.ScrollArea = "" を実行する。

Window.SplitRow / SplitColumn と FreezePanes の使い分け

項目 FreezePanes(セル選択方式) SplitRow/SplitColumn 方式
使い方 固定位置の1つ下・1つ右のセルを選択してから FreezePanes = True SplitRow / SplitColumn に数値を設定してから FreezePanes = True
行のみ固定 A2を選択 → FreezePanes SplitRow = 1, SplitColumn = 0 → FreezePanes
列のみ固定 B1を選択 → FreezePanes SplitRow = 0, SplitColumn = 1 → FreezePanes
行列同時固定 B3を選択 → FreezePanes(2行+B列固定) SplitRow = 2, SplitColumn = 1 → FreezePanes
VBA向き セルを選択する必要がある(シートのActivateが必要) 数値指定だけで済む。行列の指定が明確

結論: VBAで使うなら SplitRow / SplitColumn 方式が分かりやすい。セル選択方式は「何行目を固定しているか」がコードから読み取りにくい。

データの最終行の取得方法が不安な場合は データの最終行・最終列を正確に取得する方法 を参照。

落とし穴

自分も最初に見出し固定マクロを書いたとき、「FreezePanes = Trueだけでしょ?」と思っていた。でも実際に動かしてみると、固定位置がずれたり、そもそも固定されなかったりで30分くらい溶かした。原因は「セルの選択位置」だった。

# 症状 原因 対策
1 固定したい位置と違う行で固定される FreezePanes = Trueの前に正しいセルを選択していない 固定したい行の「1つ下」のセルを選択してからFreezePanesを実行する。またはSplitRow方式を使う
2 FreezePanes = Trueを実行しても何も起きない 既に固定されている状態でTrueを設定しても変化しない 先に FreezePanes = False で解除してから設定し直す
3 複数シートをループすると「実行時エラー」が出る シートをActivateせずにFreezePanesを設定しようとした。FreezePanesはActiveWindowに対する操作 ループ内で ws.Activate を入れてからFreezePanesを設定する
4 ScrollAreaを設定したらセルに移動できなくなった ScrollAreaの範囲が狭すぎる、または意図しない範囲を指定した ws.ScrollArea = "" で解除する。設定時は余白を持たせる(実務版は+10行、+2列)
5 ScrollAreaがブックを再度開くと解除されている ScrollAreaプロパティはブックの保存時に保持されない Workbook_Open イベントで毎回設定し直す。イベント処理は ブックを開いたとき・保存時に自動実行するイベント処理の方法 を参照
6 非表示シートで固定しようとするとエラーになる 非表示シートはActivateできない ws.Visible = xlSheetVisible で表示シートだけ処理する(実務版は対応済み)

VBAでウィンドウ枠の固定が効かないときの対処法

「FreezePanesをTrueにしたのに固定されない」という場合、原因はActiveWindowのスクロール位置やSplitRow/SplitColumnの設定が意図と違うことだ。FreezePanes設定前に ActiveWindow.SplitRow = 1 で分割位置を明示し、スクロール位置をA1に戻してから実行する。

VBAのScrollAreaが保存されないときの対処法

「ScrollAreaを設定したのにブックを閉じると元に戻る」という場合、原因はScrollAreaプロパティがブック保存時に保持されないExcelの仕様だ。Workbook_Openイベントで毎回設定し直すか、Auto_Openマクロで起動時にScrollAreaを適用する。

FAQ

Q1. 2行目まで(1〜2行目)を固定したい場合は?

Range("A3").Select してから FreezePanes = True を実行する。SplitRow方式なら SplitRow = 2 に設定する。固定したい行数をSplitRowに指定すればよい。

Q2. 列だけ固定したい場合は?

A列を固定したい場合は Range("B1").SelectFreezePanes = True。SplitRow方式なら SplitRow = 0 / SplitColumn = 1 に設定する。

Q3. ScrollAreaはブックを閉じても保持される?

保持されない。ブックを閉じると ScrollArea は空に戻る。永続化したい場合は Workbook_Open イベントで毎回設定する。自分も最初これを知らなくて「設定したはずなのに消えてる」と悩んだ。

Q4. 印刷時の見出し固定とは違うのか?

違う。FreezePanesは画面表示でのスクロール時の固定。印刷で毎ページに見出しを表示したい場合は PageSetup.PrintTitleRows を使う。詳細は 複数シートの印刷設定を一括変更して印刷する方法 を参照。

Q5. マクロなしでウィンドウ枠を固定する方法は?

「表示」タブ →「ウィンドウ枠の固定」→「先頭行の固定」で1行目を固定できる。ただし、複数シートに一括で設定したい場合やScrollAreaの制限を加えたい場合は、VBAを使うのが効率的。

まとめ

この記事では、VBAで見出し行の固定とスクロール領域の制御を自動化する方法を解説した。

  • 基本: FreezePanes = True で見出し行を固定(固定位置の1つ下のセルを選択)
  • 実務版: 複数シート一括設定+行列同時固定(SplitRow/SplitColumn)+ScrollAreaでスクロール制限
  • 使い分け: VBAでは SplitRow/SplitColumn 方式が分かりやすい

見出し固定はデータ閲覧の基本。ScrollAreaを組み合わせれば、入力担当者が触ってはいけない範囲を制限することもできる。

次にやりたくなること

コメント

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