Skip to main content

Exporting Data

This guide covers how to export report data from Shyfts in multiple formats including PDF, CSV, and Excel for external analysis, record-keeping, or payroll integration.


Overview

Export Capabilities

Shyfts provides flexible data export options:

  1. PDF Export - Formatted documents with branding for printing or sharing
  2. Excel Export - Spreadsheet format for analysis and manipulation
  3. CSV Export - Plain text format for system integration

Supported Reports

All 9 report types support export functionality:

ReportPDFExcelCSV
Overview
Staff Performance
Scheduling Analytics
Attendance Summary
Hours Tracking
Leave Analysis
Skills Matrix
Cost Analysis
Compliance Report

Exporting Reports

Export Button Location

The export button is located in the report dashboard header:

// Source: src/components/reporting/ReportingDashboard.tsx:620-650
<div className="flex items-center gap-2">
<button
onClick={() => handleExport('PDF')}
className="form-button secondary flex items-center gap-2"
>
<FileText className="w-4 h-4" />
PDF
</button>
<button
onClick={() => handleExport('EXCEL')}
className="form-button secondary flex items-center gap-2"
>
<Table className="w-4 h-4" />
Excel
</button>
<button
onClick={() => handleExport('CSV')}
className="form-button secondary flex items-center gap-2"
>
<Download className="w-4 h-4" />
CSV
</button>
</div>

Export Process

  1. Navigate to the Reports dashboard
  2. Select a report tab (Performance, Scheduling, etc.)
  3. Configure date range and filters
  4. Click Refresh to load data
  5. Click the desired export button (PDF, Excel, or CSV)
  6. File downloads automatically

Export Handler

// Source: src/components/reporting/ReportingDashboard.tsx:402-485
const handleExport = async (format: 'PDF' | 'EXCEL' | 'CSV') => {
setExportStatus(null)

let reportData: unknown
let reportTitle = ''

// Get current report data based on active tab
switch (activeTab) {
case 'overview':
reportData = {
performance: performanceData,
scheduling: schedulingData,
attendance: attendanceData,
skills: skillsData,
hours: hoursData,
leave: leaveData,
cost: costData,
compliance: complianceData,
meta: { dateRange, filters }
}
reportTitle = 'Overview_Report'
break
case 'performance':
reportData = performanceData
reportTitle = 'Staff_Performance_Report'
break
// ... other cases
}

const result = await ReportingService.exportReport(reportData, format, reportTitle)

if (result.success) {
setExportStatus({
success: true,
message: `Successfully exported as ${format}. File: ${result.file_name}`
})
}
}

PDF Export

