{"id":135161,"date":"2025-12-11T10:03:11","date_gmt":"2025-12-11T10:03:11","guid":{"rendered":"https:\/\/blog.finxter.com\/?p=1671560"},"modified":"2025-12-11T10:03:11","modified_gmt":"2025-12-11T10:03:11","slug":"merge-two-csv-files-online-free-tool","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2025\/12\/11\/merge-two-csv-files-online-free-tool\/","title":{"rendered":"Merge Two CSV Files Online (Free Tool)"},"content":{"rendered":"<p>Easily combine two CSV files into one without any downloads or complex software &#8212; just upload and merge in your browser. Perfect for quickly appending data from multiple spreadsheets.<\/p>\n<p><strong>How It Works:<\/strong> Upload your primary CSV (the one with the header row you&#8217;ll keep) as the first file. Then select the second CSV to append its rows below.<\/p>\n<div style=\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 500px; margin: 0 auto; padding: 2rem; background: #f8f9fa; border-radius: 12px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\">\n<style> .upload-area { text-align: center; margin-bottom: 1.5rem; } .file-input { display: none; } .file-label { display: inline-block; padding: 0.75rem 1.5rem; margin: 0.5rem; background: white; border: 2px dashed #dee2e6; border-radius: 8px; cursor: pointer; transition: all 0.2s; color: #495057; } .file-label:hover { border-color: #007bff; color: #007bff; } .file-label.has-file { border-color: #28a745; background: #d4edda; color: #155724; } .merge-btn { display: block; width: 100%; padding: 0.75rem; background: #007bff; color: white; border: none; border-radius: 8px; font-size: 1rem; cursor: pointer; transition: background 0.2s; margin: 1rem 0; } .merge-btn:hover:not(:disabled) { background: #0056b3; } .merge-btn:disabled { background: #6c757d; cursor: not-allowed; } .download-link { display: none; text-align: center; margin-top: 1rem; } .download-link a { color: #28a745; text-decoration: none; font-weight: 500; } .error { color: #dc3545; text-align: center; margin: 1rem 0; display: none; } h2 { text-align: center; color: #212529; margin-bottom: 1.5rem; font-size: 1.5rem; font-weight: 600; } <\/style>\n<h2>CSV Merger<\/h2>\n<div class=\"upload-area\"> <input type=\"file\" id=\"file1\" class=\"file-input\" accept=\".csv\"> <label for=\"file1\" class=\"file-label\">Upload First CSV<\/label> <\/p>\n<p style=\"font-size: 0.875rem; color: #6c757d; margin-top: 0.5rem;\">Select the primary CSV (header will be used)<\/p>\n<\/p><\/div>\n<div class=\"upload-area\"> <input type=\"file\" id=\"file2\" class=\"file-input\" accept=\".csv\"> <label for=\"file2\" class=\"file-label\">Upload Second CSV<\/label> <\/p>\n<p style=\"font-size: 0.875rem; color: #6c757d; margin-top: 0.5rem;\">Select the CSV to append<\/p>\n<\/p><\/div>\n<p> <button id=\"mergeBtn\" class=\"merge-btn\" onclick=\"mergeFiles()\" disabled>Merge CSVs<\/button> <\/p>\n<div id=\"error\" class=\"error\"><\/div>\n<div id=\"download\" class=\"download-link\">\n<p>Download ready!<\/p>\n<p> <a id=\"downloadLink\" href=\"#\" download=\"merged.csv\">Download Merged CSV<\/a> <\/div>\n<p> <script> let file1Content = null; let file2Content = null; document.getElementById('file1').addEventListener('change', function(e) { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(ev) { file1Content = ev.target.result; updateUI(); }; reader.readAsText(file); } }); document.getElementById('file2').addEventListener('change', function(e) { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(ev) { file2Content = ev.target.result; updateUI(); }; reader.readAsText(file); } }); function updateUI() { const label1 = document.querySelector('label[for=\"file1\"]'); const label2 = document.querySelector('label[for=\"file2\"]'); const btn = document.getElementById('mergeBtn'); if (file1Content) { label1.textContent = 'First CSV Selected'; label1.classList.add('has-file'); } else { label1.textContent = 'Upload First CSV'; label1.classList.remove('has-file'); } if (file2Content) { label2.textContent = 'Second CSV Selected'; label2.classList.add('has-file'); } else { label2.textContent = 'Upload Second CSV'; label2.classList.remove('has-file'); } btn.disabled = !(file1Content && file2Content); } function showError(msg) { const errorDiv = document.getElementById('error'); errorDiv.textContent = msg; errorDiv.style.display = 'block'; setTimeout(() => { errorDiv.style.display = 'none'; }, 5000); } function parseCSV(text) { const lines = text.trim().split(\/\\r?\\n\/); const result = []; for (let line of lines) { if (!line.trim()) continue; const row = []; let col = ''; let inQuote = false; for (let i = 0; i < line.length; i++) { const char = line[i]; if (char === '\"') { inQuote = !inQuote; } else if (char === ',') { if (!inQuote) { row.push(col.replace(\/\"\/g, '').trim()); col = ''; } else { col += char; } } else { col += char; } } row.push(col.replace(\/\"\/g, '').trim()); \/\/ last column result.push(row); } return result; } function toCSV(data) { return data.map(row => row.map(cell => '\"' + cell.replace(\/\"\/g, '\"\"') + '\"').join(',')).join('\\n'); } function mergeFiles() { if (!file1Content || !file2Content) return; try { const csv1 = parseCSV(file1Content); const csv2 = parseCSV(file2Content); if (csv1.length === 0 || csv2.length === 0) { throw new Error('One or both CSVs are empty.'); } const header = csv1[0]; const data1 = csv1.slice(1); const data2 = csv2.slice(1); const mergedData = [...data1, ...data2]; const merged = [header, ...mergedData]; const csvStr = toCSV(merged); const blob = new Blob([csvStr], { type: 'text\/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const downloadLink = document.getElementById('downloadLink'); downloadLink.href = url; document.getElementById('download').style.display = 'block'; \/\/ Auto-trigger download const a = document.createElement('a'); a.href = url; a.download = 'merged.csv'; document.body.appendChild(a); a.click(); document.body.removeChild(a); \/\/ Clean up after delay setTimeout(() => URL.revokeObjectURL(url), 1000); } catch (err) { showError('Error merging CSVs: ' + err.message + '. Ensure files are valid CSVs with matching headers.'); } } <\/script>\n<\/div>\n<p><strong>Quick Tips:<\/strong><\/p>\n<ul class=\"wp-block-list\">\n<li>Ensure both files have matching column headers for best results.<\/li>\n<li>The tool handles basic quoted fields but works best with simple CSVs.<\/li>\n<li>Merged file downloads automatically!<\/li>\n<\/ul>\n<p>If you run into issues, double-check file formats or try smaller files first.<\/p>\n<p>The post <a href=\"https:\/\/blog.finxter.com\/merge-two-csv-files-online-free-tool\/\">Merge Two CSV Files Online (Free Tool)<\/a> appeared first on <a href=\"https:\/\/blog.finxter.com\">Be on the Right Side of Change<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Easily combine two CSV files into one without any downloads or complex software &#8212; just upload and merge in your browser. Perfect for quickly appending data from multiple spreadsheets. How It Works: Upload your primary CSV (the one with the header row you&#8217;ll keep) as the first file. Then select the second CSV to append [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[857],"tags":[73,468,528],"class_list":["post-135161","post","type-post","status-publish","format-standard","hentry","category-python-tut","tag-programming","tag-python","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/135161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=135161"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/135161\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=135161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=135161"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=135161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}