Excelの選択範囲の情報で行グループ化するVBAマクロ


# はじめに
2008年くらいにWindows版Excelで作成したVBAマクロを見つけたので、Mac版Excelでも動くのか試してみたのですが、大抵動く、という結果でした。
せっかくなので、VBAマクロを切り出して残しておこうと思います。

# VBAマクロ
## 概要
Excelの行グループを行うVBAマクロです。
「グループとアウトラインの設定」で「詳細データの下」のチェックを外す前提のマクロです。

以下のようなデータと範囲選択を行なった状態で AutoRowGrouping() を実行すると、、、
>![実行前イメージ](https://qiita-image-store.s3.amazonaws.com/0/174697/f8af143c-d9ce-75f2-6758-80d609526189.png "実行前イメージ")

以下のようなグループ化を行います。
>![実行後イメージ](https://qiita-image-store.s3.amazonaws.com/0/174697/0d9944a6-b8b2-94f6-7a8c-f8f20877b2ca.png "実行後イメージ")

入力値があるセルをグループ化の先頭として、未入力のセルをグループ化します。下方向にグループ化するため、「詳細データの下」のチェックを外す前提という分けです。

## ソース
```vbnet
Option Explicit

'=====================================================================
'共通
'=====================================================================

'---------------------------------------------------------------------
'選択エリア情報格納用
'---------------------------------------------------------------------
Public Type SelectionInfo
    StartRowIndex As Long   '選択エリアの一番上の行インデックス
    StartColIndex As Long   '選択エリアの一番左の列インデックス
    EndRowIndex As Long     '選択エリアの一番下の行インデックス
    EndColIndex As Long     '選択エリアの一番右の列インデックス
    RowCount As Long        '選択エリア内の行数
    ColCount As Long        '選択エリア内の列数
    CurrentRowIndex As Long '現在の行インデックス
    CurrentColIndex As Long '現在の列インデックス
End Type

'---------------------------------------------------------------------
'選択エリア情報格納処理
'---------------------------------------------------------------------
'シートの内容を加工するのに必要となる「選択エリア」の情報を格納して返します。
Public Function GetSelectionInfo() As SelectionInfo

    Dim selInf As SelectionInfo
    
    With selInf
        .StartRowIndex = Selection.Row
        .StartColIndex = Selection.Column
        .EndRowIndex = Selection.Rows.Count + Selection.Row
        .EndColIndex = Selection.Columns.Count + Selection.Column
        .RowCount = Selection.Rows.Count
        .ColCount = Selection.Columns.Count
        .CurrentRowIndex = ActiveCell.Row
        .CurrentColIndex = ActiveCell.Column
    End With

    GetSelectionInfo = selInf

End Function

'=====================================================================
' 行自動グループ化
' -------------------------------------------------------------------
' 行のグループ化を自動で行う
'=====================================================================
Public Sub AutoRowGrouping()
    '選択された1カラムを基準に、以降が空白の行のグループ化を行う
    Dim rowIdx As Long      '処理用インデックス
    Dim lngGrpRowFrom As Long  'グループ化する行の開始位置(動的に使用)
    
    Dim selInf As SelectionInfo 'シートの選択領域
    
    '選択情報取得
    selInf = GetSelectionInfo()
    
    lngGrpRowFrom = selInf.StartRowIndex
    
    '一番左の列だけ参照し、上から順にグループ化する
    For rowIdx = selInf.StartRowIndex To (selInf.EndRowIndex - 1)
        'セルが空の場合はスキップ
        If Cells(rowIdx, selInf.StartColIndex) <> "" Then
            'グループ化開始位置と現在位置が同じ場合はグループ化しない
            If lngGrpRowFrom <> rowIdx Then
                'グループ化実施
                Range(Cells(lngGrpRowFrom, 1), Cells(rowIdx - 1, 1)).Rows.Group
            End If
            'グループ化開始位置を現在位置の次に変更
            lngGrpRowFrom = rowIdx + 1
        End If
    Next
    '最終位置のグループ化
    If lngGrpRowFrom <> rowIdx Then
        Range(Cells(lngGrpRowFrom, 1), Cells(rowIdx - 1, 1)).Rows.Group
    End If

End Sub

```

# 補足
## 共通部について
本当は、共通に記述されているPublicな定義は、別のモジュールに定義されていました。Publicのままにしていますが、特別な意味はないので必要に応じてPrivateにして良いです。

## 所感
当時、機能一覧やタスク一覧を羅列した後に、前述の図のような見出し行を作成して一覧表を作ることが多かったため、このようなVBAマクロを作成していました。
「[Excelの選択範囲の通常表をネスト的な表にするVBAマクロ](http://qiita.com/moroshi/items/aef579abddf9a5b9b9ae)」でネスト的な表を作成した上で、グループ化する流れです。あれば使うことはありそうだけど、、、そうでもないか。

## Windows版をMacで実行した際の修正点
特にありません。