Automate Your Monthly Reports with Excel Macros
Every month, the same ritual: open the report, paste new data, format cells, update headers, copy to distribution list. It takes an hour of mindless clicking. What if one button could do it all? Welcome to Excel macros.
The Problem
Monthly reporting involves repetitive tasks:
- Copying data from source systems
- Formatting numbers, dates, and headers
- Updating titles with current month/year
- Calculating summaries and KPIs
- Saving with standardized file names
- Distributing to stakeholders
Each step is simple, but together they consume hours of valuable time.
The Solution
VBA (Visual Basic for Applications) macros record and automate these tasks. Record once, run forever. We'll build macros that:
- Format your report consistently
- Update dates and titles automatically
- Generate summaries from raw data
- Save with dynamic file names
- Even send emails with the report attached
What You'll Need
- Excel 2013 or later recommended for full VBA functionality (Excel 2010 works but has some limitations)
- Developer tab enabled
- A report you create monthly
- 30 minutes to learn, hours saved monthly
Step 1: Enable the Developer Tab
If you don't see the Developer tab:
- File > Options
- Customize Ribbon
- Check "Developer" in the right panel
- Click OK
The Developer tab appears with macro tools.
Step 2: Record Your First Macro
Recording captures your actions as VBA code.
- Developer > Record Macro
- Name it: "FormatReport" (no spaces)
- Shortcut key: Ctrl+Shift+F (optional)
- Store in: This Workbook
- Click OK
Now perform your formatting:
- Select header row, apply bold
- Set column widths
- Apply number formats
- Add borders
- Set print area
- Developer > Stop Recording
Your macro is saved! Press Ctrl+Shift+F (or run from Developer > Macros) to replay it.
Step 3: View and Edit Recorded Code
- Developer > Macros
- Select your macro
- Click Edit
The VBA editor opens with your recorded code:
1Sub FormatReport()2'3' FormatReport Macro4'5 Rows("1:1").Select6 Selection.Font.Bold = True7 Columns("A:A").ColumnWidth = 158 Columns("B:B").NumberFormat = "$#,##0.00"9 ' ... more recorded actions10End Sub
Understanding the Code:
Sub FormatReport()- Macro nameRows("1:1").Select- Selects row 1Selection.Font.Bold = True- Makes selection boldEnd Sub- End of macro
Step 4: Write Better Code
Recorded macros work but are inefficient. Here's how to improve them:
Before (Recorded):
1Sub FormatReport()2 Rows("1:1").Select3 Selection.Font.Bold = True4 Selection.Font.Size = 125 Columns("B:D").Select6 Selection.NumberFormat = "$#,##0.00"7End Sub
After (Optimized):
1Sub FormatReport()2 With Rows("1:1").Font3 .Bold = True4 .Size = 125 End With6 Columns("B:D").NumberFormat = "$#,##0.00"7End Sub
Key Improvements:
- Remove unnecessary
.SelectandSelection - Use
Withblocks for multiple properties - Work directly with ranges
Step 5: Create a Complete Report Macro
Here's a practical macro that automates common reporting tasks:
1Sub GenerateMonthlyReport()23 Dim ws As Worksheet4 Dim lastRow As Long5 Dim reportMonth As String67 ' Reference the active sheet8 Set ws = ActiveSheet910 ' Find last row with data11 lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row1213 ' Set report month (previous month)14 reportMonth = Format(DateAdd("m", -1, Date), "MMMM YYYY")1516 ' Update title17 ws.Range("A1").Value = "Sales Report - " & reportMonth1819 ' Format header row20 With ws.Range("A3:F3")21 .Font.Bold = True22 .Font.Size = 1123 .Interior.Color = RGB(0, 112, 192)24 .Font.Color = RGB(255, 255, 255)25 End With2627 ' Format data range28 With ws.Range("A4:F" & lastRow)29 .Borders.LineStyle = xlContinuous30 .Borders.Weight = xlThin31 End With3233 ' Format currency columns34 ws.Range("D4:F" & lastRow).NumberFormat = "$#,##0.00"3536 ' Format date column37 ws.Range("B4:B" & lastRow).NumberFormat = "MM/DD/YYYY"3839 ' Auto-fit columns40 ws.Columns("A:F").AutoFit4142 ' Add summary row43 ws.Cells(lastRow + 2, 1).Value = "TOTAL"44 ws.Cells(lastRow + 2, 4).Formula = "=SUM(D4:D" & lastRow & ")"45 ws.Cells(lastRow + 2, 5).Formula = "=SUM(E4:E" & lastRow & ")"46 ws.Cells(lastRow + 2, 6).Formula = "=SUM(F4:F" & lastRow & ")"4748 ' Format total row49 With ws.Range("A" & lastRow + 2 & ":F" & lastRow + 2)50 .Font.Bold = True51 .Interior.Color = RGB(221, 235, 247)52 End With5354 MsgBox "Report generated for " & reportMonth, vbInformation, "Complete"5556End Sub
Step 6: Save the Workbook with Dynamic Name
Add this to your macro or create a separate one:
1Sub SaveReport()23 Dim filePath As String4 Dim fileName As String5 Dim reportMonth As String67 ' Create file name with current date8 reportMonth = Format(DateAdd("m", -1, Date), "YYYY-MM")9 fileName = "Sales_Report_" & reportMonth & ".xlsx"1011 ' Set save location (modify path as needed)12 filePath = "C:\Reports\" & fileName1314 ' Save as new file15 ActiveWorkbook.SaveAs fileName:=filePath, _16 FileFormat:=xlOpenXMLWorkbook1718 MsgBox "Report saved as: " & fileName, vbInformation, "Saved"1920End Sub
Step 7: Create a Button to Run Macros
Insert a Button:
- Developer > Insert > Button (Form Control)
- Draw the button on your sheet
- Assign Macro dialog appears
- Select your macro
- Click OK
- Right-click button to edit text: "Generate Report"
Or use a Shape:
- Insert > Shapes > Rectangle
- Format and add text
- Right-click > Assign Macro
The Complete Solution
Here's a master macro that ties everything together:
1Sub ProcessMonthlyReport()23 Application.ScreenUpdating = False4 Application.Calculation = xlCalculationManual56 ' Step 1: Clear old data7 Call ClearPreviousData89 ' Step 2: Import new data10 Call ImportDataFromSource1112 ' Step 3: Format the report13 Call FormatReport1415 ' Step 4: Generate summaries16 Call CreateSummarySection1718 ' Step 5: Save the file19 Call SaveReport2021 Application.Calculation = xlCalculationAutomatic22 Application.ScreenUpdating = True2324 MsgBox "Monthly report processing complete!", vbInformation2526End Sub2728Sub ClearPreviousData()29 ' Clear data area (keep headers)30 Dim ws As Worksheet31 Set ws = Sheets("Data")3233 Dim lastRow As Long34 lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row3536 If lastRow > 3 Then37 ws.Range("A4:Z" & lastRow).ClearContents38 End If39End Sub4041Sub ImportDataFromSource()42 ' Example: Import from CSV43 Dim sourceFile As String44 sourceFile = "C:\Data\monthly_export.csv"4546 ' Check if file exists47 If Dir(sourceFile) = "" Then48 MsgBox "Source file not found: " & sourceFile, vbExclamation49 Exit Sub50 End If5152 ' Import the data53 With ActiveSheet.QueryTables.Add( _54 Connection:="TEXT;" & sourceFile, _55 Destination:=Range("A4"))56 .TextFileCommaDelimiter = True57 .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1)58 .Refresh BackgroundQuery:=False59 .Delete60 End With61End Sub6263Sub CreateSummarySection()64 Dim ws As Worksheet65 Dim summaryWs As Worksheet66 Dim lastRow As Long6768 Set ws = Sheets("Data")69 Set summaryWs = Sheets("Summary")7071 lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row7273 ' Create summary by category using formulas74 summaryWs.Range("B2").Formula = _75 "=SUMIF(Data!C:C,A2,Data!D:D)"76End Sub
Macro Architecture
| Macro | Purpose |
|---|---|
| ProcessMonthlyReport | Master controller |
| ClearPreviousData | Remove old data |
| ImportDataFromSource | Bring in new data |
| FormatReport | Apply formatting |
| CreateSummarySection | Build summaries |
| SaveReport | Save with dynamic name |
Common Variations
Variation 1: Email the Report
1Sub EmailReport()2 Dim OutApp As Object3 Dim OutMail As Object45 Set OutApp = CreateObject("Outlook.Application")6 Set OutMail = OutApp.CreateItem(0)78 With OutMail9 .To = "manager@company.com"10 .Subject = "Monthly Report - " & Format(Date, "MMMM YYYY")11 .Body = "Please find the monthly report attached."12 .Attachments.Add ActiveWorkbook.FullName13 .Display ' Change to .Send to send automatically14 End With1516 Set OutMail = Nothing17 Set OutApp = Nothing18End Sub
Variation 2: Loop Through Multiple Sheets
1Sub FormatAllSheets()2 Dim ws As Worksheet34 For Each ws In ActiveWorkbook.Worksheets5 If ws.Name <> "Summary" Then6 ws.Activate7 Call FormatReport8 End If9 Next ws10End Sub
Variation 3: Error Handling
1Sub SafeProcess()2 On Error GoTo ErrorHandler34 ' Your code here5 Call ProcessMonthlyReport67 Exit Sub89ErrorHandler:10 MsgBox "Error: " & Err.Description, vbCritical11 Application.ScreenUpdating = True12 Application.Calculation = xlCalculationAutomatic13End Sub
Pro Tips
- Use
Option Explicit: Add at top of module to require variable declarations - Turn off screen updating:
Application.ScreenUpdating = Falsespeeds execution - Disable calculation:
Application.Calculation = xlCalculationManualduring data changes - Comment your code: Future you will thank present you
- Save as .xlsm: Macro-enabled workbooks require this format
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Macros disabled | Security settings | Enable in Trust Center |
| "Sub or Function not defined" | Typo in macro name | Check spelling |
| Runtime error | Code bug | Debug with F8 (step through) |
| Macro not saved | Saved as .xlsx | Save as .xlsm |
| Slow execution | Screen updating on | Add ScreenUpdating = False |
Security Considerations
Macro Security Settings:
- File > Options > Trust Center > Trust Center Settings
- Macro Settings > Choose appropriate level
Options:
- Disable all macros with notification (recommended)
- Enable macros only in trusted locations
- Never enable macros from untrusted sources
Digital Signatures: For distribution, sign your macros with a certificate to verify authenticity.
Debugging Your Macros
F8 - Step Through: In VBA editor, press F8 to execute one line at a time. Watch variables change.
Breakpoints: Click in the gray margin to add a breakpoint. Code pauses there during execution.
Immediate Window:
Ctrl+G opens Immediate Window. Type ? variableName to see current value.
Watch Window: Add variables to Watch Window to monitor their values as code runs.
Conclusion
Macros transform tedious monthly routines into one-click operations. The hour you spend building a macro pays back every month thereafter. Start simple—record a formatting macro. Then learn to edit and improve it. Before long, you'll be building sophisticated automation that handles entire workflows.
The best part? Unlike manual processes, macros are consistent. They don't forget steps, don't make typos, and don't get tired on Friday afternoons. Your reports will be accurate and formatted identically every time.
Take that monthly report that eats two hours of your time. Automate it. Reclaim those hours for work that actually needs human intelligence.
Let the machine do the machine work.
Sponsored Content
Interested in advertising? Reach automation professionals through our platform.
