- ベストアンサー
VBAでGANTのグラフを自動作成したい
- VBAを使用して、Office365でGANTのグラフを自動作成したいです。
- 現在は手動でデータ範囲を設定しているため、増えると手間がかかります。
- また、グラフには工程間の青い線を入れたいですが、現在はコピペで貼り付けている状況です。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
コードが書けたのでポストします。 ・GANTシートD列以降は4列/24時間 です。 ・マクロが書き込んでいるのは、帯状態の図と、3、23、43...行の日付です。 他の罫線やb列などは手作業で埋める前提です。 ・計画開始日時>計画終了日時、実績開始日時>実績終了日時 は、エラーとせず無視しています。 ・Nullの日時の場合も無視しています。 ・具体的にはコードを読んでください。 不明点、間違い、改修店などあれば返信してください。 Option Explicit '//共通定数、変数----------------------------- Const BeltHHi = 0.6 '行高とベルト高の比 Const SC = 30 'データブロックの行数 Const GC = 20 'ガントチャートブロックの行数 Dim BDay As Date '描写期間の開始日 Dim EDay As Date '描写期間の終了日 Dim DSht As Worksheet 'データシート Dim GSht As Worksheet 'ガントチャートシート '//メイン --------------------------------- Sub main() Set DSht = ThisWorkbook.Sheets("GANT_DATA") Set GSht = ThisWorkbook.Sheets("GANT") Call GetBDay_EDay Call DelBelt Call MakeBeltMain End Sub '//描写期間の開始日、終了日取得--------------- Sub GetBDay_EDay() Dim SCnt As Long 'シリーズカウンター Dim KCnt As Long '行程カウンター Dim c As Long '列カウンター BDay = DateSerial(3000, 1, 1) EDay = 0 SCnt = 0 Do If DSht.Cells(SCnt * SC + 1, 1).Value = "" Then Exit Do For KCnt = 1 To 6 For c = 2 To 5 With DSht.Cells(SCnt * SC + KCnt + 1, c) If .Value <> "" Then If .Value > EDay Then EDay = .Value If .Value < BDay Then BDay = .Value End If End With Next c Next KCnt SCnt = SCnt + 1 Loop End Sub '//帯図形全数削除----------------------------- Sub DelBelt() Dim SCnt As Long 'シリーズカウンター Dim KCnt As Long '行程カウンター Dim shp As Shape Dim wkName As String SCnt = 0 For SCnt = 0 To 100 For KCnt = 1 To 6 wkName = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") On Error Resume Next Set shp = GSht.Shapes(wkName & "P") shp.Delete Set shp = GSht.Shapes(wkName & "J") shp.Delete On Error GoTo 0 Next KCnt Next SCnt End Sub '//帯図形全数描写----------------------------- Sub MakeBeltMain() Dim SCnt As Long 'シリーズカウンター Dim KCnt As Long '工程カウンター Dim BPos As Double '左軸位置 Dim Nm As String '図形名 Dim Bx As Double '開始横位置 Dim By As Double '開始縦位置 Dim Hi As Double '高さ Dim Wi As Double '幅 Dim Cr As Long '色 Dim WperHi As Long '1日当たりの表示幅 Dim TateHosei As Long Dim i As Long Hi = GSht.Rows(4).RowHeight * BeltHHi BPos = GSht.Cells(2, 4).Left WperHi = GSht.Cells(4, 8).Left - GSht.Cells(4, 4).Left TateHosei = GSht.Rows(4).RowHeight * ((1 - BeltHHi) / 2) Hi = GSht.Rows(4).RowHeight * BeltHHi BDay = Int(BDay) EDay = Int(EDay) SCnt = 0 Do If DSht.Cells(SCnt * SC + 1, 1).Value = "" Then Exit Do GSht.Rows((SCnt * GC) + 3).ClearContents For i = 0 To EDay - BDay GSht.Cells((SCnt * GC) + 3, ((i + 1) * 4)).Value = BDay + i Next i For KCnt = 1 To 6 Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "P" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 2).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 2, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 3).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 2).Value) * WperHi Cr = rgbTurquoise '計画のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "J" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 4).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 3, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 5).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 4).Value) * WperHi Cr = rgbGreenYellow '実績のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr Next KCnt SCnt = SCnt + 1 Loop End Sub '// 帯描写ルーチン----------------------- Sub MakeBelt(Sh As Worksheet, Nm As String, _ Bx As Double, By As Double, Hi As Double, Wi As Double, Cr As Long) Dim shp As Shape On Error Resume Next Set shp = Sh.Shapes(Nm) shp.Delete On Error GoTo 0 If Wi > 0 Then Set shp = Sh.Shapes.AddShape(msoShapeRectangle, Bx, By, Wi, Hi) shp.Name = Nm shp.Fill.ForeColor.RGB = Cr shp.Line.Visible = True '外枠の有無 End If End Sub
その他の回答 (5)
- HohoPapa
- ベストアンサー率65% (455/693)
ごめんなさい、#5で私が示したコードの場合 実績終了日時が空欄の場合に、計画側も描写しないコードでした。 3620313さんの示したコードでいいと思います。
お礼
ありがとうございます。 教えていただいたマクロを展開して運用させていただいています。 また、いきづまったらよろしくお願いします。
補足
いろいろとありがとうございます。 とても助かりました(^^)/
- HohoPapa
- ベストアンサー率65% (455/693)
いいと思います。なお、私だったら、 無駄にコードを走らせないために '//帯図形全数描写----------------------------- Sub MakeBeltMain() Dim SCnt As Long 'シリーズカウンター Dim KCnt As Long '工程カウンター Dim BPos As Double '左軸位置 Dim Nm As String '図形名 Dim Bx As Double '開始横位置 Dim By As Double '開始縦位置 Dim Hi As Double '高さ Dim Wi As Double '幅 Dim Cr As Long '色 Dim WperHi As Long '1日当たりの表示幅 Dim TateHosei As Long Dim i As Long Hi = GSht.Rows(4).RowHeight * BeltHHi BPos = GSht.Cells(2, 4).Left WperHi = GSht.Cells(4, 8).Left - GSht.Cells(4, 4).Left TateHosei = GSht.Rows(4).RowHeight * ((1 - BeltHHi) / 2) Hi = GSht.Rows(4).RowHeight * BeltHHi BDay = Int(BDay) EDay = Int(EDay) SCnt = 0 Do If DSht.Cells(SCnt * SC + 1, 1).Value = "" Then Exit Do GSht.Rows((SCnt * GC) + 3).ClearContents For i = 0 To EDay - BDay GSht.Cells((SCnt * GC) + 3, ((i + 1) * 4)).Value = BDay + i Next i For KCnt = 1 To 6 If DSht.Cells(SCnt * SC + KCnt + 1, 4).Value <> "" Then Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "P" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 2).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 2, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 3).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 2).Value) * WperHi Cr = rgbTurquoise '計画のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "J" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 4).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 3, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 5).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 4).Value) * WperHi Cr = rgbGreenYellow '実績のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr End If Next KCnt SCnt = SCnt + 1 Loop End Sub 繰り返しますが、当方ではエラーにならないので、 後学のため、お使いのOffice(エクセルの)バージョンを教えてください。
- HohoPapa
- ベストアンサー率65% (455/693)
>終了日時が入っていないのでWiが負の値になってエラーになるのはわかるのですが 計画、実績とも、 開始日時が埋まり、終了日時が空欄の場合であっても エラーにならないように作成しています。(作成しているつもりです。) 少なくとも当方の環境ではエラーになりません。 おそらく、 終了日時のセルは空欄ではなく、何か見えない文字(制御文字かも)が埋まっています。 =Code(セル番地)といった関数で中身を調べてみてください。 埋まっているものが何者なのかがわかれば、 その場合にはスルーするようにコードを修正します。 >実績終了が空欄の日時は、現在日時で書き込むので 開始日時が埋まり、終了日時が空欄、あるいは上記の未詳な文字が埋まっていたら 実行日時に読み替えるようにコードを修正したいですか?
補足
お手数おかけして申し訳ないです。 =Code(セル番地)で確認したら、空欄セルが全て#VALUE!となります。 日時が入っている部分は52でした。 開始日時があって終了日時がない所は、=now() でOKですが、 開始日時が空欄の部分で下記部分がエラーとなりました。 '//帯図形全数描写----------------------------- Sub MakeBeltMain() Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "J" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 4).Value - BDay) * WperHi) 上記 Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 4).Value - BDay) * WperHi) の部分でエラー なのでD列のセルが空欄だったら何もしないの意味で '//帯図形全数描写----------------------------- Sub MakeBeltMain() Dim SCnt As Long 'シリーズカウンター Dim KCnt As Long '工程カウンター Dim BPos As Double '左軸位置 Dim Nm As String '図形名 Dim Bx As Double '開始横位置 Dim By As Double '開始縦位置 Dim Hi As Double '高さ Dim Wi As Double '幅 Dim Cr As Long '色 Dim WperHi As Long '1日当たりの表示幅 Dim TateHosei As Long Dim i As Long Hi = GSht.Rows(4).RowHeight * BeltHHi BPos = GSht.Cells(2, 4).Left WperHi = GSht.Cells(4, 8).Left - GSht.Cells(4, 4).Left TateHosei = GSht.Rows(4).RowHeight * ((1 - BeltHHi) / 2) Hi = GSht.Rows(4).RowHeight * BeltHHi BDay = Int(BDay) EDay = Int(EDay) SCnt = 0 Do If DSht.Cells(SCnt * SC + 1, 1).Value = "" Then Exit Do GSht.Rows((SCnt * GC) + 3).ClearContents For i = 0 To EDay - BDay GSht.Cells((SCnt * GC) + 3, ((i + 1) * 4)).Value = BDay + i Next i For KCnt = 1 To 6 Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "P" Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 2).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 2, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 3).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 2).Value) * WperHi Cr = rgbTurquoise '計画のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr Nm = "Belt" & Format(SCnt, "000") & Format(KCnt, "00") & "J" If DSht.Cells(SCnt * SC + KCnt + 1, 4).Value = "" Then Else Bx = (BPos + (DSht.Cells(SCnt * SC + KCnt + 1, 4).Value - BDay) * WperHi) By = GSht.Cells(SCnt * GC + (KCnt * 2) + 3, 1).Top + TateHosei Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 5).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 4).Value) * WperHi Cr = rgbGreenYellow '実績のベルトの色 MakeBelt GSht, Nm, Bx, By, Hi, Wi, Cr End If Next KCnt SCnt = SCnt + 1 Loop End Sub としたら、エラーなく表示できたのですが、 こんな感じで大丈夫でしょうか? 確認までです。
- HohoPapa
- ベストアンサー率65% (455/693)
私の本業に追われ、マクロのコーディングをこれから始めます。 >軸書式の説明してませんでしたが、 >軸の最小値:計画開始日時と実績開始日時の全レコードの最小値 >軸の最大値:計画終了日時と実績終了日時の全レコードの最大値 >とするつもりです。 これは、 計画開始日時>計画終了日時 あるいは、 実績開始日時>実績終了日時 が想定されるという意味ですか? また、serial1,2,3と増えていくわけですが、 軸の最小値、最大値は、serialごとに求めるんですか? それとも、 serial1,2,3..これら全体で求めるんですか?
補足
これは、 計画開始日時>計画終了日時 あるいは、 実績開始日時>実績終了日時 が想定されるという意味ですか? → 違います 通常であれば 実績開始日時>計画開始日時 または 実績終了日時>計画終了日時 なのですが、 計画開始日時>実績開始日時 または 計画終了日時>実績終了日時 の場合があるので、軸の最小値を計画、実績両方の最小値にする意味合いです。 serial1,2,3と増えていくわけですが、 軸の最小値、最大値は、serialごとに求めるんですか? それとも、 serial1,2,3..これら全体で求めるんですか? → serial1,2,3..これら全体で求めるとします の方です。 全シリアルの状況を日時で比較したいので、軸の最小、最大は、全アイテムとしています。
- HohoPapa
- ベストアンサー率65% (455/693)
次のように理解しました。 エクセルの積み上げ横棒グラフを利用してガントチャートを手作りしている。 手間がかかるので、VBAを使い、省力化したい。 エクセルの積み上げ横棒グラフを利用すると、 指摘の >GANTグラフには工程間に細く青い線をしきりで入れてます。 の作業を追加したくなりますが この線をグラフ上にVBAで線を引くのは 引く場所を特定するのが相当厳しいものになりましょう。 私だったら、 VBAを持ち込むわけですから、 添付画像のように、 グラフを使わず、シート上に図形を描写する対応にします。 これなら、補助線などを設ける作業は罫線ですから扱いやすいです。 これでよければ、 サンプルなコードを紹介できると思います。 (タイムリーには提示できませんが) なお、series1,2,3..と増えていくものと思いますが それごとにガントチャートのシートを分けるのではなく 1枚のシートに縦方向に並べるんですね? 更に、ざっくりでいいですので、 series1,2,3..と増えていく最大値を教えてください。
補足
グラフを使わず、シート上に図形を描写する対応にします。 これなら、補助線などを設ける作業は罫線ですから扱いやすいです。 これでよければ、 サンプルなコードを紹介できると思います。 → 図形描写で大丈夫です。 なお、series1,2,3..と増えていくものと思いますが それごとにガントチャートのシートを分けるのではなく 1枚のシートに縦方向に並べるんですね? → 1枚の縦方向に並べます ※ 軸書式の説明してませんでしたが、 軸の最小値:計画開始日時と実績開始日時の全レコードの最小値 軸の最大値:計画終了日時と実績終了日時の全レコードの最大値 とするつもりです。 更に、ざっくりでいいですので、 series1,2,3..と増えていく最大値を教えてください。 → ざっくり100レコードくらいあります。
お礼
ありがとうございます。 時間表示の所は、想定以上にわかりやすい構成でした。 これでばっちりです。
補足
コードありがとうございます。 1点教えていただきたい内容があります。 データベースからデータを持ってきた時、実績終了日時が空欄の場合があります。 この状態だと、 '//帯図形全数描写----------------------------- Sub MakeBeltMain() の Wi = (DSht.Cells(SCnt * SC + KCnt + 1, 5).Value - _ DSht.Cells(SCnt * SC + KCnt + 1, 4).Value) * WperHi の部分で型が一致しません のエラーになります。 終了日時が入っていないのでWiが負の値になってエラーになるのはわかるのですが、いったんこの空欄の日時を埋めて実行するとエラー発生しなくなり、再度同じセルを削除して空欄にしてマクロ実行した場合は、エラー発生しなくなります。 つまり、 イニシャル時にマクロ実行で、実績終了日時が空欄だとエラー。 一度実績終了日時を埋めた後で、マクロ実行してセルの内容を削除した場合はエラーが発生しなくなります。 実績終了が空欄の日時は、現在日時で書き込むので、ガント表示には支障ないのですが、上記エラー発生の有無を教えていただけないでしょうか。