Why Automate Report Generation?
Every business generates reports: sales summaries, analytics dashboards, client deliverables, compliance documents. Doing this manually means hours of copy-pasting data into templates, adjusting formatting, and exporting PDFs.
With the ToolCenter HTML-to-PDF API, you can turn any HTML template into a polished PDF in a single API call. Feed it data, get a report.
The Architecture
The workflow is straightforward:
- Fetch your data — Database query, API call, or spreadsheet
- Render HTML template — Inject data into an HTML template
- Convert to PDF — Send the HTML to ToolCenter
- Deliver — Email, upload to S3, or serve to users
Step 1: Design Your Report Template
Create a professional HTML report template:
<!DOCTYPE html>
<html>
<head>
<style>
@page { size: A4; margin: 40px; }
body { font-family: 'Helvetica Neue', sans-serif; color: #333; line-height: 1.6; }
.header { display: flex; justify-content: space-between; align-items: center;
border-bottom: 3px solid #667eea; padding-bottom: 20px; margin-bottom: 30px; }
.logo { font-size: 24px; font-weight: bold; color: #667eea; }
.meta { text-align: right; font-size: 14px; color: #666; }
h1 { font-size: 28px; color: #1a1a1a; margin-bottom: 10px; }
.summary-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 30px 0; }
.card { background: #f8f9fa; border-radius: 8px; padding: 20px; text-align: center; }
.card-value { font-size: 32px; font-weight: bold; color: #667eea; }
.card-label { font-size: 14px; color: #666; margin-top: 5px; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background: #667eea; color: white; padding: 12px; text-align: left; }
td { padding: 10px 12px; border-bottom: 1px solid #eee; }
tr:nth-child(even) { background: #f8f9fa; }
.footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;
font-size: 12px; color: #999; text-align: center; }
</style>
</head>
<body>
<div class="header">
<div class="logo">Acme Analytics</div>
<div class="meta">
<div>Monthly Sales Report</div>
<div>{{reportDate}}</div>
</div>
</div>
<h1>{{reportTitle}}</h1>
<div class="summary-cards">
<div class="card">
<div class="card-value">{{totalRevenue}}</div>
<div class="card-label">Total Revenue</div>
</div>
<div class="card">
<div class="card-value">{{totalOrders}}</div>
<div class="card-label">Orders</div>
</div>
<div class="card">
<div class="card-value">{{avgOrderValue}}</div>
<div class="card-label">Avg Order Value</div>
</div>
</div>
<h2>Top Products</h2>
<table>
<tr><th>Product</th><th>Units Sold</th><th>Revenue</th></tr>
{{#products}}
<tr><td>{{name}}</td><td>{{units}}</td><td>{{revenue}}</td></tr>
{{/products}}
</table>
<div class="footer">
Generated automatically on {{generatedAt}} | Confidential
</div>
</body>
</html>
Step 2: Populate the Template with Data
Use a template engine to inject your data:
const Handlebars = require('handlebars');
const fs = require('fs');
function renderReport(data) {
const templateSrc = fs.readFileSync('./templates/report.html', 'utf-8');
const template = Handlebars.compile(templateSrc);
return template({
reportTitle: `Sales Report — ${data.month} ${data.year}`,
reportDate: new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }),
totalRevenue: `$${data.totalRevenue.toLocaleString()}`,
totalOrders: data.totalOrders.toLocaleString(),
avgOrderValue: `$${(data.totalRevenue / data.totalOrders).toFixed(2)}`,
products: data.topProducts,
generatedAt: new Date().toISOString(),
});
}
Step 3: Convert to PDF with ToolCenter
const axios = require('axios');
async function generatePDF(html) {
const response = await axios.post(
'https://api.toolcenter.dev/v1/pdf',
{
html: html,
format: 'A4',
margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
printBackground: true,
preferCSSPageSize: true,
},
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
responseType: 'arraybuffer',
}
);
return Buffer.from(response.data);
}
Step 4: Put It All Together
async function createMonthlyReport(month, year) {
// 1. Fetch data from your database
const data = await fetchSalesData(month, year);
// 2. Render HTML
const html = renderReport(data);
// 3. Convert to PDF
const pdf = await generatePDF(html);
// 4. Save or send
const filename = `sales-report-${year}-${month}.pdf`;
fs.writeFileSync(`./reports/${filename}`, pdf);
// Optional: send via email
await sendEmail({
to: '[email protected]',
subject: `Sales Report — ${month}/${year}`,
attachments: [{ filename, content: pdf }],
});
return filename;
}
Python Implementation
import requests
from jinja2 import Template
from datetime import datetime
def generate_report(data):
# Load and render template
with open('templates/report.html') as f:
template = Template(f.read())
html = template.render(
report_title=f"Sales Report — {data['month']}",
report_date=datetime.now().strftime('%B %d, %Y'),
total_revenue=f"${data['total_revenue']:,.2f}",
total_orders=f"{data['total_orders']:,}",
products=data['top_products'],
)
# Convert to PDF
response = requests.post(
'https://api.toolcenter.dev/v1/pdf',
json={
'html': html,
'format': 'A4',
'margin': {'top': '20mm', 'bottom': '20mm', 'left': '15mm', 'right': '15mm'},
'printBackground': True,
},
headers={'Authorization': 'Bearer YOUR_API_KEY'},
)
return response.content
Scheduling Reports
With Cron (Node.js)
const cron = require('node-cron');
// Generate monthly report on the 1st at 9 AM
cron.schedule('0 9 1 * *', async () => {
const now = new Date();
const lastMonth = now.getMonth(); // 0-indexed, so this is last month
const year = now.getFullYear();
await createMonthlyReport(lastMonth, year);
console.log('Monthly report generated and sent!');
});
With AWS Lambda
exports.handler = async (event) => {
const { month, year } = event;
const filename = await createMonthlyReport(month, year);
return { statusCode: 200, body: `Report generated: ${filename}` };
};
Advanced Features
Adding Charts
Include chart images in your report using a charting library:
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
async function renderChart(data) {
const canvas = new ChartJSNodeCanvas({ width: 600, height: 300 });
const image = await canvas.renderToDataURL({
type: 'bar',
data: {
labels: data.map(d => d.month),
datasets: [{ label: 'Revenue', data: data.map(d => d.revenue) }],
},
});
return image; // data:image/png;base64,...
}
Embed it in your HTML template:
<img src="{{chartImage}}" style="width:100%;max-width:600px;" />
Multi-Page Reports
For long reports, use CSS page breaks:
.page-break { page-break-after: always; }
Headers and Footers
const response = await axios.post('https://api.toolcenter.dev/v1/pdf', {
html: html,
format: 'A4',
headerTemplate: '<div style="font-size:10px;text-align:center;width:100%;">Acme Corp — Confidential</div>',
footerTemplate: '<div style="font-size:10px;text-align:center;width:100%;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',
displayHeaderFooter: true,
});
Conclusion
Automated report generation eliminates hours of manual work. Design your templates once in HTML/CSS, populate them with live data, and let the ToolCenter PDF API handle the conversion. Whether it’s daily dashboards, weekly summaries, or monthly analytics, the pipeline stays the same: data in, PDF out.