Features

  • Formatted Layout - Professional document structure
  • Company Branding - Coral accent colours (#FFB5B0)
  • Tables - Auto-formatted data tables with headers
  • Multi-page Support - Automatic pagination for large datasets

PDF Generation

// Source: src/services/reportingService.ts:1529-1642
private static exportToPDF(reportData: unknown, reportTitle: string): ExportResult {
try {
const doc = new jsPDF()
const pageHeight = doc.internal.pageSize.getHeight()
const pageWidth = doc.internal.pageSize.getWidth()
const marginX = 14
const contentWidth = pageWidth - marginX * 2
let y = 35

const ensureSpace = (minY: number) => {
if (y > pageHeight - minY) {
doc.addPage()
y = 20
}
}

// Add title
doc.setFontSize(16)
doc.setTextColor(255, 181, 176) // Coral accent
doc.text(reportTitle.replace(/_/g, ' '), marginX, 25)

// Add timestamp
doc.setFontSize(8)
doc.setTextColor(128, 128, 128)
doc.text(`Generated: ${new Date().toLocaleString('en-GB')}`, marginX, y)
y += 10

// ... table rendering logic

// Save and download
const fileName = `${reportTitle}_${formatForFilename(new Date())}.pdf`
doc.save(fileName)

return {
success: true,
file_name: fileName
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'PDF export failed',
file_name: ''
}
}
}

PDF Document Structure

SectionContent
HeaderReport title with coral styling
MetadataGeneration timestamp (DD/MM/YYYY HH:mm)
Data TablesAuto-generated from report data
FooterPage numbers

PDF Use Cases

Use CaseBenefit
Printable ReportsProfessional format for meetings
Email AttachmentsShareable document format
Audit RecordsOfficial documentation
Board PresentationsBranded visual reports

Excel Export

Features

  • Multiple Sheets - Overview exports create separate sheets per section
  • Data Formatting - Numbers, dates, and text properly typed
  • Pivot-Ready - Data structured for pivot table analysis
  • Formula Compatible - Ready for Excel calculations

Excel Generation

// Source: src/services/reportingService.ts:1648-1717
private static exportToExcel(reportData: unknown, reportTitle: string): ExportResult {
try {
const workbook = XLSX.utils.book_new()

if (Array.isArray(reportData)) {
// Array-based reports - convert to worksheet
if (reportData.length === 0) {
return {
success: false,
error: 'No data to export',
file_name: ''
}
}

const worksheet = XLSX.utils.json_to_sheet(reportData)
XLSX.utils.book_append_sheet(workbook, worksheet, 'Report Data')
} else if (typeof reportData === 'object' && reportData !== null) {
// Object-based reports - create sheet per section
const entries = Object.entries(reportData as Record<string, unknown>)

for (const [key, value] of entries) {
const safeName = String(key).slice(0, 31) || 'Sheet'

if (Array.isArray(value)) {
const rows = value.length > 0 ? value : [{ note: 'No data' }]
const worksheet = XLSX.utils.json_to_sheet(rows)
XLSX.utils.book_append_sheet(workbook, worksheet, safeName)
}
}
}

// Generate and download
const fileName = `${reportTitle}_${formatForFilename(new Date())}.xlsx`
XLSX.writeFile(workbook, fileName)

return {
success: true,
file_name: fileName
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Excel export failed',
file_name: ''
}
}
}

Overview Report Sheets

When exporting the Overview report, each section gets its own sheet:

Sheet NameContent
performanceStaff performance metrics
schedulingScheduling analytics data
attendanceAttendance summary records
skillsSkills matrix data
hoursHours tracking records
leaveLeave analysis data
costCost analysis breakdown
complianceCompliance report data
metaDate range and filter info

Excel Use Cases

Use CaseBenefit
Payroll IntegrationImport into payroll systems
Data AnalysisCreate pivot tables and charts
Custom ReportsBuild on exported data
Historical TrackingArchive for comparison

CSV Export

Features

  • Universal Compatibility - Works with any spreadsheet or database
  • System Integration - Import into payroll and HR systems
  • Lightweight - Small file sizes for quick transfer
  • Plain Text - Human-readable format

CSV Generation

// Source: src/services/reportingService.ts:1468-1524
private static exportToCSV(reportData: unknown, reportTitle: string): ExportResult {
try {
let csv = ''

if (Array.isArray(reportData)) {
// For array-based reports (staff performance, attendance, etc.)
if (reportData.length === 0) {
return {
success: false,
error: 'No data to export',
file_name: ''
}
}

// Get headers from first item
const headers = Object.keys(reportData[0])
csv = headers.join(',') + '\n'

// Add data rows
reportData.forEach(item => {
const row = headers.map(header => {
const value = this.getNestedValue(item, header)
return typeof value === 'string' && value.includes(',')
? `"${value}"`
: value
})
csv += row.join(',') + '\n'
})
} else if (typeof reportData === 'object' && reportData !== null) {
// For object-based reports (cost analysis, scheduling analytics)
csv = this.objectToCSV(reportData as Record<string, unknown>)
}

// Create and download file
const fileName = `${reportTitle}_${formatForFilename(new Date())}.csv`
const blob = new Blob([csv], { type: 'text/csv' })
// ... download logic

return {
success: true,
file_name: fileName
}
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'CSV export failed',
file_name: ''
}
}
}

CSV Format Example

staff_name,role,attendance_rate,punctuality_rate,shifts_completed,total_hours
"Sarah Johnson",Nurse,98.5,95.2,22,176.5
"James Wilson",Doctor,94.0,88.5,20,160.0
"Emma Brown",Receptionist,100.0,97.8,23,184.0

CSV Use Cases

Use CaseBenefit
Payroll SystemsDirect import compatibility
Database ImportLoad into SQL databases
Data MigrationTransfer between systems
Simple AnalysisOpen in any spreadsheet app

Export File Naming

Filename Convention

All exports follow a consistent naming pattern:

{ReportType}_{Timestamp}.{extension}

Examples

ReportPDFExcelCSV
OverviewOverview_Report_20250114_143052.pdf.xlsx.csv
PerformanceStaff_Performance_Report_20250114_143052.pdf.xlsx.csv
SchedulingScheduling_Analytics_Report_20250114_143052.pdf.xlsx.csv
AttendanceAttendance_Summary_Report_20250114_143052.pdf.xlsx.csv
HoursHours_Tracking_Report_20250114_143052.pdf.xlsx.csv
LeaveLeave_Analysis_Report_20250114_143052.pdf.xlsx.csv
SkillsSkills_Matrix_Report_20250114_143052.pdf.xlsx.csv
CostCost_Analysis_Report_20250114_143052.pdf.xlsx.csv
ComplianceCompliance_Report_20250114_143052.pdf.xlsx.csv

