【VBA】Excelでガントチャートを自動生成・更新する方法(コピペOK)

VBA
スポンサーリンク

スポンサーリンク

この記事でできること

VBAでタスク一覧(開始日・終了日)からセルの色塗りでガントチャートを自動生成できるようになる。

  • 対象:Excelでプロジェクト管理をしていて、ガントチャートを手で色塗りしている人
  • 所要時間:コピペ → 実行まで5分

どんな場面で使う?

  • プロジェクトのタスク一覧から視覚的なガントチャートを自動で作りたいとき
  • タスクの日程変更のたびに手作業でセルを塗り直すのが面倒なとき
  • 進捗率に応じてガントバーの色を自動で変えて、遅延タスクを一目で把握したいとき
  • 週次・月次のプロジェクト報告資料にガントチャートを含めたいとき

完成イメージ(Before / After)

Before(手作業)

操作 回数
タスクごとにセル範囲を選択して背景色を設定 タスク数 × 1回
日程変更のたびにセルの色を消して塗り直し 変更のたびに毎回
土日・祝日の列を目視で確認してグレーに塗る 列数 × 1回

20タスク × 30日 = 600セル。日程変更があるたびに手で塗り直し。

After(VBA実行後)

  1. タスク一覧に開始日・終了日を入力する
  2. マクロを実行する
  3. 日付列にガントバーが自動で色塗りされる
  4. 土日祝はグレー、進捗率に応じて色が変わる
  5. 日程変更後も再実行するだけで更新完了

タスク一覧(入力するデータ):

A B C D E
1 タスク名 担当者 開始日 終了日 進捗率
2 要件定義 田中 2026/04/01 2026/04/10 100%
3 設計 鈴木 2026/04/07 2026/04/18 60%
4 開発 佐藤 2026/04/14 2026/05/02 20%
5 テスト 田中 2026/04/28 2026/05/09 0%

生成されるガントチャート(F列以降に日付ヘッダー+色塗り):


       F       G       H       I   ...
 1   4/1     4/2     4/3     4/4  ...
 2   ████    ████    ████    ████ ...  ← 要件定義(青)
 3                           ████ ...  ← 設計(青+薄青で進捗表示)
 4                                ...  ← 開発
 5                                ...  ← テスト

プロジェクト管理をExcelでやっていた時期がある。タスクが20個、期間が2ヶ月。ガントチャートを手で塗っていたが、日程変更のたびにセルの色を消して塗り直すのが地味にストレスだった。しかも色を塗り忘れてスケジュールの重複に気づかず、上司に「このタスク並行できるの?」と聞かれてヒヤッとしたこともある。

VBAで自動化してからは、日程を変えてマクロを再実行するだけ。土日祝も自動でグレーに塗られるので、カレンダーと見比べる必要もなくなった。

Excelでプロジェクト管理をしている人に、この自動ガントチャートを使ってほしい。まずは日付範囲の色塗りから始めよう。

タスク一覧の開始日・終了日を読み取り → 日付列のセルを色塗り。これがガントチャート自動化の基本。

事前準備

シート構成を用意する

このマクロは1つのシートで完結する。

シートレイアウト

列範囲 内容
A列 タスク名
B列 担当者
C列 開始日
D列 終了日
E列 進捗率(0%〜100%)
F列以降 日付ヘッダー+ガントバー(自動生成)
  • 1行目はヘッダー。タスクデータは2行目から入力する
  • A列が空の行が最終行として判定される
  • C列・D列は日付型で入力する
  • E列は0〜1の数値(0.6 = 60%)またはパーセント表示

バックアップを取る

F列以降のセルを上書きする処理のため、実行前にファイルのコピーを取っておくこと。テスト用のダミーデータで動作確認してから本番データで実行することを強く推奨する。

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

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

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

手順(コピペ → 実行まで約5分)

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

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. コード内の書き換えポイント(★マーク)を自分の環境に合わせて変更する
  3. Alt + F8 → マクロ名を選んで「実行」

コード(最小版)– 日付範囲のセルを色塗り

まずシンプルに、開始日〜終了日のセルに色を塗るだけの最小構成。進捗率も土日祝もない。

セルの色塗りの基本はセルの背景色・文字色をRGBで自由に操作する方法を参照。日付の扱いは日付・曜日の判定で月末処理を自動化する方法が参考になる。


