# 主任席自動割り振りマクロ 使い方

## 1. ファイル

- `主任席自動割り振り_VBA.md`  
  VBAコード本体です。説明文やコードフェンスは入れていないため、全文をそのまま標準モジュールへ貼り付けられます。

- `主任席自動割り振り_使い方.md`  
  このファイルです。

## 2. 導入

1. 対象のExcelブックを、マクロ有効ブック(`.xlsm`)として保存します。
2. `Alt + F11`でVBAエディターを開きます。
3. 対象ブックを選び、`挿入` → `標準モジュール`を選びます。
4. `主任席自動割り振り_VBA.md`を開き、全文をコピーして標準モジュールへ貼り付けます。
5. `Ctrl + S`で保存します。

コードでは`ThisWorkbook`を使っているため、個人用マクロブックではなく、座席表が入っている対象ブックへ貼り付けてください。

参照設定の追加は不要です。

---

## 3. 最初に変更する設定

コード上部の「設定」欄を、会社のブックに合わせて変更します。

### シート名

```vb
Private Const SHIFT_SHEET_NAME As String = "シフト表"
Private Const 主任_LIST_SHEET_NAME As String = "主任一覧"
Private Const LOG_SHEET_NAME As String = "主任割当ログ"
```

`LOG_SHEET_NAME`のシートは、実行時に自動作成されます。同名シートがある場合は内容が消去され、今回のログへ更新されます。

### シフト表の位置

```vb
Private Const SHIFT_DATE_ROW As Long = 1
Private Const SHIFT_NAME_COL As Long = 1
Private Const SHIFT_FIRST_NAME_ROW As Long = 2
Private Const SHIFT_FIRST_DATE_COL As Long = 2
```

例:

- 日付が3行目に並ぶ → `SHIFT_DATE_ROW = 3`
- 氏名がB列にある → `SHIFT_NAME_COL = 2`
- 最初の氏名が5行目 → `SHIFT_FIRST_NAME_ROW = 5`
- 最初の日付がD列 → `SHIFT_FIRST_DATE_COL = 4`

列番号は、A=1、B=2、C=3、D=4です。

### 対象年月

```vb
Private Const TARGET_YEAR As Long = 0
Private Const TARGET_MONTH As Long = 0
```

シフト表が1か月分だけなら、通常は両方`0`で構いません。

シフト表に複数月の実日付が横並びになっている場合は、例として2026年7月なら次のように設定します。

```vb
Private Const TARGET_YEAR As Long = 2026
Private Const TARGET_MONTH As Long = 7
```

日付見出しは、次の形式を読み取れます。

- `1`、`2`、`12`などの日番号
- `12日`
- Excelの実日付
- 日付として認識できる文字列

### 主任一覧の位置

```vb
Private Const 主任_LIST_NAME_COL As Long = 1
Private Const 主任_LIST_FIRST_ROW As Long = 2
```

例:

- 主任氏名がC列 → `主任_LIST_NAME_COL = 3`
- 最初の主任氏名が4行目 → `主任_LIST_FIRST_ROW = 4`

氏名は、シフト表と主任一覧で完全に同じ表記にするのが安全です。半角・全角スペースは比較時に除去されます。

### 主任固定席

コード内の次の関数を変更します。

```vb
Private Function Get主任SeatAddresses() As Collection

    Dim seats As New Collection

    seats.Add "F5"
    seats.Add "G5"
    seats.Add "H5"
    seats.Add "J5"

    Set Get主任SeatAddresses = seats

End Function
```

会社の実際の主任席へ置き換えてください。セルが結合されている場合は、原則として結合範囲の左上セルを指定します。

### メンバー席

主任が固定席数を超えた場合だけ使用する候補席です。

```vb
Private Function GetMemberSeatAddresses() As Collection

    Dim seats As New Collection

    seats.Add "B10"
    seats.Add "C10"
    seats.Add "D10"

    Set GetMemberSeatAddresses = seats

End Function
```

メンバー席を使用しない場合は、初期状態のまま何も追加しなくて構いません。その場合、5人目以降は未割り当てとしてログに出ます。

メンバー席は、次のどちらかの場合だけ空席として扱われます。

- 完全な空白
- `MEMBER_EMPTY_MARKER`と同じ文字

初期設定は次のとおりです。

```vb
Private Const MEMBER_EMPTY_MARKER As String = "空席"
```

一般メンバーの氏名や別の文字が入っているセルは上書きしません。

### 主任固定席の初期文字

```vb
Private Const 主任_MARKER As String = "主任"
```

日付シートの主任固定席が、すべてこの文字になっている場合だけ自動割り振りを実行します。

4席のうち1席でも人名、空白、別の文字になっているシートは、既存割り当て済みとしてスキップします。ただし、そこに入っている主任名は次の日以降の座席履歴として読み込みます。

---

## 4. 在宅セルのRGB設定

### RGBを調べる

1. シフト表の在宅を表す青色セルを選択します。
2. `Alt + F8`を押します。
3. `選択セルのRGBを確認する`を実行します。
4. 表示されたRGB値を控えます。

