誰も教えてくれない、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分のガントチャート
10分単位のガントチャート、1時間を6分割する
小さなセルに9:10とか9:20などと書き込むのは難しいですし、 見づらいので上の行に時間を入れ、下の行に分を表す数値を入れることにします。
ところが、セルには0~、10~、20~、などと記載しています。これはその方が理解しやすいと考えたからです。1つのセルが10分間を表すという意味です。
始めに、上の行に時間を入れ、下の行に分を表す数値を入れています。時間も9時なら9を6個入れ、最初の9だけ見せて、他は文字色を白にしています。
そしてそのまま表示するのではなく、ユーザー定義で数値の後ろに~と表示する設定にしてあります。
10分単位のガントチャート、マクロコード解説
今回は以下の変数を使います。
これらの変数は最終的にガントチャートのレクタングルを描画するための開始セルと終了セルを特定するために必要な変数となります。
開始セルと終了セルを特定する時間の書きかたですが、起点となるセルから何個オフセットするかを考えます。
With ws ~ End With に挟まれた部分が実際に操作するためのマクロコード部分です。
外側のFor文では、
i = 4 から CurrentRegion.Rows.Countで行数をカウントして、
それぞれの レクタングルに必要な、スタートタイムとエンドタイムとそしてセルの背景色と セルに書き込む テキストの値を取得しています。
そして、その次に来るFor文では、開始時間から終了時間までの間、対応する列を見つけるためのコードが書かれています。 j As Date のjはFor文の中で回していくために使う変数です。
' 開始時間から終了時間までの間、対応する列を見つける 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)
というコードは、シートの分で表示されている部分と対応します。
なぜ時間を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関数で丸めています。
人間の目で見たら同じと判断できますが、時間はシリアル値な為、どうやってその時間を作成したかによって、
実際には小数点以下の精度において誤差が生じる事が多々あります。
どんなに微小な誤差でも誤差があれば、同じだとみなされません。それを防ぐためにROUNDしています。
startCol = .Cells(2, 6).Offset(0, (Hour(j) - 9) * 6 + Minute(j) / 10).Column
これは開始時間が同じであれば、開始列はどこになるかというコードです。
9時00分ならば、.Cells(2, 6)でOffsetする必要はないのですが、それを式にすると上記のようになります。
9時10分ならば、分の方の値が1となるので、1つ分Offsetします。
9時20分ならば、分の方の値が2となるので、2つ分Offsetします。
終了時間の列を探す場合、考え方は一緒ですが、マイナス1してやります。
12時終了だとすると、実際には11時59分59秒・・・のように限りなく12時に近いけどその直前の意味であるとします。
開始列と終了列が見つかったらFor文を抜けます。
そして描画するために、セルのアドレスを取得してやります。列は分っているので、行を決めてセルアドレスに格納します。
レクタングルを描画するコードは今までのコードと同じです。
10分単位のガントチャートを描画するマクロを実行すると、以下の図のようにガントチャートを作成することができました。
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