Sub ガントチャートを作成する()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim col As Long
    Dim startDate As Date
    Dim endDate As Date
    Dim chartStartDate As Date
    Dim chartDays As Long
    Dim taskStart As Date
    Dim taskEnd As Date

    Set ws = ActiveSheet

    ' ★ 最終行を取得(A列で判定)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

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

    ' ★ ガントチャートの表示期間(開始日と日数)
    chartStartDate = DateSerial(2026, 4, 1)  ' チャート開始日
    chartDays = 45                            ' 表示日数

    ' --- 日付ヘッダーを作成(F列〜) ---
    Dim headerCol As Long
    headerCol = 6  ' F列 = 6

    For col = 0 To chartDays - 1
        ws.Cells(1, headerCol + col).Value = chartStartDate + col
        ws.Cells(1, headerCol + col).NumberFormat = "m/d"
        ws.Cells(1, headerCol + col).ColumnWidth = 3.5
    Next col

    ' --- 既存の色をクリア ---
    If chartDays > 0 Then
        ws.Range(ws.Cells(2, headerCol), _
                 ws.Cells(lastRow, headerCol + chartDays - 1)).Interior.ColorIndex = xlNone
    End If

    ' --- タスクごとにガントバーを色塗り ---
    For i = 2 To lastRow
        ' 開始日・終了日を取得
        If Not IsDate(ws.Cells(i, 3).Value) Or Not IsDate(ws.Cells(i, 4).Value) Then
            GoTo NextTask
        End If

        taskStart = CDate(ws.Cells(i, 3).Value)
        taskEnd = CDate(ws.Cells(i, 4).Value)

        ' 日付列を走査して色塗り
        For col = 0 To chartDays - 1
            Dim currentDate As Date
            currentDate = chartStartDate + col

            If currentDate >= taskStart And currentDate <= taskEnd Then
                ' ★ ガントバーの色(青)
                ws.Cells(i, headerCol + col).Interior.Color = RGB(91, 155, 213)
            End If
        Next col

NextTask:
    Next i

    MsgBox "ガントチャートを作成しました。"
End Sub

書き換えポイント

# 書き換え箇所 初期値 説明
1 DateSerial(2026, 4, 1) 2026/04/01 チャートの表示開始日
2 chartDays = 45 45 チャートの表示日数
3 headerCol = 6 6(F列) 日付ヘッダーの開始列
4 RGB(91, 155, 213) ガントバーの色

動作確認

  1. A2〜D2にテスト用のタスクデータを1件入力する(例:要件定義, 田中, 2026/04/01, 2026/04/10)
  2. マクロを実行する
  3. F列以降に日付ヘッダーが作成され、対応する日付のセルが青く塗られることを確認する

最小版で色塗りが確認できたら、次の実務版に進む。

コード(実務版)– 進捗率表示+土日祝色分け+自動更新

自分はこの実務版をプロジェクト管理に使っている。土日祝がグレーで表示されるので、稼働日が一目で分かる。進捗率に応じて色が変わるので、朝会で画面を見せるだけで状況が伝わる。

営業日の計算は祝日・土日を除いた営業日を自動計算する方法を参照。


