誰も教えてくれない、10分のガントチャート

10分単位のガントチャート 動画と記事解説 04回
誰も教えてくれない、10分のガントチャート

動画でExcel 誰も教えてくれない、10分のガントチャート

誰も教えてくれない、10分のガントチャート

今回は10分単位のGanttチャートを作成したいと思います。
今まで ガントチャートをいろいろ作ってきて、今回の10分単位が一番難しいでしょう。
どこが難しいかというと、時間の捉え方が難しいようです。

  • 【タイムライン】
  • ●目次
  • 00:00 - イントロ
  • 00:30 - 動画の内容
  • 00:58 - 10分単位の時間の書きかた
  • 04:24 - 変数の説明
  • 05:58 - ネストしたFor文の説明
  • 07:15 - 2回目のFor文
  • 09:22 - なぜ時間をROUNDするのか
  • 11:32 - 開始列の求め方
  • 14:30 - 終了列の求め方
  • 15:33 - ガントチャートを描画するコード
  • 17:57 - マクロの実行
  • 19:10 - コードタイム
  • 21:59 - End

マクロ動画 誰も教えてくれない、10分のガントチャート

https://youtu.be/2MzWCmkb8MY

10分単位のガントチャート、1時間を6分割する

小さなセルに9:10とか9:20などと書き込むのは難しいですし、 見づらいので上の行に時間を入れ、下の行に分を表す数値を入れることにします。

10分単位のGantt chartをVBAマクロだけで作成する1

ところが、セルには0~、10~、20~、などと記載しています。これはその方が理解しやすいと考えたからです。1つのセルが10分間を表すという意味です。

10分単位のGantt chartをVBAマクロだけで作成する2

始めに、上の行に時間を入れ、下の行に分を表す数値を入れています。時間も9時なら9を6個入れ、最初の9だけ見せて、他は文字色を白にしています。

10分単位のGantt chartをVBAマクロだけで作成する4

そしてそのまま表示するのではなく、ユーザー定義で数値の後ろに~と表示する設定にしてあります。

10分単位のGantt chartをVBAマクロだけで作成する5

10分単位のガントチャート、マクロコード解説

今回は以下の変数を使います。
これらの変数は最終的にガントチャートのレクタングルを描画するための開始セルと終了セルを特定するために必要な変数となります。

10分単位のGantt chartをVBAマクロだけで作成する6

開始セルと終了セルを特定する時間の書きかたですが、起点となるセルから何個オフセットするかを考えます。

10分単位のGantt chartをVBAマクロだけで作成する3

With ws ~ End With に挟まれた部分が実際に操作するためのマクロコード部分です。

10分単位のGantt chartをVBAマクロだけで作成する7

外側のFor文では、
i = 4 から CurrentRegion.Rows.Countで行数をカウントして、 それぞれの レクタングルに必要な、スタートタイムとエンドタイムとそしてセルの背景色と セルに書き込む テキストの値を取得しています。

10分単位のGantt chartをVBAマクロだけで作成する8

そして、その次に来るFor文では、開始時間から終了時間までの間、対応する列を見つけるためのコードが書かれています。 j As Date のjはFor文の中で回していくために使う変数です。

10分単位のGantt chartをVBAマクロだけで作成する9
' 開始時間から終了時間までの間、対応する列を見つける
For j = TimeValue("9:00:00") To TimeValue("18:00:00") Step TimeSerial(0, 10, 0)
    If Round(j, 10) = Round(startT, 10) Then
        startCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column
    End If
    If j >= startT And Round(j, 10) = Round(endT, 10) Then
        endCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column - 1
    Exit For
    End If
Next j

For j = TimeValue("9:00:00") To TimeValue("18:00:00") Step TimeSerial(0, 10, 0)
というコードは、シートの分で表示されている部分と対応します。

10分単位のGantt chartをVBAマクロだけで作成する10

なぜ時間をROUNDするのか

次のコード、
If Round(j, 10) = Round(startT, 10) Then
startCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column

