Ad Hoc Analysis Tool

Paste Your Data

Paste your data in CSV (Comma-Separated Values) format below. The first row should contain headers.

Analysis Controls

Analysis Results

Your analysis results will appear here.

Use the controls on the left to generate a chart and data table.

Use the controls to generate your first analysis.

`; document.getElementById('pdf-download-wrapper').style.display = 'none'; }; const generateAnalysis = () => { const dimension = groupBySelect.value; const metric = metricSelect.value; const aggFunc = document.getElementById('agg-func').value; if (!dimension || !metric) { alert("Please select both a dimension and a metric."); return; } const groupedData = rawData.reduce((acc, row) => { const key = row[dimension]; if (!acc[key]) { acc[key] = []; } acc[key].push(row[metric]); return acc; }, {}); const labels = Object.keys(groupedData); let data = []; let tableData = []; labels.forEach(label => { const values = groupedData[label].filter(v => v !== null); // Filter out nulls for calculations let result; switch(aggFunc) { case 'sum': result = values.reduce((a, b) => a + b, 0); break; case 'average': result = values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0; break; case 'count': result = groupedData[label].length; // Count all, including nulls break; case 'countUnique': result = new Set(values).size; break; } data.push(result); tableData.push({ dimension: label, value: result }); }); analysisResult = { title: `${aggFunc.charAt(0).toUpperCase() + aggFunc.slice(1)} of ${metric} by ${dimension}`, labels, data, tableData, dimensionHeader: dimension, metricHeader: `${aggFunc.charAt(0).toUpperCase() + aggFunc.slice(1)}(${metric})` }; renderResults(analysisResult); }; const renderResults = (result) => { analysisTitle.textContent = result.title; // Prepare display area resultsDisplay.innerHTML = `
`; // Render Chart const chartType = document.getElementById('chart-type').value; const ctx = document.getElementById('analysisChart').getContext('2d'); if (currentChart) { currentChart.destroy(); } currentChart = new Chart(ctx, { type: chartType, data: { labels: result.labels, datasets: [{ label: result.title, data: result.data, backgroundColor: chartType === 'pie' ? result.data.map((_, i) => `hsl(${i * 360 / result.data.length}, 70%, 60%)`) : 'rgba(0, 123, 255, 0.6)', borderColor: 'rgba(0, 123, 255, 1)', borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false } }); // Render Table const table = document.getElementById('analysis-table'); table.innerHTML = ` ${result.dimensionHeader} ${result.metricHeader} ${result.tableData.map(row => ` ${row.dimension} ${typeof row.value === 'number' ? row.value.toLocaleString(undefined, { maximumFractionDigits: 2 }) : row.value} `).join('')} `; document.getElementById('pdf-download-wrapper').style.display = 'block'; }; const downloadPDF = () => { if (!analysisResult.title) { alert("Please generate an analysis before downloading."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(20); doc.text("Ad Hoc Analysis Report", 105, 20, { align: 'center' }); doc.setFontSize(14); doc.text(analysisResult.title, 14, 35); let finalY = 40; if(currentChart) { try { const chartImg = currentChart.toBase64Image('image/png', 1.0); doc.addImage(chartImg, 'PNG', 14, finalY, 180, 100); finalY += 110; } catch(e) { console.error("Could not add chart to PDF:", e); } } const tableHead = [analysisResult.dimensionHeader, analysisResult.metricHeader]; const tableBody = analysisResult.tableData.map(row => [row.dimension, row.value.toLocaleString(undefined, { maximumFractionDigits: 2 })]); doc.autoTable({ startY: finalY, head: [tableHead], body: tableBody, theme: 'striped' }); doc.save(`AdHoc_Analysis_${new Date().toISOString().slice(0,10)}.pdf`); }; // --- EVENT LISTENERS --- processDataBtn.addEventListener('click', processData); generateAnalysisBtn.addEventListener('click', generateAnalysis); downloadPdfBtn.addEventListener('click', downloadPDF); window.adhocSwitchTab = (evt, tabName) => { if (evt.currentTarget.classList.contains('disabled')) return; document.querySelectorAll('#adhoc-analysis-container .adhoc-tab-content').forEach(tc => tc.style.display = 'none'); document.querySelectorAll('#adhoc-analysis-container .adhoc-tab-button').forEach(tl => tl.classList.remove('active')); document.getElementById(tabName).style.display = 'block'; evt.currentTarget.classList.add('active'); }; });
Scroll to Top