Sub ガントチャートを自動生成()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim col As Long
    Dim chartStartDate As Date
    Dim chartDays As Long
    Dim headerCol As Long
    Dim taskStart As Date
    Dim taskEnd As Date
    Dim progress As Double
    Dim currentDate As Date
    Dim taskDays As Long
    Dim elapsed As Long

    Set ws = ActiveSheet

    ' ★ 最終行を取得(A列で判定)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

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

    ' ★ ガントチャートの表示期間
    ' タスクの最小開始日〜最大終了日を自動計算(ここが追加)
    Dim minDate As Date
    Dim maxDate As Date
    minDate = #12/31/9999#
    maxDate = #1/1/100#

    For i = 2 To lastRow
        If IsDate(ws.Cells(i, 3).Value) And IsDate(ws.Cells(i, 4).Value) Then
            If CDate(ws.Cells(i, 3).Value) < minDate Then minDate = CDate(ws.Cells(i, 3).Value)
            If CDate(ws.Cells(i, 4).Value) > maxDate Then maxDate = CDate(ws.Cells(i, 4).Value)
        End If
    Next i

    ' 前後に余裕を持たせる
    chartStartDate = minDate - 2
    chartDays = CLng(maxDate - minDate) + 7

    ' 上限チェック(列数が多すぎるとExcelが重くなる)
    If chartDays > 180 Then
        MsgBox "表示期間が180日を超えています。" & vbCrLf & _
               "期間を短くするか、タスクの日付を確認してください。", vbExclamation
        Exit Sub
    End If

    ' 確認ダイアログ
    If MsgBox("ガントチャートを作成します。" & vbCrLf & _
              "期間: " & Format(chartStartDate, "yyyy/mm/dd") & " 〜 " & _
              Format(chartStartDate + chartDays - 1, "yyyy/mm/dd") & vbCrLf & _
              "タスク数: " & (lastRow - 1) & vbCrLf & vbCrLf & _
              "F列以降のデータは上書きされます。実行しますか?", _
              vbYesNo + vbQuestion) = vbNo Then
        Exit Sub
    End If

    Application.ScreenUpdating = False

    headerCol = 6  ' F列

    ' ★ 祝日リスト(ここが追加:日本の祝日を配列で定義)
    Dim holidays() As Date
    holidays = GetHolidays(Year(chartStartDate), Year(chartStartDate + chartDays))

    ' --- 日付ヘッダーを作成 ---
    For col = 0 To chartDays - 1
        currentDate = chartStartDate + col

        With ws.Cells(1, headerCol + col)
            .Value = currentDate
            .NumberFormat = "m/d"
            .ColumnWidth = 3.5
            .HorizontalAlignment = xlCenter
            .Font.Size = 8

            ' ★ 土日祝のヘッダーをグレーに(ここが追加)
            If Weekday(currentDate, vbMonday) >= 6 Then
                ' 土日
                .Interior.Color = RGB(217, 217, 217)
                .Font.Color = RGB(128, 128, 128)
            ElseIf IsHoliday(currentDate, holidays) Then
                ' 祝日
                .Interior.Color = RGB(255, 230, 230)
                .Font.Color = RGB(192, 0, 0)
            Else
                .Interior.ColorIndex = xlNone
                .Font.Color = RGB(0, 0, 0)
            End If
        End With
    Next col

    ' --- 既存の色をクリア(ヘッダー以外) ---
    If chartDays > 0 And lastRow >= 2 Then
        ws.Range(ws.Cells(2, headerCol), _
                 ws.Cells(lastRow, headerCol + chartDays - 1)).Interior.ColorIndex = xlNone
        ws.Range(ws.Cells(2, headerCol), _
                 ws.Cells(lastRow, headerCol + chartDays - 1)).Value = ""
    End If

    ' --- 土日祝の列を全行グレーに(ここが追加) ---
    For col = 0 To chartDays - 1
        currentDate = chartStartDate + col
        If Weekday(currentDate, vbMonday) >= 6 Then
            ws.Range(ws.Cells(2, headerCol + col), _
                     ws.Cells(lastRow, headerCol + col)).Interior.Color = RGB(242, 242, 242)
        ElseIf IsHoliday(currentDate, holidays) Then
            ws.Range(ws.Cells(2, headerCol + col), _
                     ws.Cells(lastRow, headerCol + col)).Interior.Color = RGB(255, 245, 245)
        End If
    Next col

    ' --- タスクごとにガントバーを色塗り ---
    For i = 2 To lastRow
        If Not IsDate(ws.Cells(i, 3).Value) Or Not IsDate(ws.Cells(i, 4).Value) Then
            GoTo NextTask
        End If

        taskStart = CDate(ws.Cells(i, 3).Value)
        taskEnd = CDate(ws.Cells(i, 4).Value)

        ' ★ 進捗率を取得(ここが追加)
        progress = 0
        If IsNumeric(ws.Cells(i, 5).Value) Then
            progress = ws.Cells(i, 5).Value
            If progress > 1 Then progress = progress / 100  ' 60→0.6に変換
        End If

        ' タスクの総日数
        taskDays = CLng(taskEnd - taskStart) + 1

        ' 日付列を走査して色塗り
        For col = 0 To chartDays - 1
            currentDate = chartStartDate + col

            If currentDate >= taskStart And currentDate <= taskEnd Then
                ' 開始日からの経過日数
                elapsed = CLng(currentDate - taskStart) + 1

                ' ★ 進捗率に応じた色分け(ここが追加)
                If progress >= 1 Then
                    ' 完了(緑)
                    ws.Cells(i, headerCol + col).Interior.Color = RGB(112, 173, 71)
                ElseIf elapsed <= taskDays * progress Then
                    ' 進捗済み部分(青)
                    ws.Cells(i, headerCol + col).Interior.Color = RGB(68, 114, 196)
                Else
                    ' 未着手部分(薄青)
                    ws.Cells(i, headerCol + col).Interior.Color = RGB(180, 210, 240)
                End If
            End If
        Next col

