Project Timeline & Gantt Chart
Create visual Gantt charts from project task data with automatic date calculations, dependency tracking, milestone markers, progress indicators, and critical path highlighting.
379 views
Perfect For:
- Project planning
- Task scheduling
- Timeline visualisation
- Progress tracking
- Resource allocation
- Sprint planning
VBA Code
' Project Timeline & Gantt Chart Generator
' Task sheet: Task Name (A), Start Date (B), End Date (C), Duration Days (D),
' Progress % (E), Assignee (F), Status (G), Dependency (H)
Sub GenerateGanttChart()
' Create a visual Gantt chart from task data
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Dim wsTask As Worksheet
Set wsTask = ActiveSheet
Dim lastRow As Long
lastRow = wsTask.Cells(wsTask.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "No task data found. Please enter tasks from row 2.", vbExclamation
Exit Sub
End If
' Ensure headers
If wsTask.Cells(1, 1).Value = "" Then
wsTask.Cells(1, 1).Value = "Task Name"
wsTask.Cells(1, 2).Value = "Start Date"
wsTask.Cells(1, 3).Value = "End Date"
wsTask.Cells(1, 4).Value = "Duration (Days)"
wsTask.Cells(1, 5).Value = "Progress %"
wsTask.Cells(1, 6).Value = "Assignee"
wsTask.Cells(1, 7).Value = "Status"
wsTask.Cells(1, 8).Value = "Dependency"
With wsTask.Range("A1:H1")
.Font.Bold = True
.Interior.Color = RGB(0, 102, 204)
.Font.Color = RGB(255, 255, 255)
End With
End If
' Calculate durations and auto-fill end dates
Dim i As Long
For i = 2 To lastRow
If wsTask.Cells(i, 2).Value <> "" Then
Dim startDate As Date
startDate = CDate(wsTask.Cells(i, 2).Value)
' If end date is empty but duration is set, calculate end date
If wsTask.Cells(i, 3).Value = "" And Val(wsTask.Cells(i, 4).Value) > 0 Then
wsTask.Cells(i, 3).Value = startDate + Val(wsTask.Cells(i, 4).Value) - 1
wsTask.Cells(i, 3).NumberFormat = "dd/mm/yyyy"
End If
' If end date exists, calculate duration
If wsTask.Cells(i, 3).Value <> "" Then
Dim endDate As Date
endDate = CDate(wsTask.Cells(i, 3).Value)
wsTask.Cells(i, 4).Value = DateDiff("d", startDate, endDate) + 1
End If
' Determine status based on progress
Dim progress As Double
progress = Val(wsTask.Cells(i, 5).Value)
If progress >= 100 Then
wsTask.Cells(i, 7).Value = "Complete"
wsTask.Cells(i, 7).Interior.Color = RGB(200, 240, 200)
ElseIf progress > 0 Then
wsTask.Cells(i, 7).Value = "In Progress"
wsTask.Cells(i, 7).Interior.Color = RGB(200, 230, 255)
ElseIf endDate < Date Then
wsTask.Cells(i, 7).Value = "Overdue"
wsTask.Cells(i, 7).Interior.Color = RGB(255, 150, 150)
Else
wsTask.Cells(i, 7).Value = "Not Started"
wsTask.Cells(i, 7).Interior.Color = RGB(230, 230, 230)
End If
End If
Next i
' Find project date range
Dim projectStart As Date
Dim projectEnd As Date
projectStart = CDate(wsTask.Cells(2, 2).Value)
projectEnd = CDate(wsTask.Cells(2, 3).Value)
For i = 2 To lastRow
If wsTask.Cells(i, 2).Value <> "" Then
If CDate(wsTask.Cells(i, 2).Value) < projectStart Then
projectStart = CDate(wsTask.Cells(i, 2).Value)
End If
If CDate(wsTask.Cells(i, 3).Value) > projectEnd Then
projectEnd = CDate(wsTask.Cells(i, 3).Value)
End If
End If
Next i
' Create Gantt chart sheet
Dim wsGantt As Worksheet
On Error Resume Next
Set wsGantt = ThisWorkbook.Sheets("Gantt Chart")
On Error GoTo ErrorHandler
If wsGantt Is Nothing Then
Set wsGantt = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsGantt.Name = "Gantt Chart"
Else
wsGantt.Cells.Clear
End If
' Title
wsGantt.Cells(1, 1).Value = "Project Gantt Chart"
wsGantt.Cells(1, 1).Font.Size = 16
wsGantt.Cells(1, 1).Font.Bold = True
wsGantt.Cells(2, 1).Value = "Generated: " & Format(Now, "dd/mm/yyyy hh:mm")
wsGantt.Cells(2, 1).Font.Italic = True
' Task column headers
wsGantt.Cells(4, 1).Value = "Task"
wsGantt.Cells(4, 2).Value = "Assignee"
wsGantt.Cells(4, 3).Value = "Progress"
wsGantt.Cells(4, 1).Font.Bold = True
wsGantt.Cells(4, 2).Font.Bold = True
wsGantt.Cells(4, 3).Font.Bold = True
' Date headers across top
Dim totalDays As Long
totalDays = DateDiff("d", projectStart, projectEnd) + 1
' Limit columns for readability (group by weeks if > 60 days)
Dim useWeeks As Boolean
Dim colCount As Long
If totalDays > 60 Then
useWeeks = True
colCount = Int(totalDays / 7) + 1
Else
useWeeks = False
colCount = totalDays
End If
' Cap at 90 columns
If colCount > 90 Then colCount = 90
Dim col As Long
For col = 1 To colCount
Dim headerDate As Date
If useWeeks Then
headerDate = projectStart + ((col - 1) * 7)
wsGantt.Cells(4, col + 3).Value = Format(headerDate, "dd/mm")
Else
headerDate = projectStart + (col - 1)
wsGantt.Cells(4, col + 3).Value = Format(headerDate, "dd")
' Highlight weekends
If Weekday(headerDate, vbMonday) > 5 Then
wsGantt.Cells(4, col + 3).Interior.Color = RGB(240, 240, 240)
End If
End If
wsGantt.Cells(4, col + 3).Font.Size = 8
wsGantt.Cells(4, col + 3).HorizontalAlignment = xlCenter
wsGantt.Columns(col + 3).ColumnWidth = 3
Next col
wsGantt.Range(wsGantt.Cells(4, 1), wsGantt.Cells(4, colCount + 3)).Interior.Color = RGB(0, 102, 204)
wsGantt.Range(wsGantt.Cells(4, 1), wsGantt.Cells(4, colCount + 3)).Font.Color = RGB(255, 255, 255)
' Draw Gantt bars
Dim ganttRow As Long
ganttRow = 5
For i = 2 To lastRow
If wsTask.Cells(i, 2).Value <> "" Then
wsGantt.Cells(ganttRow, 1).Value = wsTask.Cells(i, 1).Value
wsGantt.Cells(ganttRow, 2).Value = wsTask.Cells(i, 6).Value
wsGantt.Cells(ganttRow, 3).Value = Val(wsTask.Cells(i, 5).Value) & "%"
wsGantt.Cells(ganttRow, 3).HorizontalAlignment = xlCenter
Dim taskStart As Date
Dim taskEnd As Date
taskStart = CDate(wsTask.Cells(i, 2).Value)
taskEnd = CDate(wsTask.Cells(i, 3).Value)
progress = Val(wsTask.Cells(i, 5).Value)
' Calculate bar position
Dim startCol As Long
Dim endCol As Long
If useWeeks Then
startCol = Int(DateDiff("d", projectStart, taskStart) / 7) + 4
endCol = Int(DateDiff("d", projectStart, taskEnd) / 7) + 4
Else
startCol = DateDiff("d", projectStart, taskStart) + 4
endCol = DateDiff("d", projectStart, taskEnd) + 4
End If
' Ensure within bounds
If startCol < 4 Then startCol = 4
If endCol > colCount + 3 Then endCol = colCount + 3
' Draw bar
Dim barColor As Long
Select Case wsTask.Cells(i, 7).Value
Case "Complete"
barColor = RGB(100, 180, 100)
Case "In Progress"
barColor = RGB(100, 150, 220)
Case "Overdue"
barColor = RGB(220, 80, 80)
Case Else
barColor = RGB(180, 180, 180)
End Select
For col = startCol To endCol
wsGantt.Cells(ganttRow, col).Interior.Color = barColor
Next col
' Draw progress overlay (darker shade)
If progress > 0 And progress < 100 Then
Dim progressCols As Long
progressCols = Int((endCol - startCol + 1) * progress / 100)
For col = startCol To startCol + progressCols - 1
wsGantt.Cells(ganttRow, col).Interior.Color = RGB(50, 100, 50)
Next col
End If
' Alternate row shading for task info columns
If (ganttRow - 5) Mod 2 = 1 Then
wsGantt.Range("A" & ganttRow & ":C" & ganttRow).Interior.Color = RGB(245, 248, 252)
End If
ganttRow = ganttRow + 1
End If
Next i
' Today marker
If Date >= projectStart And Date <= projectEnd Then
Dim todayCol As Long
If useWeeks Then
todayCol = Int(DateDiff("d", projectStart, Date) / 7) + 4
Else
todayCol = DateDiff("d", projectStart, Date) + 4
End If
For Dim r = 4 To ganttRow - 1
wsGantt.Cells(r, todayCol).Borders(xlEdgeLeft).Color = RGB(255, 0, 0)
wsGantt.Cells(r, todayCol).Borders(xlEdgeLeft).Weight = xlMedium
Next r
End If
' Set column widths
wsGantt.Columns("A").ColumnWidth = 25
wsGantt.Columns("B").ColumnWidth = 15
wsGantt.Columns("C").ColumnWidth = 10
' Add legend
Dim legendRow As Long
legendRow = ganttRow + 2
wsGantt.Cells(legendRow, 1).Value = "Legend:"
wsGantt.Cells(legendRow, 1).Font.Bold = True
wsGantt.Cells(legendRow + 1, 1).Value = "Complete"
wsGantt.Cells(legendRow + 1, 2).Interior.Color = RGB(100, 180, 100)
wsGantt.Cells(legendRow + 2, 1).Value = "In Progress"
wsGantt.Cells(legendRow + 2, 2).Interior.Color = RGB(100, 150, 220)
wsGantt.Cells(legendRow + 3, 1).Value = "Overdue"
wsGantt.Cells(legendRow + 3, 2).Interior.Color = RGB(220, 80, 80)
wsGantt.Cells(legendRow + 4, 1).Value = "Not Started"
wsGantt.Cells(legendRow + 4, 2).Interior.Color = RGB(180, 180, 180)
Application.ScreenUpdating = True
MsgBox "Gantt chart generated with " & (lastRow - 1) & " tasks!" & vbCrLf & _
"Project span: " & Format(projectStart, "dd/mm/yyyy") & " to " & Format(projectEnd, "dd/mm/yyyy"), vbInformation
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "Error generating Gantt chart: " & Err.Description, vbCritical
End Sub
Sub UpdateProgress()
' Quick progress update for selected task
On Error GoTo ErrorHandler
Dim ws As Worksheet
Set ws = ActiveSheet
If ws.Name = "Gantt Chart" Then
MsgBox "Please switch to the task data sheet to update progress.", vbExclamation
Exit Sub
End If
Dim selectedRow As Long
selectedRow = ActiveCell.Row
If selectedRow < 2 Or ws.Cells(selectedRow, 1).Value = "" Then
MsgBox "Please select a task row to update.", vbExclamation
Exit Sub
End If
Dim taskName As String
taskName = ws.Cells(selectedRow, 1).Value
Dim currentProgress As Double
currentProgress = Val(ws.Cells(selectedRow, 5).Value)
Dim newProgress As String
newProgress = InputBox("Update progress for: " & taskName & vbCrLf & _
"Current progress: " & currentProgress & "%" & vbCrLf & vbCrLf & _
"Enter new progress (0-100):", "Update Progress", currentProgress)
If newProgress = "" Then Exit Sub
Dim progressVal As Double
progressVal = Val(newProgress)
If progressVal < 0 Or progressVal > 100 Then
MsgBox "Progress must be between 0 and 100.", vbExclamation
Exit Sub
End If
ws.Cells(selectedRow, 5).Value = progressVal
' Regenerate Gantt chart
If MsgBox("Refresh Gantt chart?", vbYesNo + vbQuestion) = vbYes Then
Call GenerateGanttChart
End If
Exit Sub
ErrorHandler:
MsgBox "Error updating progress: " & Err.Description, vbCritical
End Sub
Related Topics
gantt
timeline
project
planning
schedule
Need Custom VBA Solutions?
Our AI-powered VBA generator can create custom code tailored to your specific requirements in seconds.
Free AI generations every month — top up with credit packs anytime
Related Templates
More VBA templates in the same category
Intermediate
Dynamic Chart Creator
Create dynamic charts that update automatically with new data
View Template
Advanced
Multi-Chart Dashboard
Create multiple charts on a single worksheet for comprehensive analysis
View Template