Profit & Loss Statement Generator

Profit & Loss Statement Generator

Dynamically create and download a P&L statement for your business.

Revenue

Expenses

Live Preview

Profit & Loss Statement

${data.statementPeriod || 'Statement Period'}

`; // Revenue Section html += `

Revenue

`; data.revenues.forEach(item => { if (item.description || item.amount > 0) html += `
${item.description}${formatCurrency(item.amount || 0)}
`; }); html += `
Total Revenue${formatCurrency(totalRevenue)}
`; // Expenses Section html += `

Expenses

`; data.expenses.forEach(item => { if (item.description || item.amount > 0) html += `
${item.description}${formatCurrency(item.amount || 0)}
`; }); html += `
Total Expenses${formatCurrency(totalExpenses)}
`; // Net Profit html += `
Net Profit${formatCurrency(netProfit)}
`; preview.innerHTML = html; } function updateData(e) { const id = parseInt(e.target.parentElement.dataset.id); const type = e.target.dataset.type; const isAmount = e.target.classList.contains('amount-input'); const value = isAmount ? parseFloat(e.target.value) : e.target.value; const key = isAmount ? 'amount' : 'description'; const item = data[type].find(i => i.id === id); if (item) { item[key] = value; } renderPreview(); } function handleGeneralInput(e) { data[e.target.id.replace(/-/g, '')] = e.target.value; renderPreview(); } // --- Event Listeners --- document.getElementById('add-revenue-btn').addEventListener('click', () => { data.revenues.push({ id: Date.now(), description: '', amount: 0 }); renderInputs(); }); document.getElementById('add-expense-btn').addEventListener('click', () => { data.expenses.push({ id: Date.now(), description: '', amount: 0 }); renderInputs(); }); ['revenue-items', 'expense-items'].forEach(id => { document.getElementById(id).addEventListener('input', updateData); document.getElementById(id).addEventListener('click', (e) => { if (e.target.classList.contains('remove-btn')) { const id = parseInt(e.target.parentElement.dataset.id); const type = e.target.parentElement.querySelector('input').dataset.type; data[type] = data[type].filter(item => item.id !== id); renderInputs(); renderPreview(); } }); }); document.getElementById('company-name').addEventListener('input', handleGeneralInput); document.getElementById('statement-period').addEventListener('input', handleGeneralInput); document.getElementById('download-pdf-btn').addEventListener('click', () => { const { jsPDF } = window.jspdf; const pdf = new jsPDF(); const totalRevenue = data.revenues.reduce((sum, item) => sum + (item.amount || 0), 0); const totalExpenses = data.expenses.reduce((sum, item) => sum + (item.amount || 0), 0); const netProfit = totalRevenue - totalExpenses; pdf.setFontSize(18).setFont('helvetica', 'bold').text(data.companyName, 105, 20, { align: 'center' }); pdf.setFontSize(14).setFont('helvetica', 'normal').text('Profit & Loss Statement', 105, 28, { align: 'center' }); pdf.setFontSize(10).text(data.statementPeriod, 105, 35, { align: 'center' }); pdf.autoTable({ startY: 45, head: [['Revenue', 'Amount']], body: data.revenues.map(i => [i.description, formatCurrency(i.amount || 0)]), foot: [['Total Revenue', formatCurrency(totalRevenue)]], theme: 'striped', headStyles: { fillColor: '#047857' }, footStyles: { fontStyle: 'bold' } }); pdf.autoTable({ startY: pdf.autoTable.previous.finalY + 10, head: [['Expenses', 'Amount']], body: data.expenses.map(i => [i.description, formatCurrency(i.amount || 0)]), foot: [['Total Expenses', formatCurrency(totalExpenses)]], theme: 'striped', headStyles: { fillColor: '#b91c1c' }, footStyles: { fontStyle: 'bold' } }); pdf.setFontSize(12).setFont('helvetica', 'bold'); pdf.text('Net Profit:', 15, pdf.autoTable.previous.finalY + 15); pdf.text(formatCurrency(netProfit), 200, pdf.autoTable.previous.finalY + 15, { align: 'right' }); pdf.save(`${data.companyName}_PnL.pdf`); }); // --- Initial Load --- renderInputs(); renderPreview(); });
Scroll to Top