NextTask:
    Next i

    ' --- 今日の列に赤線マーカー(ここが追加) ---
    Dim todayCol As Long
    todayCol = CLng(Date - chartStartDate)
    If todayCol >= 0 And todayCol < chartDays Then
        With ws.Range(ws.Cells(1, headerCol + todayCol), _
                      ws.Cells(lastRow, headerCol + todayCol))
            .Borders(xlEdgeLeft).Color = RGB(255, 0, 0)
            .Borders(xlEdgeLeft).Weight = xlMedium
        End With
    End If

    Application.ScreenUpdating = True

    MsgBox "ガントチャートを作成しました。" & vbCrLf & _
           "期間: " & Format(chartStartDate, "yyyy/mm/dd") & " 〜 " & _
           Format(chartStartDate + chartDays - 1, "yyyy/mm/dd"), vbInformation
End Sub

' --- 祝日リストを返す関数 ---
Private Function GetHolidays(startYear As Long, endYear As Long) As Date()
    ' ★ 祝日を手動で定義(年度ごとに更新が必要)
    ' 必要に応じて追加・変更してください
    Dim h(1 To 20) As Date
    Dim cnt As Long
    cnt = 0

    Dim y As Long
    For y = startYear To endYear
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 1, 1)    ' 元日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 2, 11)   ' 建国記念の日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 2, 23)   ' 天皇誕生日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 3, 20)   ' 春分の日(概算)
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 4, 29)   ' 昭和の日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 5, 3)    ' 憲法記念日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 5, 4)    ' みどりの日
        cnt = cnt + 1: If cnt <= 20 Then h(cnt) = DateSerial(y, 5, 5)    ' こどもの日
    Next y

    ' 配列サイズを調整
    If cnt > 20 Then cnt = 20
    Dim result() As Date
    ReDim result(1 To cnt)
    Dim j As Long
    For j = 1 To cnt
        result(j) = h(j)
    Next j

    GetHolidays = result
End Function

' --- 祝日判定関数 ---
Private Function IsHoliday(d As Date, holidays() As Date) As Boolean
    Dim j As Long
    IsHoliday = False
    On Error Resume Next  ' 空配列対策
    For j = LBound(holidays) To UBound(holidays)
        If d = holidays(j) Then
            IsHoliday = True
            Exit Function
        End If
    Next j
    On Error GoTo 0
End Function

書き換えポイント

# 書き換え箇所 初期値 説明
1 headerCol = 6 6(F列) 日付ヘッダーの開始列。G列にしたい場合は7
2 RGB(68, 114, 196) 濃い青 進捗済み部分の色
3 RGB(180, 210, 240) 薄い青 未着手部分の色
4 RGB(112, 173, 71) 完了タスクの色
5 GetHolidays 関数 2026年の祝日 年度ごとに祝日を更新する
6 chartDays > 180 180 表示期間の上限日数

実務版で追加した機能

機能 説明 参考記事
表示期間の自動計算 タスクの最小開始日〜最大終了日から期間を自動決定
進捗率の色分け 完了(緑)・進捗済み(濃青)・未着手(薄青)の3段階 RGB色操作
土日のグレー表示 土曜・日曜の列をグレーに塗り分け
祝日の色分け 祝日列を薄赤で表示。祝日リストは手動定義 営業日計算
今日マーカー 今日の列に赤い縦線を表示
上限チェック 180日超の場合は警告表示。Excelの負荷を防止
確認ダイアログ 期間とタスク数を表示してYes/Noで確認

よくある落とし穴5選

# 症状 原因 対策
1 日付ヘッダーが「46200」のような数値で表示される セルの表示形式が「標準」のままで日付のシリアル値が表示されている コードで .NumberFormat = "m/d" を設定済み。手動で直す場合はセルの書式設定 → 表示形式 → ユーザー定義 → m/d
2 開始日・終了日がテキストで色が塗られない 日付がテキスト形式で IsDate()False を返す セルを選択 →「データ」→「区切り位置」→「完了」で日付型に変換。入力時に日付として認識される形式(例:2026/4/1)で入力する
3 進捗率が反映されない(全部薄青になる) E列に「60%」とテキストで入力しているため IsNumericFalse になる E列のセル書式を「パーセンテージ」に設定し、数値として0.6を入力する。または60(整数)を入力すれば progress / 100 で自動変換される
4 マクロ実行がとても遅い タスク数 × 日数のセル処理でループ回数が膨大になっている Application.ScreenUpdating = False を設定済み。それでも遅い場合は表示日数を減らすか、配列を使った高速化を検討する
5 祝日が色分けされない GetHolidays 関数に対象年の祝日が定義されていない 関数内の祝日リストに対象年の祝日を追加する。ハッピーマンデー制度で日付が変わる祝日(成人の日、海の日など)は毎年確認が必要

