Industry Benchmarking & Budget Comparison Tool

Setup Information

$
Required if comparing by '% of Total Revenue'.
Required if comparing by 'Cost Per Employee'.

Budget Categories & Benchmark Data

Add your budget categories. The 'Industry Benchmark Value' should be entered based on the 'Primary Basis for Comparison' selected in Tab 1 (e.g., if you chose '% of Revenue', enter the benchmark as a percentage like '15' for 15%).

No budget categories added yet.

Comparison Report

Complete setup and budget data in previous tabs to see the report.

Total Revenue: ${currency}${totalRevenue.toFixed(2)}

`; if (basis === 'perEmployee') html += `

Total Employees: ${totalEmployees}

`; html += `
`; html += '' + '' + `` + `` + `` + `` + `` + '' + ''; if (categoriesData.length === 0) { html += ''; } else { categoriesData.forEach(cat => { let varianceAbsClass = cat.varianceAbs === 0 ? '' : (cat.varianceAbs > 0 ? 'ibbc-variance-negative' : 'ibbc-variance-positive'); // Higher cost than benchmark is often negative let variancePercClass = cat.variancePerc === 0 ? '' : (cat.variancePerc > 0 ? 'ibbc-variance-negative' : 'ibbc-variance-positive'); if (isFinite(cat.variancePerc)) { variancePercText = `${cat.variancePerc.toFixed(1)}%`; } else if (cat.yourBudgetAbs > 0 && cat.benchmarkCalculatedAbs === 0) { variancePercText = "New"; // Budget exists where benchmark was zero variancePercClass = "ibbc-variance-positive"; // Typically new items are not 'negative' variance immediately } else { variancePercText = "N/A"; variancePercClass = ""; } html += ``; }); } // Overall Total Row const totalVarianceAbs = totalYourBudget - totalBenchmarkCalculatedAbs; const totalVariancePerc = totalBenchmarkCalculatedAbs !== 0 ? (totalVarianceAbs / totalBenchmarkCalculatedAbs) * 100 : (totalYourBudget > 0 ? Infinity : 0); let totalVarianceAbsClass = totalVarianceAbs === 0 ? '' : (totalVarianceAbs > 0 ? 'ibbc-variance-negative' : 'ibbc-variance-positive'); let totalVariancePercClass = totalVariancePerc === 0 ? '' : (totalVariancePerc > 0 ? 'ibbc-variance-negative' : 'ibbc-variance-positive'); let totalVariancePercText = isFinite(totalVariancePerc) ? `${totalVariancePerc.toFixed(1)}%` : (totalYourBudget > 0 && totalBenchmarkCalculatedAbs === 0 ? "New Total" : "N/A"); html += ``; html += '
CategoryYour Budget (${currency})Your Budget (${basis === 'percentageOfRevenue' ? '%' : basis === 'perEmployee' ? currency+'/Emp' : currency})Benchmark (${basis === 'percentageOfRevenue' ? '%' : basis === 'perEmployee' ? currency+'/Emp' : 'Value'})Benchmark (${currency} Equiv.)Variance (${currency})Variance (%)
No categories or data entered.
${cat.name} ${currency}${cat.yourBudgetAbs.toFixed(2)} ${basis === 'percentageOfRevenue' ? cat.yourBudgetBasisVal.toFixed(1) + '%' : currency + cat.yourBudgetBasisVal.toFixed(2)} ${basis === 'percentageOfRevenue' ? cat.benchmarkInputValue.toFixed(1) + '%' : basis === 'perEmployee' ? currency + cat.benchmarkInputValue.toFixed(2) : currency + cat.benchmarkInputValue.toFixed(2)} ${currency}${cat.benchmarkCalculatedAbs.toFixed(2)} ${currency}${cat.varianceAbs.toFixed(2)} ${variancePercText}
TOTALS ${currency}${totalYourBudget.toFixed(2)} ${ basis === 'percentageOfRevenue' && totalRevenue > 0 ? ((totalYourBudget/totalRevenue)*100).toFixed(1)+'%' : (basis === 'perEmployee' && totalEmployees > 0 ? currency+(totalYourBudget/totalEmployees).toFixed(2) : '-')} - ${currency}${totalBenchmarkCalculatedAbs.toFixed(2)} ${currency}${totalVarianceAbs.toFixed(2)} ${totalVariancePercText}
'; html += "

Note: Variance color-coding assumes higher 'Your Budget' than 'Benchmark' is unfavorable for costs. Interpret based on category type (e.g., for Revenue categories, this might be favorable). 'New' percentage variance means your budget has a value where the benchmark was zero.

"; reportOutput.innerHTML = html; document.getElementById('ibbc-download-pdf').disabled = categoriesData.length === 0; } // PDF Download document.getElementById('ibbc-download-pdf').addEventListener('click', function () { if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { alert('Error: jsPDF library is not loaded.'); return; } const { jsPDF } = jspdf; const doc = new jsPDF('l'); // Landscape for wide table const currency = CONFIG_INPUTS.currencySymbol.value || '$'; const basis = CONFIG_INPUTS.comparisonBasis.value; const totalRevenue = getNum(CONFIG_INPUTS.totalRevenue.value); const totalEmployees = getNum(CONFIG_INPUTS.totalEmployees.value); const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--ibbc-primary-color').trim(); const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--ibbc-secondary-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--ibbc-text-color').trim(); const buttonTextColor = getComputedStyle(document.documentElement).getPropertyValue('--ibbc-button-text-color').trim(); doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text('Industry Benchmark & Budget Comparison Report', doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' }); doc.setFontSize(12); doc.setTextColor(textColor); let lastY = 30; doc.text(`Business Name: ${CONFIG_INPUTS.businessName.value || 'N/A'}`, 14, lastY); lastY += 7; doc.text(`Analysis Period: ${CONFIG_INPUTS.analysisPeriod.value || 'N/A'}`, 14, lastY); lastY += 7; let basisText = basis === 'absolute' ? "Absolute Amounts" : basis === 'percentageOfRevenue' ? "% of Total Revenue" : `Cost Per Employee (${currency}/Emp)`; doc.text(`Comparison Basis: ${basisText}`, 14, lastY); lastY += 7; if (basis === 'percentageOfRevenue') doc.text(`Total Revenue: ${currency}${totalRevenue.toFixed(2)}`, 14, lastY); lastY += 7; if (basis === 'perEmployee') doc.text(`Total Employees: ${totalEmployees}`, 14, lastY); lastY += 7; doc.text(`Currency: ${currency}`, 14, lastY); lastY += 10; const tableBody = []; let totalYourBudgetPdf = 0; let totalBenchmarkCalculatedAbsPdf = 0; document.querySelectorAll('.ibbc-category-item').forEach(item => { const catName = item.querySelector('.ibbc-cat-name').value || 'N/A'; const yourBudgetAbs = getNum(item.querySelector('.ibbc-cat-budget').value); const benchmarkInputValue = getNum(item.querySelector('.ibbc-cat-benchmark-val').value); let yourBudgetBasisValText = "-"; let benchmarkInputValText = "-"; let benchmarkCalculatedAbs = 0; if (basis === 'absolute') { yourBudgetBasisValText = `${currency}${yourBudgetAbs.toFixed(2)}`; benchmarkInputValText = `${currency}${benchmarkInputValue.toFixed(2)}`; benchmarkCalculatedAbs = benchmarkInputValue; } else if (basis === 'percentageOfRevenue') { yourBudgetBasisValText = totalRevenue > 0 ? `${((yourBudgetAbs / totalRevenue) * 100).toFixed(1)}%` : 'N/A'; benchmarkInputValText = `${benchmarkInputValue.toFixed(1)}%`; benchmarkCalculatedAbs = (benchmarkInputValue / 100) * totalRevenue; } else if (basis === 'perEmployee') { yourBudgetBasisValText = totalEmployees > 0 ? `${currency}${(yourBudgetAbs / totalEmployees).toFixed(2)}` : 'N/A'; benchmarkInputValText = `${currency}${benchmarkInputValue.toFixed(2)}`; benchmarkCalculatedAbs = benchmarkInputValue * totalEmployees; } const varianceAbs = yourBudgetAbs - benchmarkCalculatedAbs; const variancePerc = benchmarkCalculatedAbs !== 0 ? (varianceAbs / benchmarkCalculatedAbs) * 100 : (yourBudgetAbs > 0 ? Infinity : 0); let variancePercText = isFinite(variancePerc) ? `${variancePerc.toFixed(1)}%` : (yourBudgetAbs > 0 && benchmarkCalculatedAbs === 0 ? "New" : "N/A"); tableBody.push([ catName, `${currency}${yourBudgetAbs.toFixed(2)}`, yourBudgetBasisValText, benchmarkInputValText, `${currency}${benchmarkCalculatedAbs.toFixed(2)}`, `${currency}${varianceAbs.toFixed(2)}`, variancePercText ]); totalYourBudgetPdf += yourBudgetAbs; totalBenchmarkCalculatedAbsPdf += benchmarkCalculatedAbs; }); const totalVarianceAbsPdf = totalYourBudgetPdf - totalBenchmarkCalculatedAbsPdf; const totalVariancePercPdf = totalBenchmarkCalculatedAbsPdf !== 0 ? (totalVarianceAbsPdf / totalBenchmarkCalculatedAbsPdf) * 100 : (totalYourBudgetPdf > 0 ? Infinity : 0); let totalVariancePercTextPdf = isFinite(totalVariancePercPdf) ? `${totalVariancePercPdf.toFixed(1)}%` : (totalYourBudgetPdf > 0 && totalBenchmarkCalculatedAbsPdf === 0 ? "New Total" : "N/A"); tableBody.push([ // Total Row { content: 'TOTALS', styles: { fontStyle: 'bold', fillColor: primaryColor, textColor: buttonTextColor } }, { content: `${currency}${totalYourBudgetPdf.toFixed(2)}`, styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } }, { content: `${ basis === 'percentageOfRevenue' && totalRevenue > 0 ? ((totalYourBudgetPdf/totalRevenue)*100).toFixed(1)+'%' : (basis === 'perEmployee' && totalEmployees > 0 ? currency+(totalYourBudgetPdf/totalEmployees).toFixed(2) : '-')}`, styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } }, { content: '-', styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } }, // Sum of benchmark inputs is not always meaningful { content: `${currency}${totalBenchmarkCalculatedAbsPdf.toFixed(2)}`, styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } }, { content: `${currency}${totalVarianceAbsPdf.toFixed(2)}`, styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } }, { content: totalVariancePercTextPdf, styles: { fontStyle: 'bold', halign:'right', fillColor: primaryColor, textColor: buttonTextColor } } ]); doc.autoTable({ startY: lastY, head: [['Category', `Your Budget (${currency})`, `Your Budget (${basis === 'percentageOfRevenue' ? '%' : basis === 'perEmployee' ? currency+'/E' : currency})`, `Benchmark (${basis === 'percentageOfRevenue' ? '%' : basis === 'perEmployee' ? currency+'/E' : 'Val'})`, `Benchmark (${currency} Eq.)`, `Variance (${currency})`, 'Variance (%)']], body: tableBody, theme: 'grid', headStyles: { fillColor: secondaryColor, textColor: buttonTextColor, fontSize: 7, cellPadding:1 }, styles: { fontSize: 7, cellPadding: 1.5 }, columnStyles: { 1: {halign: 'right'}, 2: {halign: 'right'}, 3: {halign: 'right'}, 4: {halign: 'right'}, 5: {halign: 'right'}, 6: {halign: 'right'} } }); doc.save(`Budget_Benchmark_Comparison_${CONFIG_INPUTS.analysisPeriod.value.replace(/\s+/g, '_') || 'Report'}.pdf`); }); // Initial setup checkEmptyState(CATEGORIES_CONTAINER, 'ibbc-no-items-text'); updateBenchmarkInputLabels(); showTab(0); updateAllCurrencyPrefixes(); });
Scroll to Top