ですが、(j, 10) と(startT, 10)が同じだったらと言う事ですが、ROUND関数で丸めています。

10分単位のGantt chartをVBAマクロだけで作成する11

人間の目で見たら同じと判断できますが、時間はシリアル値な為、どうやってその時間を作成したかによって、 実際には小数点以下の精度において誤差が生じる事が多々あります。
どんなに微小な誤差でも誤差があれば、同じだとみなされません。それを防ぐためにROUNDしています。

10分単位のGantt chartをVBAマクロだけで作成する12

startCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column
これは開始時間が同じであれば、開始列はどこになるかというコードです。
9時00分ならば、.Cells(2, 6)でOffsetする必要はないのですが、それを式にすると上記のようになります。

10分単位のGantt chartをVBAマクロだけで作成する13

9時10分ならば、分の方の値が1となるので、1つ分Offsetします。

10分単位のGantt chartをVBAマクロだけで作成する14

9時20分ならば、分の方の値が2となるので、2つ分Offsetします。

10分単位のGantt chartをVBAマクロだけで作成する15

終了時間の列を探す場合、考え方は一緒ですが、マイナス1してやります。

10分単位のGantt chartをVBAマクロだけで作成する16

12時終了だとすると、実際には11時59分59秒・・・のように限りなく12時に近いけどその直前の意味であるとします。

10分単位のGantt chartをVBAマクロだけで作成する17

開始列と終了列が見つかったらFor文を抜けます。

10分単位のGantt chartをVBAマクロだけで作成する18

そして描画するために、セルのアドレスを取得してやります。列は分っているので、行を決めてセルアドレスに格納します。
レクタングルを描画するコードは今までのコードと同じです。

10分単位のGantt chartをVBAマクロだけで作成する19

10分単位のガントチャートを描画するマクロを実行すると、以下の図のようにガントチャートを作成することができました。

10分単位のGantt chartをVBAマクロだけで作成する20

10分単位のガントチャート、コード全体

'==============================================================
'=10分単位のガントチャート、TenMinutesGunttChart
'==============================================================
Sub TenMinutesGuntt_normal()
    Dim ws As Worksheet
    Dim i As Long, colorC As Long
    Dim startT As Double, endT As Double
    Dim shtext As String
    Dim startCol As Long, endCol As Long, j As Date
    Dim startCe As String, endCe As String

    Set ws = ThisWorkbook.Worksheets("工程表")

    With ws
        For i = 4 To .Cells(3, 1).CurrentRegion.Rows.Count  ' 表の状態で調整必要
            startT = CDbl(.Cells(i, 3).Value)
            endT = CDbl(.Cells(i, 4).Value)
            colorC = .Cells(i, 5).Interior.Color
            shtext = .Cells(i, 2).Value

            startCol = 0
            endCol = 0
            ' 開始時間から終了時間までの間、対応する列を見つける
            For j = TimeValue("9:00:00") To TimeValue("18:00:00") Step TimeSerial(0, 10, 0)
                If Round(j, 10) = Round(startT, 10) Then
                    startCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column
                End If
                If j >= startT And Round(j, 10) = Round(endT, 10) Then
                    endCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column - 1
                Exit For
                End If
            Next j

            ' レクタングルの描画
            If startCol > 0 And endCol > 0 Then
                startCe = .Cells(i, startCol).Address
                endCe = .Cells(i, endCol).Offset(0, 1).Address

                With .Shapes.AddShape(msoShapeRectangle, .Range(startCe).Left, _
                    .Range(startCe).Top, .Range(endCe).Left - .Range(startCe).Left, _
                    .Range(endCe).Height)
                    .Fill.ForeColor.RGB = colorC
                    .TextFrame.Characters.Text = shtext
                    .TextFrame.Characters.Font.Size = 14
                    .TextFrame.Characters.Font.Bold = True
                    .TextFrame.Characters.Font.Name = "メイリオ"
                End With
            End If
        Next i
    End With
End Sub