How to Create a Dynamic Excel Project Tracker Dashboard with Claude AI (Step-by-Step Guide)
Meta Title: Create an Excel Project Tracker Dashboard with Claude AI
Meta Description: Learn how to build a professional Excel Project Tracker Dashboard using Claude AI and VBA with interactive charts, KPIs, slicers, and one-click automation.
Focus Keyword: Excel Project Tracker Dashboard
Introduction
Building a professional Excel Project Tracker Dashboard traditionally required advanced Excel skills, formulas, PivotTables, charts, and VBA programming. Thanks to Claude AI, the entire workflow has become much faster and easier.
Instead of writing hundreds of lines of VBA code manually, you simply upload your Excel workbook, describe your dashboard requirements, and let Claude AI generate production-ready VBA code. Within minutes you can create a professional dashboard with KPI cards, charts, slicers, and automation.
If you’re new to dashboard automation, don’t miss our guide on Excel Dashboard in 60 Seconds, where we demonstrate how quickly a professional dashboard can be built.
Why Use Claude AI?
- Generate VBA automatically
- Create dashboards in minutes
- Reduce manual coding
- Build professional reports
- Create interactive KPI cards
- Generate charts automatically
- Easy customization
If you also build business reports, check out our Excel Sales Dashboard tutorial.
Requirements
- Microsoft Excel 365
- Developer Tab enabled
- Claude AI
- Project data
- Dashboard Prompt
- VBA Prompt
Step 1 – Upload Your Excel File
Upload your workbook to Claude AI. Claude understands the table structure and prepares VBA specifically for your workbook.
Step 2 – Paste Your Dashboard Prompt
Describe your dashboard including KPIs, charts, slicers, summary cards, and project status.
If you frequently automate PowerPoint presentations, read our guide on Automatic Table of Contents.
Step 3 – Add the VBA Prompt
Add a second prompt requesting clean VBA with error handling, dynamic charts, formatting, and automation.
You can also explore our PowerPoint VBA Tricks article.
Step 4 – Generate VBA Code
Press Enter. Claude AI generates complete VBA code. Copy the generated code.
Option Explicit
'=====================================================================
' MODULE-LEVEL CONSTANTS AND VARIABLES
'=====================================================================
Private Const DATA_SHEET As String = "Data"
Private Const PIVOT_SHEET As String = "Pivot"
Private Const DASH_SHEET As String = "Dashboard"
Private Const TABLE_NAME As String = "tblProjectTasks"
Private Const PCT_FORMAT As String = "0%"
Private BuildStep As String
'=====================================================================
' PUBLIC ENTRY POINT
'=====================================================================
Public Sub BuildProjectTrackerDashboard()
On Error GoTo ErrHandler
Application.ScreenUpdating = True
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.Calculation = xlCalculationAutomatic
BuildStep = "RemoveAllSlicerCaches"
ShowProgress "Clearing old slicers..."
RemoveAllSlicerCaches
BuildStep = "PrepareDataSheet"
ShowProgress "Validating and preparing Data sheet..."
PrepareDataSheet
BuildStep = "BuildPivotSheet"
ShowProgress "Building Pivot sheet..."
BuildPivotSheet
BuildStep = "BuildDashboardSheet"
ShowProgress "Building Dashboard sheet..."
BuildDashboardSheet
Application.StatusBar = False
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Dashboard Created Successfully", vbInformation, "Done"
Exit Sub
ErrHandler:
Application.StatusBar = False
Application.EnableEvents = True
Application.DisplayAlerts = True
MsgBox "Error in step: " & BuildStep & vbCrLf & _
"Error " & Err.Number & ": " & Err.Description, vbCritical, "Build Failed"
End Sub
'=====================================================================
' PROGRESS / TIMING HELPERS
'=====================================================================
Private Sub ShowProgress(ByVal msg As String)
Application.StatusBar = "Project Tracker Dashboard: " & msg
DoEvents
Wait 0.12
End Sub
Private Sub Wait(ByVal seconds As Double)
Dim t As Double
t = Timer
Do While Timer - t < seconds
DoEvents
Loop
End Sub
'=====================================================================
' GENERIC HELPERS
'=====================================================================
Private Function LastUsedRow(ws As Worksheet, ByVal col As Long) As Long
LastUsedRow = ws.Cells(ws.Rows.Count, col).End(xlUp).Row
End Function
Private Function LastUsedCol(ws As Worksheet, ByVal rowIdx As Long) As Long
LastUsedCol = ws.Cells(rowIdx, ws.Columns.Count).End(xlToLeft).Column
End Function
Private Function HeaderColumn(ws As Worksheet, ByVal headerName As String) As Long
Dim lastCol As Long, i As Long
lastCol = LastUsedCol(ws, 1)
HeaderColumn = 0
For i = 1 To lastCol
If Trim(LCase(CStr(ws.Cells(1, i).Value))) = Trim(LCase(headerName)) Then
HeaderColumn = i
Exit Function
End If
Next i
End Function
Private Sub RequireHeader(ws As Worksheet, ByVal headerName As String)
If HeaderColumn(ws, headerName) = 0 Then
Err.Raise vbObjectError + 1000, "RequireHeader", _
"Required column header '" & headerName & "' was not found on sheet '" & ws.Name & "'."
End If
End Sub
Private Sub DeleteSheetIfExists(ByVal sheetName As String)
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(sheetName)
On Error GoTo 0
If Not ws Is Nothing Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = False
End If
End Sub
Private Sub RemoveAllSlicerCaches()
Dim i As Long
On Error Resume Next
For i = ThisWorkbook.SlicerCaches.Count To 1 Step -1
ThisWorkbook.SlicerCaches(i).Delete
Next i
On Error GoTo 0
End Sub
Private Function PivotDataRowsCount(pt As PivotTable) As Long
On Error Resume Next
PivotDataRowsCount = pt.RowRange.Rows.Count - 1
On Error GoTo 0
End Function
Private Sub FormatPivotValues(pt As PivotTable, ByVal fmt As String)
On Error Resume Next
pt.DataBodyRange.NumberFormat = fmt
On Error GoTo 0
End Sub
Private Function SafeNumberFormat(ByVal rng As Range, ByVal fmt As String) As Boolean
On Error GoTo Fail
rng.NumberFormat = fmt
SafeNumberFormat = True
Exit Function
Fail:
SafeNumberFormat = False
End Function
'=====================================================================
' STEP 1: PREPARE DATA SHEET
'=====================================================================
Private Sub PrepareDataSheet()
Dim ws As Worksheet
Dim lastRow As Long, lastCol As Long
Dim tbl As ListObject
Dim lo As ListObject
Dim requiredHeaders As Variant
Dim i As Long, r As Long
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(DATA_SHEET)
On Error GoTo 0
If ws Is Nothing Then
Err.Raise vbObjectError + 1001, "PrepareDataSheet", _
"A sheet named '" & DATA_SHEET & "' was not found in this workbook."
End If
requiredHeaders = Array("Task ID", "Start Date", "Due Date", "Project", _
"Owner", "Status", "Priority", "% Complete")
For i = LBound(requiredHeaders) To UBound(requiredHeaders)
RequireHeader ws, CStr(requiredHeaders(i))
Next i
Dim taskIdCol As Long, dueCol As Long, statusCol As Long, startCol As Long, pctCol As Long
taskIdCol = HeaderColumn(ws, "Task ID")
dueCol = HeaderColumn(ws, "Due Date")
statusCol = HeaderColumn(ws, "Status")
startCol = HeaderColumn(ws, "Start Date")
pctCol = HeaderColumn(ws, "% Complete")
lastRow = LastUsedRow(ws, taskIdCol)
lastCol = LastUsedCol(ws, 1)
' add / reuse "Is Overdue" helper column
Dim isOverdueCol As Long
isOverdueCol = HeaderColumn(ws, "Is Overdue")
If isOverdueCol = 0 Then
isOverdueCol = lastCol + 1
ws.Cells(1, isOverdueCol).Value = "Is Overdue"
lastCol = isOverdueCol
End If
ws.Cells(2, isOverdueCol).Formula = _
"=IF(AND(" & ws.Cells(2, dueCol).Address(False, False) & "<TODAY()," & _
ws.Cells(2, statusCol).Address(False, False) & "<>""Completed""),""Overdue"",""On Track"")"
If lastRow > 2 Then
ws.Cells(2, isOverdueCol).Copy Destination:=ws.Range(ws.Cells(3, isOverdueCol), ws.Cells(lastRow, isOverdueCol))
End If
Application.CutCopyMode = False
' normalize % Complete: if stored as 0-100 rather than 0-1, convert to decimal
Dim isWholeScale As Boolean, v As Variant
isWholeScale = False
For r = 2 To lastRow
v = ws.Cells(r, pctCol).Value
If IsNumeric(v) Then
If v > 1 Then
isWholeScale = True
Exit For
End If
End If
Next r
If isWholeScale Then
For r = 2 To lastRow
v = ws.Cells(r, pctCol).Value
If IsNumeric(v) Then ws.Cells(r, pctCol).Value = CDbl(v) / 100
Next r
End If
' remove any existing table wrapper so it can be rebuilt cleanly
For Each lo In ws.ListObjects
lo.Unlist
Next lo
Set tbl = ws.ListObjects.Add(xlSrcRange, ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)), , xlYes)
tbl.Name = TABLE_NAME
ws.Range(ws.Cells(2, startCol), ws.Cells(lastRow, startCol)).NumberFormat = "dd-mmm-yyyy"
ws.Range(ws.Cells(2, dueCol), ws.Cells(lastRow, dueCol)).NumberFormat = "dd-mmm-yyyy"
ws.Range(ws.Cells(2, pctCol), ws.Cells(lastRow, pctCol)).NumberFormat = PCT_FORMAT
With ws.Range(ws.Cells(1, 1), ws.Cells(1, lastCol))
.Font.Bold = True
.Font.Color = RGB(255, 255, 255)
.Interior.Color = RGB(30, 58, 95)
End With
ws.Columns.AutoFit
End Sub
'=====================================================================
' STEP 2: BUILD PIVOT SHEET
'=====================================================================
Private Sub BuildPivotSheet()
Dim wsData As Worksheet, wsPivot As Worksheet
Dim pc As PivotCache
Dim tbl As ListObject
DeleteSheetIfExists DASH_SHEET
DeleteSheetIfExists PIVOT_SHEET
Set wsData = ThisWorkbook.Worksheets(DATA_SHEET)
Set tbl = wsData.ListObjects(TABLE_NAME)
ThisWorkbook.Worksheets.Add(After:=wsData).Name = PIVOT_SHEET
Set wsPivot = ThisWorkbook.Worksheets(PIVOT_SHEET)
Set pc = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=tbl.Range)
ShowProgress "Building pivot: Tasks by Status..."
BuildCountPivot pc, wsPivot, "A1", "PT_TasksByStatus", "Status"
ShowProgress "Building pivot: Tasks by Owner..."
BuildCountPivot pc, wsPivot, "D1", "PT_TasksByOwner", "Owner"
ShowProgress "Building pivot: Completion Trend..."
BuildTrendPivot pc, wsPivot, "G1", "PT_CompletionTrend"
ShowProgress "Building pivot: Priority Breakdown..."
BuildCountPivot pc, wsPivot, "J1", "PT_PriorityBreakdown", "Priority"
ShowProgress "Building pivot: Project Load..."
BuildCountPivot pc, wsPivot, "M1", "PT_ProjectLoad", "Project"
ShowProgress "Building pivot: KPI summary..."
BuildKPIPivot pc, wsPivot, "P1", "PT_KPI"
ShowProgress "Building pivot: Overdue Status..."
BuildCountPivot pc, wsPivot, "S1", "PT_OverdueStatus", "Is Overdue"
wsPivot.Columns.AutoFit
End Sub
Private Sub BuildCountPivot(pc As PivotCache, wsPivot As Worksheet, ByVal destCell As String, _
ByVal ptName As String, ByVal rowField As String)
Dim pt As PivotTable
Set pt = pc.CreatePivotTable(TableDestination:=wsPivot.Range(destCell), TableName:=ptName)
With pt
.PivotFields(rowField).Orientation = xlRowField
.RowAxisLayout xlTabularRow
With .PivotFields("Task ID")
.Orientation = xlDataField
.Function = xlCount
.Caption = "Count of Task ID"
End With
.ColumnGrand = False
.RowGrand = False
End With
On Error Resume Next
pt.PivotFields(rowField).Subtotals(1) = False
On Error GoTo 0
End Sub
Private Sub BuildTrendPivot(pc As PivotCache, wsPivot As Worksheet, ByVal destCell As String, ByVal ptName As String)
Dim pt As PivotTable
Set pt = pc.CreatePivotTable(TableDestination:=wsPivot.Range(destCell), TableName:=ptName)
With pt
.PivotFields("Start Date").Orientation = xlRowField
.RowAxisLayout xlTabularRow
With .PivotFields("% Complete")
.Orientation = xlDataField
.Function = xlAverage
.Caption = "Average of % Complete"
.NumberFormat = "0.0%"
End With
.ColumnGrand = False
.RowGrand = False
End With
On Error Resume Next
pt.PivotFields("Start Date").LabelRange.Group Start:=True, End:=True, _
Periods:=Array(False, False, False, False, True, False, False)
On Error GoTo 0
End Sub
Private Sub BuildKPIPivot(pc As PivotCache, wsPivot As Worksheet, ByVal destCell As String, ByVal ptName As String)
Dim pt As PivotTable
Set pt = pc.CreatePivotTable(TableDestination:=wsPivot.Range(destCell), TableName:=ptName)
With pt
With .PivotFields("Task ID")
.Orientation = xlDataField
.Function = xlCount
.Caption = "Count of Task ID"
End With
With .PivotFields("% Complete")
.Orientation = xlDataField
.Function = xlAverage
.Caption = "Average of % Complete"
.NumberFormat = "0.0%"
End With
End With
End Sub
'=====================================================================
' STEP 3: BUILD DASHBOARD SHEET
'=====================================================================
Private Sub BuildDashboardSheet()
Dim wsDash As Worksheet
ThisWorkbook.Worksheets.Add(Before:=ThisWorkbook.Worksheets(1)).Name = DASH_SHEET
Set wsDash = ThisWorkbook.Worksheets(DASH_SHEET)
wsDash.Activate
ActiveWindow.Zoom = 70
ActiveWindow.DisplayHeadings = True
ShowProgress "Applying dashboard canvas..."
ApplyDashboardCanvas wsDash
ShowProgress "Creating header banner..."
CreateHeader wsDash
ShowProgress "Creating KPI helper formulas..."
CreateKPIHelperFormulas wsDash
ShowProgress "Creating KPI cards..."
CreateKPICards wsDash
ShowProgress "Creating dashboard charts..."
CreateDashboardCharts wsDash
ShowProgress "Creating Project slicer..."
CreateProjectSlicer wsDash
ShowProgress "Creating Owner slicer..."
CreateOwnerSlicer wsDash
ShowProgress "Applying final formatting..."
FinalDashboardFormatting wsDash
wsDash.Activate
ActiveWindow.Zoom = 70
ActiveWindow.DisplayHeadings = True
End Sub
Private Sub ApplyDashboardCanvas(ws As Worksheet)
Dim c As Long
With ws.Cells
.Interior.Color = RGB(245, 247, 250)
.Font.Name = "Aptos"
.Font.Size = 10
End With
For c = 1 To 30
ws.Columns(c).ColumnWidth = 7.3
Next c
ws.Rows("1:3").RowHeight = 22
ws.Rows("4:29").RowHeight = 18
ActiveWindow.DisplayGridlines = False
End Sub
Private Sub CreateHeader(ws As Worksheet)
Dim banner As Shape, icon As Shape, titleBox As Shape, dateBox As Shape
Dim bannerLeft As Double, bannerTop As Double, bannerWidth As Double, bannerHeight As Double
With ws.Range("A1:AD3")
bannerLeft = .Left
bannerTop = .Top
bannerWidth = .Width
bannerHeight = .Height
End With
Set banner = ws.Shapes.AddShape(msoShapeRectangle, bannerLeft, bannerTop, bannerWidth, bannerHeight)
With banner.Fill
.Visible = msoTrue
.TwoColorGradient msoGradientHorizontal, 1
.GradientStops(1).Color.RGB = RGB(30, 58, 95)
.GradientStops(2).Color.RGB = RGB(40, 160, 150)
End With
banner.Line.Visible = msoFalse
banner.Name = "DashHeaderBanner"
Set icon = ws.Shapes.AddShape(msoShapeOval, bannerLeft + 12, bannerTop + (bannerHeight - 42) / 2, 42, 42)
icon.Fill.ForeColor.RGB = RGB(255, 255, 255)
icon.Line.Visible = msoFalse
With icon.TextFrame2.TextRange
.Text = "P"
.Font.Size = 22
.Font.Bold = msoTrue
.Font.Fill.ForeColor.RGB = RGB(30, 58, 95)
End With
icon.TextFrame2.VerticalAnchor = msoAnchorMiddle
icon.TextFrame2.HorizontalAnchor = msoAnchorCenter
icon.Name = "DashHeaderIcon"
Set titleBox = ws.Shapes.AddTextbox(msoTextOrientationHorizontal, bannerLeft + 70, bannerTop, bannerWidth - 280, bannerHeight)
With titleBox.TextFrame
.Characters.Text = "PROJECT TRACKER DASHBOARD | FY 2026"
.Characters.Font.Size = 44
.Characters.Font.Bold = True
.Characters.Font.Color = RGB(255, 255, 255)
.Characters.Font.Name = "Aptos"
.VerticalAlignment = xlVAlignCenter
.HorizontalAlignment = xlHAlignLeft
End With
titleBox.TextFrame2.WordWrap = msoFalse
titleBox.TextFrame2.AutoSize = msoAutoSizeNone
titleBox.Fill.Visible = msoFalse
titleBox.Line.Visible = msoFalse
titleBox.Name = "DashHeaderTitle"
Set dateBox = ws.Shapes.AddTextbox(msoTextOrientationHorizontal, bannerLeft + bannerWidth - 200, bannerTop, 190, bannerHeight)
With dateBox.TextFrame
.Characters.Text = "Data as of: " & Format(Date, "dd-mmm-yyyy")
.Characters.Font.Size = 18
.Characters.Font.Bold = True
.Characters.Font.Color = RGB(255, 255, 255)
.Characters.Font.Name = "Aptos"
.VerticalAlignment = xlVAlignCenter
.HorizontalAlignment = xlHAlignRight
End With
dateBox.TextFrame2.WordWrap = msoTrue
dateBox.Fill.Visible = msoFalse
dateBox.Line.Visible = msoFalse
dateBox.Name = "DashHeaderDate"
End Sub
Private Sub CreateKPIHelperFormulas(ws As Worksheet)
Dim t As String
t = TABLE_NAME
With ws
.Range("AF2").Formula = "=COUNTA(" & t & "[Task ID])"
.Range("AF3").Formula = "=IF(AF2=0,0,COUNTIFS(" & t & "[Status],""Completed"")/AF2)"
.Range("AF4").Formula = "=COUNTIFS(" & t & "[Is Overdue],""Overdue"")"
.Range("AF5").Formula = "=COUNTIFS(" & t & "[Status],""In Progress"")"
.Range("AF6").Formula = "=IFERROR(AVERAGEIFS(" & t & "[Due Date]," & t & "[Status],""Completed"")-AVERAGEIFS(" & t & "[Start Date]," & t & "[Status],""Completed""),0)"
.Range("AF7").Formula = "=SUMPRODUCT((( " & t & "[Priority]=""High"")+(" & t & "[Priority]=""Critical""))*(" & t & "[Status]<>""Completed""))"
.Range("AF2").NumberFormat = "#,##0"
.Range("AF3").NumberFormat = "0.0%"
.Range("AF4").NumberFormat = "#,##0"
.Range("AF5").NumberFormat = "#,##0"
.Range("AF6").NumberFormat = "0.0"
.Range("AF7").NumberFormat = "#,##0"
.Range("AG2").Formula = "=TEXT(AF2,""#,##0"")"
.Range("AG3").Formula = "=TEXT(AF3,""0.0%"")"
.Range("AG4").Formula = "=TEXT(AF4,""#,##0"")"
.Range("AG5").Formula = "=TEXT(AF5,""#,##0"")"
.Range("AG6").Formula = "=TEXT(AF6,""0.0"")"
.Range("AG7").Formula = "=TEXT(AF7,""#,##0"")"
End With
End Sub
Private Sub AddKPICard(ws As Worksheet, ByVal addr As String, ByVal title As String, _
ByVal valueCellAddr As String, ByVal iconGlyph As String, _
ByVal subtitle As String, ByVal accentRGB As Long)
Dim rng As Range
Dim cardShape As Shape, iconShape As Shape
Dim titleBox As Shape, valueBox As Shape, subtitleBox As Shape
Dim L As Double, T As Double, W As Double, H As Double
Set rng = ws.Range(addr)
L = rng.Left: T = rng.Top: W = rng.Width: H = rng.Height
Set cardShape = ws.Shapes.AddShape(msoShapeRoundedRectangle, L, T, W, H)
With cardShape
.Fill.ForeColor.RGB = RGB(255, 255, 255)
.Line.ForeColor.RGB = RGB(208, 220, 230)
.Line.Weight = 0.75
.Shadow.Visible = msoTrue
.Name = "KPICard_" & Replace(Replace(title, " ", ""), "%", "Pct")
End With
Set iconShape = ws.Shapes.AddShape(msoShapeOval, L + 10, T + (H - 38) / 2, 38, 38)
With iconShape.Fill
.Visible = msoTrue
.OneColorGradient msoGradientDiagonalUp, 1, 0.3
.ForeColor.RGB = accentRGB
End With
iconShape.Line.Visible = msoFalse
With iconShape.TextFrame2.TextRange
.Text = iconGlyph
.Font.Size = 13
.Font.Bold = msoTrue
.Font.Fill.ForeColor.RGB = RGB(255, 255, 255)
End With
iconShape.TextFrame2.VerticalAnchor = msoAnchorMiddle
iconShape.TextFrame2.HorizontalAnchor = msoAnchorCenter
Set titleBox = ws.Shapes.AddTextbox(msoTextOrientationHorizontal, L + 56, T + 4, W - 62, 20)
With titleBox.TextFrame
.Characters.Text = title
.Characters.Font.Size = 11
.Characters.Font.Bold = True
.Characters.Font.Color = RGB(45, 55, 65)
.Characters.Font.Name = "Aptos"
End With
titleBox.Fill.Visible = msoFalse
titleBox.Line.Visible = msoFalse
Set valueBox = ws.Shapes.AddTextbox(msoTextOrientationHorizontal, L + 56, T + 22, W - 62, H - 44)
valueBox.Fill.Visible = msoFalse
valueBox.Line.Visible = msoFalse
valueBox.TextFrame.Characters.Text = " "
valueBox.TextFrame.Characters.Font.Size = 20
valueBox.TextFrame.Characters.Font.Bold = True
valueBox.TextFrame.Characters.Font.Color = RGB(20, 40, 70)
valueBox.TextFrame.Characters.Font.Name = "Aptos"
valueBox.Select
Selection.Formula = "=" & ws.Name & "!" & valueCellAddr
Set subtitleBox = ws.Shapes.AddTextbox(msoTextOrientationHorizontal, L + 56, T + H - 18, W - 62, 16)
With subtitleBox.TextFrame
.Characters.Text = subtitle
.Characters.Font.Size = 8
.Characters.Font.Color = RGB(90, 95, 100)
.Characters.Font.Name = "Aptos"
End With
subtitleBox.Fill.Visible = msoFalse
subtitleBox.Line.Visible = msoFalse
End Sub
Private Sub CreateKPICards(ws As Worksheet)
ShowProgress "KPI card: Total Tasks..."
AddKPICard ws, "A5:E8", "Total Tasks", "AG2", "#", "All Tasks", RGB(30, 58, 95)
ShowProgress "KPI card: Completed %..."
AddKPICard ws, "F5:J8", "Completed %", "AG3", "%", "Tasks Done", RGB(40, 120, 140)
ShowProgress "KPI card: Overdue Tasks..."
AddKPICard ws, "K5:O8", "Overdue Tasks", "AG4", "!", "Past Due Date", RGB(190, 70, 50)
ShowProgress "KPI card: In Progress..."
AddKPICard ws, "P5:T8", "In Progress", "AG5", ">", "Active Now", RGB(40, 160, 150)
ShowProgress "KPI card: High-Priority Open..."
AddKPICard ws, "U5:Y8", "High-Priority Open", "AG7", "^", "Needs Attention", RGB(210, 140, 30)
ShowProgress "KPI card: Avg Completion (days)..."
AddKPICard ws, "Z5:AD8", "Avg Completion (days)", "AG6", "T", "Per Task", RGB(60, 90, 130)
End Sub
'=====================================================================
' CHARTS — now genuine PivotCharts sourced directly from PivotTables
' so they auto-refresh whenever a connected slicer filters the data
'=====================================================================
Private Function AddPivotChart(ws As Worksheet, ByVal destAddr As String, pt As PivotTable, _
ByVal chartType As XlChartType, ByVal chartTitle As String) As ChartObject
Dim rng As Range, co As ChartObject
Set rng = ws.Range(destAddr)
Set co = ws.ChartObjects.Add(rng.Left, rng.Top, rng.Width, rng.Height)
With co.Chart
.SetSourceData Source:=pt.TableRange1
.ChartType = chartType
.HasTitle = True
.ChartTitle.Text = chartTitle
End With
Set AddPivotChart = co
End Function
Private Function AddPivotChartFixedCm(ws As Worksheet, ByVal destAddr As String, pt As PivotTable, _
ByVal chartType As XlChartType, ByVal chartTitle As String, _
ByVal heightCm As Double, ByVal shrinkFactor As Double) As ChartObject
Dim rng As Range, co As ChartObject, h As Double
Set rng = ws.Range(destAddr)
h = Application.CentimetersToPoints(heightCm) * shrinkFactor
Set co = ws.ChartObjects.Add(rng.Left, rng.Top, rng.Width, h)
With co.Chart
.SetSourceData Source:=pt.TableRange1
.ChartType = chartType
.HasTitle = True
.ChartTitle.Text = chartTitle
End With
Set AddPivotChartFixedCm = co
End Function
Private Sub FormatChart(co As ChartObject, ByVal chartKind As String)
Dim cht As Chart
Set cht = co.Chart
co.Border.LineStyle = 1
co.Border.Color = RGB(208, 220, 230)
co.Border.Weight = 0.7
' hide the default pivot field buttons for a clean dashboard look
On Error Resume Next
With cht.PivotLayout
.ShowAxisFieldButtons = False
.ShowLegendFieldButtons = False
.ShowReportFilterFieldButtons = False
.ShowValueFieldButtons = False
End With
On Error GoTo 0
With cht.ChartTitle.Font
.Color = RGB(20, 40, 70)
.Bold = True
.Size = 12
.Name = "Aptos"
End With
On Error Resume Next
With cht.SeriesCollection(1)
.HasDataLabels = True
.DataLabels.Font.Size = 8
.DataLabels.Font.Bold = True
.DataLabels.Font.Color = RGB(55, 55, 55)
End With
On Error GoTo 0
If LCase(chartKind) = "trend" Then
On Error Resume Next
cht.SeriesCollection(1).DataLabels.NumberFormat = "0%"
On Error GoTo 0
End If
Select Case LCase(chartKind)
Case "owner"
cht.HasLegend = True
cht.Legend.Position = xlLegendPositionRight
Case "project"
cht.HasLegend = False
Case "status"
cht.HasLegend = True
cht.Legend.Position = xlLegendPositionBottom
On Error Resume Next
cht.Legend.Left = 229.614
cht.Legend.Width = 206.285
On Error GoTo 0
Case Else
cht.HasLegend = True
cht.Legend.Position = xlLegendPositionBottom
End Select
End Sub
Private Sub CreateDashboardCharts(ws As Worksheet)
Dim wsPivot As Worksheet
Dim co As ChartObject
Set wsPivot = ThisWorkbook.Worksheets(PIVOT_SHEET)
ShowProgress "Chart: Tasks by Status..."
Set co = AddPivotChart(ws, "A10:L18", wsPivot.PivotTables("PT_TasksByStatus"), xlDoughnut, "Tasks by Status")
FormatChart co, "status"
ShowProgress "Chart: Tasks by Owner..."
Set co = AddPivotChart(ws, "M10:V18", wsPivot.PivotTables("PT_TasksByOwner"), xlBarClustered, "Tasks by Owner")
FormatChart co, "owner"
ShowProgress "Chart: Completion Trend..."
Set co = AddPivotChart(ws, "A19:L28", wsPivot.PivotTables("PT_CompletionTrend"), xlLineMarkers, "Completion Trend")
FormatChart co, "trend"
ShowProgress "Chart: Priority Breakdown..."
Set co = AddPivotChart(ws, "M19:V28", wsPivot.PivotTables("PT_PriorityBreakdown"), xlColumnClustered, "Priority Breakdown")
FormatChart co, "priority"
ShowProgress "Chart: Project Load..."
Set co = AddPivotChartFixedCm(ws, "W19:AD28", wsPivot.PivotTables("PT_ProjectLoad"), xlColumnClustered, "Project Load", 7.18, 0.8986)
FormatChart co, "project"
End Sub
'=====================================================================
' SLICERS
'=====================================================================
Private Sub AddPivotToSlicer(sc As SlicerCache, pt As PivotTable)
Dim already As Boolean
Dim spt As PivotTable
already = False
On Error Resume Next
For Each spt In sc.PivotTables
If spt.Name = pt.Name Then already = True
Next spt
On Error GoTo 0
If Not already Then
On Error Resume Next
sc.PivotTables.AddPivotTable pt
On Error GoTo 0
End If
End Sub
Private Sub CreateProjectSlicer(ws As Worksheet)
AddSlicerForField ws, "Project", "W10:AD14", "Project"
End Sub
Private Sub CreateOwnerSlicer(ws As Worksheet)
AddSlicerForField ws, "Owner", "W15:AD18", "Owner"
End Sub
Private Sub AddSlicerForField(ws As Worksheet, ByVal fieldName As String, ByVal destAddr As String, ByVal captionText As String)
Dim wsPivot As Worksheet
Dim pt As PivotTable, pt2 As PivotTable
Dim sc As SlicerCache
Dim sl As Slicer
Dim rng As Range
Dim ptNames As Variant, i As Long
Dim hasField As Boolean
Set wsPivot = ThisWorkbook.Worksheets(PIVOT_SHEET)
ptNames = Array("PT_TasksByStatus", "PT_TasksByOwner", "PT_CompletionTrend", _
"PT_PriorityBreakdown", "PT_ProjectLoad", "PT_KPI", "PT_OverdueStatus")
Set pt = Nothing
For i = LBound(ptNames) To UBound(ptNames)
Set pt2 = Nothing
On Error Resume Next
Set pt2 = wsPivot.PivotTables(CStr(ptNames(i)))
hasField = False
If Not pt2 Is Nothing Then hasField = Not pt2.PivotFields(fieldName) Is Nothing
On Error GoTo 0
If hasField Then
Set pt = pt2
Exit For
End If
Next i
If pt Is Nothing Then
Err.Raise vbObjectError + 1002, "AddSlicerForField", _
"Could not find field '" & fieldName & "' on any pivot table to build a slicer."
End If
Set sc = ThisWorkbook.SlicerCaches.Add2(pt, fieldName)
Set rng = ws.Range(destAddr)
Set sl = sc.Slicers.Add(ws, , sc.Name, captionText, rng.Top, rng.Left, rng.Width, rng.Height)
sl.Style = "SlicerStyleLight6"
sl.Caption = captionText
sl.NumberOfColumns = 6
For i = LBound(ptNames) To UBound(ptNames)
Set pt2 = Nothing
On Error Resume Next
Set pt2 = wsPivot.PivotTables(CStr(ptNames(i)))
On Error GoTo 0
If Not pt2 Is Nothing Then AddPivotToSlicer sc, pt2
Next i
End Sub
Private Sub FinalDashboardFormatting(ws As Worksheet)
With ws.Range("A1:AD29")
.Font.Name = "Aptos"
.VerticalAlignment = xlCenter
End With
ws.Range("AF:AG").EntireColumn.Hidden = True
ActiveWindow.DisplayGridlines = False
With ws.PageSetup
.FitToPagesWide = 1
.FitToPagesTall = 1
.Zoom = False
End With
End SubStep 5 – Open VBA Editor
Go to Developer → Visual Basic.
Step 6 – Insert Module
Insert a new module and paste the VBA code.
For HR automation, see our Salary Slip Generator using Excel VBA.
Step 7 – Create a Button
Insert a rounded rectangle shape and rename it “Generate Dashboard”.
Step 8 – Assign the Macro
Right-click the button, choose Assign Macro, select your macro, and click OK.
Step 9 – Generate Your Dashboard
Click the button to automatically create:
- KPI Cards
- Project Summary
- Charts
- Slicers
- Department Reports
- Status Analysis
- Completion Trends
Real-World Applications
Inventory Management
Build warehouse dashboards using our Inventory Management Dashboard.
Expense Tracking
Create finance dashboards using our Excel Expense Tracker.
School Infrastructure
Monitor inspections using Project INSPECT School Infrastructure Dashboard.
Benefits
- Save hours every week
- Reduce coding errors
- Create professional dashboards
- Refresh reports with one click
- Easy maintenance
Frequently Asked Questions
Can beginners use this?
Yes. Claude AI generates the VBA code for you.
Is it dynamic?
Yes. Refresh your data and regenerate the dashboard anytime.
Can I customize it?
Absolutely. Change colors, charts, KPIs, and layouts whenever needed.
Related Articles
- Excel Dashboard in 60 Seconds
- Excel Sales Dashboard
- Inventory Management Dashboard
- Excel Expense Tracker
- Salary Slip Generator using Excel VBA
- Project INSPECT Dashboard
- PowerPoint VBA Tricks
- Automatic Table of Contents
Final Thoughts
Claude AI dramatically reduces the time needed to build professional Excel dashboards. Whether you manage projects, sales, HR, inventory, or finance, combining AI with Excel VBA allows you to automate repetitive work and build dashboards that update in just one click.

