horizon-bulk-csv-generator.md (3565B)
1 --- 2 title: "Horizon bulk CSV generator" 3 date: 2025-08-16T08:26:00 4 tags: ["Downloads", "Tools", "Work"] 5 --- 6 7 I had a bit of a thought recently that each time I generate a bulk upload CSV file for Horizon I spend more time copy and pasting data to-and-from Excel and notepad versus actually inputting data so I threw together a bulk upload generator. 8 9 <label>Domain: <input type="text" id="domain" placeholder="example.com"></label> 10 11 <label>Extension Range: <input type="text" id="range" placeholder="200-220"></label> 12 13 <label><input type="checkbox" id="device">Include Devices</label> 14 15 <button onclick="downloadCSV()">Download CSV</button> 16 17 <div id="preview"></div> 18 19 <script> 20 let lastGenerated = { headers: [], rows: [], domain: "", start: 0, end: 0 }; 21 22 function buildData() { 23 const domain = document.getElementById('domain').value.trim(); 24 const rangeInput = document.getElementById('range').value.trim(); 25 const includeDevice = document.getElementById('device').checked; 26 27 // Parse range safely 28 const parts = rangeInput.split('-').map(p => parseInt(p, 10)); 29 if (parts.length !== 2 || isNaN(parts[0]) || isNaN(parts[1]) || parts[0] > parts[1] || !domain) { 30 document.getElementById('preview').innerHTML = "<p style='color:red'>Enter a valid domain and range.</p>"; 31 lastGenerated = { headers: [], rows: [], domain: "", start: 0, end: 0 }; 32 return; 33 } 34 35 const start = parts[0]; 36 const end = parts[1]; 37 38 // Headers 39 let headers = ["User ID","First Name","Last Name","Email","Phone Number","Extension"]; 40 if (includeDevice) headers.push("Device"); 41 headers.push("Service Pack"); 42 43 let rows = [headers]; 44 45 for (let ext = start; ext <= end; ext++) { 46 let userId = `ext${ext}@${domain}`; 47 let lastName = ext.toString(); 48 let email = "email@example.com"; 49 let servicePack = "Premium"; 50 51 let row = [userId, "", lastName, email, "", ext.toString()]; 52 if (includeDevice) row.push(""); // device placeholder 53 row.push(servicePack); 54 55 rows.push(row); 56 } 57 58 // Save for download later 59 lastGenerated = { headers, rows, domain, start, end }; 60 61 // Build preview 62 let html = "<h3>Preview</h3><table><thead><tr>"; 63 headers.forEach(h => { html += `<th>${h}</th>`; }); 64 html += "</tr></thead><tbody>"; 65 rows.slice(1, 11).forEach(r => { 66 html += "<tr>"; 67 r.forEach(cell => { html += `<td>${cell}</td>`; }); 68 html += "</tr>"; 69 }); 70 if (rows.length > 11) { 71 html += `<tr><td colspan="${headers.length}">...and ${rows.length - 11} more rows</td></tr>`; 72 } 73 html += "</tbody></table>"; 74 document.getElementById('preview').innerHTML = html; 75 } 76 77 function downloadCSV() { 78 if (!lastGenerated.rows.length) { 79 alert("Please enter valid inputs first."); 80 return; 81 } 82 83 const { rows, domain, start, end } = lastGenerated; 84 85 const csvContent = rows.map(r => r.join(",")).join("\n"); 86 const blob = new Blob([csvContent], { type: "text/csv" }); 87 const url = URL.createObjectURL(blob); 88 89 const safeDomain = domain.replace(/[^a-zA-Z0-9.-]/g, "_"); 90 const fileName = `${safeDomain}-${start}-${end}.csv`; 91 92 const a = document.createElement("a"); 93 a.href = url; 94 a.download = fileName; 95 a.click(); 96 URL.revokeObjectURL(url); 97 } 98 99 // Live update listeners 100 document.getElementById('domain').addEventListener('input', buildData); 101 document.getElementById('range').addEventListener('input', buildData); 102 document.getElementById('device').addEventListener('change', buildData); 103 </script>