条件付き書式が使われている場合は「画面上の表示色」を使います。

### RGBを設定する

例として表示色が`RGB(91, 155, 213)`なら、次のように変更します。

```vb
Private Const REMOTE_COLOR_R As Long = 91
Private Const REMOTE_COLOR_G As Long = 155
Private Const REMOTE_COLOR_B As Long = 213
```

### 条件付き書式か直接塗りつぶしか

```vb
Private Const USE_DISPLAY_FORMAT As Boolean = True
```

- `True`:条件付き書式を含め、画面に見えている色で判定
- `False`:セルに直接設定された塗りつぶし色で判定

判断できない場合は、まず`True`で試してください。

RGBは完全一致で判定します。

---

## 5. 出勤扱いになるシフト

次のような「英字+数字」だけを出勤扱いにします。

- `A4`
- `C1`
- `AA2`
- `a4`

次は割り当て対象外です。

- 空白
- `PM休`
- `研`
- その他、英字+数字だけではない文字列
- 出勤コードが入っていても、セル色が設定した在宅RGBと一致する場合

---

## 6. 日付シート

日付シート名は、基本的に次の形式を想定しています。

- `1`
- `2`
- `12`
- `01`
- `12日`

1~31として解釈できるシートだけを対象にします。

実行前に、既存のマクロで1か月分の日付シートを作成し、各日付シートの主任固定席をすべて`主任`にしておきます。

---

## 7. 割り当てルール

処理は1日から31日の順で行います。

1. 前日も出勤し、前日に主任固定席へ座っていた主任は、同じ主任固定席を優先
2. それ以外は、本人が直近に使用した主任固定席を優先
3. 残った主任は、空いている主任固定席へ割り当て
4. 主任固定席がすべて埋まった場合だけ、メンバー席を使用
5. メンバー席でも、前日と同じ席、直近の席、その他の空席の順で割り当て
6. 全候補席が埋まっている場合は、既存氏名を上書きせず未割り当てとしてログへ記録

優先席がない主任同士、および同条件の空席は初期設定ではランダムです。

```vb
Private Const RANDOMIZE_UNPREFERRED_ASSIGNMENTS As Boolean = True
```

固定順にしたい場合は`False`へ変更します。

### メンバー席に関する例外

「基本は主任席から割り振る」という仕様を優先しています。

前日に5人目としてメンバー席へ座った主任でも、当日に主任固定席へ入れる場合は主任固定席へ移動します。主任固定席が当日も満席の場合に限り、前日と同じメンバー席を優先します。

### 連続出勤の判定

カレンダー上で前日との差が1日の場合を連続出勤とします。

- 11日と12日 → 連続
- 金曜日と翌週月曜日 → 連続ではない
- 日付シートがなくてもシフト列があれば、その日の出勤実績は翌日の判定に反映

---

## 8. 実行

1. 既存マクロで1か月分の日付シートを生成します。
2. 主任固定席がすべて`主任`になっていることを確認します。
3. シフト表と主任一覧を確認します。
4. `Alt + F8`を押します。
5. `主任座席を一括割り振る`を実行します。
6. 確認画面で`はい`を押します。

確認画面を出したくない場合は、次を`False`へ変更します。

```vb
Private Const SHOW_CONFIRMATION As Boolean = False
```

ボタンへ登録する場合は、ボタンに`主任座席を一括割り振る`を割り当てます。

---

## 9. 実行結果とログ

実行後、`主任割当ログ`シートが作成されます。

主な区分は次のとおりです。

- `割当`:自動で氏名を書き込んだ
- `履歴`:割り当て済みシートの座席を履歴として読み込んだ
- `スキップ`:対象条件を満たさず処理しなかった
- `未割当`:空席不足で配置できなかった
- `警告`:氏名重複、日付重複など
- `エラー`:処理を継続できない問題

同名のログシートがある場合、実行のたびに内容を消去して作り直します。

---

## 10. 再実行

一度氏名を入れた日付シートは、主任固定席の全セルが`主任`ではなくなるため、次回実行時は自動的にスキップされます。そのシートの既存座席は、後続日の割り当て履歴として利用されます。

特定の日だけ作り直す場合は、次の作業を行ってから再実行します。

1. その日の主任固定席をすべて`主任`へ戻す
2. マクロでメンバー席へ入れた主任名があれば、そのセルを空白または`空席`へ戻す
3. 再実行する

マクロには自動リセット処理を入れていません。一般メンバーの氏名を誤って消さないためです。

---

## 11. 最初の試運転

本番ブックをコピーして、次の小さな条件で試すのが安全です。

1. 3~5日分だけ日付シートを用意
2. 主任を2~5人だけ主任一覧へ登録
3. 連続出勤、休み明け、在宅、5人目のケースを作る
4. 割り当て結果とログを確認
5. 問題がなければ本番ブックで実行

特に確認する項目は次のとおりです。

- 在宅色が正しく除外されるか
- シフトコードが正しく判定されるか
- 前日の主任固定席が維持されるか
- 休み明けに直近席が優先されるか
- 5人目がメンバー席へ入るか
- 一般メンバーの氏名を上書きしないか