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.

299 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

Advanced

Multi-Chart Dashboard

Create multiple charts on a single worksheet for comprehensive analysis

View Template
Intermediate

Dynamic Chart Creator

Create dynamic charts that update automatically with new data

View Template