開始日に「4/1」と入力して色が塗られず、原因を探すのに20分かかったことがある。セルの中身を見たら日付ではなく文字列だった。Excelは日付とテキストを見た目で区別できないので、IsDate() チェックを入れておくのが安全。実務版コードではチェック済み。

VBAでガントチャートの色が塗られないときの対処法

「マクロを実行したのにセルが白のまま」という場合、原因は開始日・終了日がテキスト形式で格納されていて日付として認識されないことだ。セルを選択して「データ」→「区切り位置」→「完了」で日付型に変換するか、入力時に2026/4/1のような日付形式で入力しよう。

VBAのガントチャートで土日祝の色分けができないときの対処法

「土日はグレーになるのに祝日が色分けされない」場合、GetHolidays関数に対象年の祝日データが登録されていないことが原因だ。関数内の祝日配列に対象年のデータを追加し、ハッピーマンデー制度で日付が変動する祝日(成人の日・海の日など)は毎年確認して更新しよう。

FAQ

Q1. ガントバーの色をタスクごとに変えたい

担当者やカテゴリに応じて色を変える場合は、色のテーブルを用意して担当者名で分岐する。


Select Case ws.Cells(i, 2).Value  ' B列:担当者
    Case "田中": barColor = RGB(68, 114, 196)   ' 青
    Case "鈴木": barColor = RGB(237, 125, 49)    ' オレンジ
    Case "佐藤": barColor = RGB(112, 173, 71)    ' 緑
    Case Else:   barColor = RGB(165, 165, 165)   ' グレー
End Select

分岐の書き方はSelect Caseで複数条件の分岐をスッキリ書く方法を参照。

Q2. 日程が変わったら自動で更新したい(手動実行なし)

Worksheet_Change イベントを使えば、C列・D列・E列が変更されたタイミングで自動更新できる。ただしタスク数が多いと更新が遅くなるので注意。


' シートモジュールに貼り付け
Private Sub Worksheet_Change(ByVal Target As Range)
    ' C〜E列が変更されたら再描画
    If Not Intersect(Target, Me.Range("C:E")) Is Nothing Then
        Application.EnableEvents = False
        Call ガントチャートを自動生成
        Application.EnableEvents = True
    End If
End Sub

イベント処理の基本はセルの値が変わったら自動実行する方法を参照。

Q3. チャートの表示開始日を手動で指定したい

実務版コードの chartStartDate = minDate - 2 の行を、固定日付に変更する。


chartStartDate = DateSerial(2026, 4, 1)  ' 4月1日固定
chartDays = 90                            ' 90日間

Q4. 印刷やPDF出力に対応したい

印刷範囲を設定してから ExportAsFixedFormat でPDF出力する。


ws.PageSetup.PrintArea = ws.Range(ws.Cells(1, 1), _
    ws.Cells(lastRow, headerCol + chartDays - 1)).Address
ws.ExportAsFixedFormat Type:=xlTypePDF, _
    Filename:=ThisWorkbook.Path & "\ガントチャート.pdf"

PDF出力の詳細はExcelファイルをPDFに一括変換する方法を参照。

Q5. 祝日リストをシートから読み取りたい

別シートに祝日一覧を作成し、そこから配列に読み込む方法が管理しやすい。祝日・土日を除いた営業日を自動計算する方法で祝日リストの管理パターンを紹介している。

まとめ

この記事では、VBAでタスク一覧(開始日・終了日)からセルの色塗りでガントチャートを自動生成する方法を解説した。

  • 最小版: 日付範囲のセルを1色で色塗りするシンプルな構成
  • 実務版: 進捗率の3段階色分け+土日祝グレー表示+今日マーカー+自動期間計算

日程が変わったらマクロを再実行するだけで更新できる。テスト用のダミータスクで動作確認してから本番で使うこと。

関連記事

次にやりたくなること

ガントチャートの自動生成ができたら、次はこのあたりが気になるはず。

コメント

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