Timestamp Format

// Filename timestamp format: YYYYMMDD_HHmmss
function formatForFilename(date: Date): string {
return date.toISOString()
.replace(/[-:]/g, '')
.replace('T', '_')
.slice(0, 15)
}

Export Status Feedback

Success Message

// Source: src/components/reporting/ReportingDashboard.tsx:468-473
if (result.success) {
setExportStatus({
success: true,
message: `Successfully exported as ${format}. File: ${result.file_name}`
})
}

Error Handling

// Source: src/components/reporting/ReportingDashboard.tsx:474-483
if (!result.success) {
setExportStatus({
success: false,
message: result.error || 'Export failed'
})
}

Status Display

// Export status banner
{exportStatus && (
<div className={`p-4 rounded-xl ${
exportStatus.success
? 'bg-green-500/20 border-green-500/30'
: 'bg-red-500/20 border-red-500/30'
}`}>
{exportStatus.success ? (
<CheckCircle className="w-5 h-5 text-green-400" />
) : (
<AlertCircle className="w-5 h-5 text-red-400" />
)}
<span>{exportStatus.message}</span>
</div>
)}

Data Formatting

Value Formatting for Export

// Source: src/services/reportingService.ts:1768-1784
private static formatValueForExport(value: unknown): string {
if (value === null || value === undefined) {
return ''
}
if (typeof value === 'boolean') {
return value ? 'Yes' : 'No'
}
if (typeof value === 'number') {
return value.toFixed(2)
}
if (typeof value === 'object') {
return JSON.stringify(value)
}
return String(value)
}

Type Conversions

Data TypeExport Format
Numbers2 decimal places
Booleans"Yes" / "No"
DatesDD/MM/YYYY format
ObjectsJSON string
ArraysSeparate rows/sheets
Null/UndefinedEmpty string

Currency Formatting

Cost and financial data is formatted in GBP:

FieldExample
Total Labour Cost£12,450.00
Overtime Cost£1,250.50
Average Cost/Hour£18.75
Budget Variance-£500.00

Export Considerations

Performance

Report SizeRecommendation
< 100 rowsAny format suitable
100-1000 rowsCSV or Excel preferred
> 1000 rowsUse pagination, export in batches

Data Freshness

Exports include data as of the export time:

  1. Check date range - Verify correct period selected
  2. Apply filters - Ensure filters match requirements
  3. Refresh data - Click Refresh before exporting
  4. Note timestamp - File includes generation time

Privacy Considerations

Exported files may contain sensitive information:

Data TypeConsideration
Staff NamesPersonal data - handle appropriately
Hours/AttendanceHR records - secure storage required
Cost DataFinancial information - restricted access
Compliance ViolationsSensitive - limited distribution

Best Practices

For Regular Reporting

FrequencyRecommended FormatUse Case
DailyCSVSystem integration
WeeklyExcelAnalysis and review
MonthlyPDFManagement reports
QuarterlyPDF + ExcelBoard presentations

For Data Analysis

  1. Use Excel - Better for pivot tables and charts
  2. Export Overview - Gets all data in one file
  3. Check Filters - Ensure correct data scope
  4. Save Originals - Archive for comparison

For Payroll Integration

  1. Use CSV - Universal compatibility
  2. Export Hours - Hours Tracking report
  3. Include Staff IDs - For matching records
  4. Verify Totals - Cross-check with system

For Compliance Audits

  1. Use PDF - Official record format
  2. Include Date Range - Clear reporting period
  3. Note Filters Applied - Document scope
  4. Archive Securely - Retain for required period

Troubleshooting

Common Issues

IssueCauseSolution
No data to exportEmpty reportLoad data before exporting
Export failedLarge datasetUse pagination, export smaller batches
File not downloadingBrowser blockingCheck download permissions
Wrong data exportedWrong tab selectedSwitch to correct report tab

Error Messages

ErrorMeaningAction
"No data to export"Report has no recordsAdjust date range or filters
"PDF export failed"Document generation errorTry CSV instead
"Excel export failed"Workbook creation errorTry CSV instead
"CSV export failed"Data conversion errorCheck data format

Browser Compatibility

BrowserPDFExcelCSV
Chrome
Firefox
Safari
Edge


Source Files:

  • src/components/reporting/ReportingDashboard.tsx - Export UI and handlers
  • src/services/reportingService.ts:1435-1784 - Export implementation
  • src/lib/utils/csv-parser.ts - CSV utilities