{"id":699,"date":"2026-07-16T11:34:58","date_gmt":"2026-07-16T11:34:58","guid":{"rendered":"https:\/\/vikassrivastava.in\/academy\/?page_id=699"},"modified":"2026-07-16T11:52:59","modified_gmt":"2026-07-16T11:52:59","slug":"data-cleaning-excel-studio","status":"publish","type":"page","link":"https:\/\/vikassrivastava.in\/academy\/data-cleaning-excel-studio\/","title":{"rendered":"Data Cleaning &amp; Excel Studio"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"699\" class=\"elementor elementor-699\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ca61eef e-con e-atomic-element e-flexbox-base e-bd3ce83 \" data-id=\"ca61eef\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"ca61eef\">\n    \t\t<div class=\"elementor-element elementor-element-9ca5a23 elementor-widget elementor-widget-html\" data-id=\"9ca5a23\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!--\r\nFAST Data Cleaning & Excel Studio for WordPress\r\nPaste into a WordPress Custom HTML block or WPCode HTML snippet.\r\nLibraries: SheetJS + JSZip. Files are processed locally in the browser.\r\n-->\r\n<div id=\"dces-fast-app\" class=\"dces-fast-app\">\r\n  <header class=\"dces-fast-header\">\r\n    <div class=\"dces-fast-brand\">\r\n      <span class=\"dces-fast-logo\">XL<\/span>\r\n      <div>\r\n        <strong>Data Cleaning & Excel Studio<\/strong>\r\n        <small>Fast browser-based Excel cleaning and consolidation<\/small>\r\n      <\/div>\r\n    <\/div>\r\n    <button id=\"dces-fast-theme\" class=\"dces-fast-theme\" type=\"button\" aria-label=\"Toggle dark mode\">\u25d0<\/button>\r\n  <\/header>\r\n\r\n  <section class=\"dces-fast-hero\">\r\n    <span>FAST \u2022 PRIVATE \u2022 NO UPLOAD<\/span>\r\n    <h1>Clean, Consolidate and Validate Excel Data<\/h1>\r\n    <p>Optimized for quick processing of office workbooks without repeated headers or unnecessary browser load.<\/p>\r\n  <\/section>\r\n\r\n  <main class=\"dces-fast-main\">\r\n    <input id=\"dces-fast-search\" class=\"dces-fast-search\" type=\"search\" placeholder=\"Search tools\u2026\">\r\n\r\n    <section id=\"dces-fast-tools\" class=\"dces-fast-tools\">\r\n      <button class=\"dces-fast-card active\" data-tool=\"clean\" data-search=\"clean duplicate blanks spaces\">\r\n        <i>\ud83e\uddf9<\/i><b>Clean Excel Data<\/b><small>Remove duplicates, blanks and extra spaces<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"consolidateFiles\" data-search=\"consolidate workbooks files same format\">\r\n        <i>\ud83d\udcda<\/i><b>Consolidate Workbooks<\/b><small>Append same-format files with one header<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"consolidateSheets\" data-search=\"consolidate worksheets workbook no headers\">\r\n        <i>\ud83d\udcd1<\/i><b>Consolidate Worksheets<\/b><small>Append all sheets without repeated headers<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"compare\" data-search=\"compare excel files changes\">\r\n        <i>\u2696\ufe0f<\/i><b>Compare Excel Files<\/b><small>Find added, removed and changed rows<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"mapping\" data-search=\"column mapping rename reorder\">\r\n        <i>\ud83e\udded<\/i><b>Column Mapping<\/b><small>Rename and reorder columns<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"validate\" data-search=\"duplicate key missing validation\">\r\n        <i>\ud83d\udd11<\/i><b>Key Validation<\/b><small>Find missing and duplicate keys<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"split\" data-search=\"split workbook worksheets zip\">\r\n        <i>\u2702\ufe0f<\/i><b>Split Workbook<\/b><small>Download each sheet separately<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"profile\" data-search=\"data profile quality blanks unique\">\r\n        <i>\ud83d\udcca<\/i><b>Data Quality Profile<\/b><small>Analyze blanks, duplicates and unique values<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"format\" data-search=\"format dates phone text number\">\r\n        <i>\ud83d\udee0\ufe0f<\/i><b>Format Columns<\/b><small>Standardize text, dates and phone numbers<\/small>\r\n      <\/button>\r\n      <button class=\"dces-fast-card\" data-tool=\"convert\" data-search=\"convert xlsx csv json\">\r\n        <i>\ud83d\udd04<\/i><b>Convert Data<\/b><small>Convert XLSX, CSV and JSON<\/small>\r\n      <\/button>\r\n    <\/section>\r\n\r\n    <section class=\"dces-fast-workspace\">\r\n      <div class=\"dces-fast-head\">\r\n        <div>\r\n          <h2 id=\"dces-fast-title\">Clean Excel Data<\/h2>\r\n          <p id=\"dces-fast-desc\">Remove duplicate rows, blank rows and unnecessary spaces.<\/p>\r\n        <\/div>\r\n        <button id=\"dces-fast-reset\" class=\"dces-fast-btn light\" type=\"button\">Reset<\/button>\r\n      <\/div>\r\n\r\n      <div id=\"dces-fast-alert\" class=\"dces-fast-alert\" hidden><\/div>\r\n\r\n      <div id=\"dces-fast-upload\" class=\"dces-fast-upload\" tabindex=\"0\" role=\"button\">\r\n        <strong>\u21e7<\/strong>\r\n        <h3>Drop Excel or CSV files here<\/h3>\r\n        <p>or click to browse<\/p>\r\n        <button class=\"dces-fast-btn primary\" type=\"button\">Choose Files<\/button>\r\n        <small>Supported: XLSX, XLS, CSV \u2022 Recommended up to 25 MB per file<\/small>\r\n        <input id=\"dces-fast-input\" type=\"file\" accept=\".xlsx,.xls,.csv\" hidden>\r\n      <\/div>\r\n\r\n      <div id=\"dces-fast-files\" class=\"dces-fast-files\"><\/div>\r\n      <div id=\"dces-fast-options\" class=\"dces-fast-options\"><\/div>\r\n\r\n      <section id=\"dces-fast-preview\" class=\"dces-fast-preview\" hidden>\r\n        <div class=\"dces-fast-preview-head\">\r\n          <h3>Preview<\/h3>\r\n          <small id=\"dces-fast-preview-summary\"><\/small>\r\n        <\/div>\r\n        <div class=\"dces-fast-table-wrap\">\r\n          <table id=\"dces-fast-table\"><\/table>\r\n        <\/div>\r\n      <\/section>\r\n\r\n      <div id=\"dces-fast-kpis\"><\/div>\r\n\r\n      <div id=\"dces-fast-progress\" class=\"dces-fast-progress\" hidden>\r\n        <div><span id=\"dces-fast-progress-text\">Processing\u2026<\/span><span id=\"dces-fast-progress-pct\">0%<\/span><\/div>\r\n        <em><i id=\"dces-fast-bar\"><\/i><\/em>\r\n      <\/div>\r\n\r\n      <div class=\"dces-fast-action\">\r\n        <button id=\"dces-fast-process\" class=\"dces-fast-btn primary large\" type=\"button\" disabled>Clean Data<\/button>\r\n      <\/div>\r\n\r\n      <section id=\"dces-fast-result\" class=\"dces-fast-result\" hidden>\r\n        <span>\u2713<\/span>\r\n        <h3>Your file is ready<\/h3>\r\n        <p id=\"dces-fast-result-details\"><\/p>\r\n        <button id=\"dces-fast-download\" class=\"dces-fast-btn success\" type=\"button\">Download File<\/button>\r\n      <\/section>\r\n    <\/section>\r\n  <\/main>\r\n<\/div>\r\n\r\n<style>\r\n#dces-fast-app{\r\n  --p:#135ef2;--p2:#6a5af9;--g:#12825a;--r:#c63d4c;\r\n  --bg:#f4f7fb;--s:#fff;--s2:#eef3f9;--t:#172033;--m:#687487;--b:#dbe3ee;\r\n  --shadow:0 16px 42px rgba(29,48,87,.11);\r\n  font-family:Inter,system-ui,-apple-system,\"Segoe UI\",sans-serif;\r\n  color:var(--t);background:var(--bg);border-radius:22px;overflow:hidden;line-height:1.5\r\n}\r\n#dces-fast-app.dark{--bg:#0f141d;--s:#171e29;--s2:#222b38;--t:#f4f7fb;--m:#aab4c3;--b:#303b4c;--shadow:0 16px 42px rgba(0,0,0,.3)}\r\n#dces-fast-app *{box-sizing:border-box}\r\n#dces-fast-app button,#dces-fast-app input,#dces-fast-app select,#dces-fast-app textarea{font:inherit}\r\n#dces-fast-app button{cursor:pointer}\r\n.dces-fast-header{display:flex;align-items:center;justify-content:space-between;padding:17px clamp(16px,4vw,52px);background:var(--s);border-bottom:1px solid var(--b)}\r\n.dces-fast-brand{display:flex;align-items:center;gap:12px}.dces-fast-brand div{display:flex;flex-direction:column}.dces-fast-brand strong{font-size:20px}.dces-fast-brand small{color:var(--m)}\r\n.dces-fast-logo{display:grid;place-items:center;width:48px;height:48px;border-radius:14px;background:linear-gradient(135deg,#107c41,var(--p));color:#fff;font-weight:900}\r\n.dces-fast-theme{width:42px;height:42px;border:1px solid var(--b);border-radius:11px;background:var(--s2);color:var(--t);font-size:20px}\r\n.dces-fast-hero{text-align:center;padding:54px 18px 76px;background:radial-gradient(circle at 12% 20%,rgba(19,94,242,.14),transparent 28%),radial-gradient(circle at 88% 20%,rgba(16,124,65,.12),transparent 28%),var(--s)}\r\n.dces-fast-hero>span{display:inline-block;padding:7px 13px;border-radius:999px;background:rgba(19,94,242,.1);color:var(--p);font-size:12px;font-weight:850}\r\n.dces-fast-hero h1{max-width:950px;margin:17px auto 13px;font-size:clamp(34px,6vw,60px);line-height:1.08;letter-spacing:-.045em}\r\n.dces-fast-hero p{max-width:820px;margin:auto;color:var(--m);font-size:clamp(16px,2vw,20px)}\r\n.dces-fast-main{max-width:1280px;margin:auto;padding:30px clamp(12px,3vw,34px) 50px}\r\n.dces-fast-search{display:block;width:min(640px,100%);height:56px;margin:-52px auto 27px;padding:0 20px;border:1px solid var(--b);border-radius:15px;background:var(--s);color:var(--t);box-shadow:var(--shadow);outline:none}\r\n.dces-fast-tools{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:13px;margin-bottom:27px}\r\n.dces-fast-card{min-height:148px;text-align:left;padding:17px;border:1px solid var(--b);border-radius:16px;background:var(--s);color:var(--t);transition:.18s}\r\n.dces-fast-card:hover{transform:translateY(-2px);border-color:var(--p);box-shadow:var(--shadow)}\r\n.dces-fast-card.active{border-color:var(--p);box-shadow:0 0 0 3px rgba(19,94,242,.11)}\r\n.dces-fast-card i{display:grid;place-items:center;width:42px;height:42px;border-radius:11px;background:rgba(19,94,242,.1);font-style:normal;font-size:21px;margin-bottom:11px}\r\n.dces-fast-card b,.dces-fast-card small{display:block}.dces-fast-card small{margin-top:5px;color:var(--m);font-size:12px}\r\n.dces-fast-workspace{padding:clamp(18px,3vw,31px);background:var(--s);border:1px solid var(--b);border-radius:21px;box-shadow:var(--shadow)}\r\n.dces-fast-head{display:flex;justify-content:space-between;gap:20px}.dces-fast-head h2{margin:0 0 5px;font-size:28px}.dces-fast-head p{margin:0;color:var(--m)}\r\n.dces-fast-alert{margin:16px 0;padding:12px 14px;border-radius:11px;background:rgba(198,61,76,.1);border:1px solid rgba(198,61,76,.25);color:var(--r)}\r\n.dces-fast-upload{text-align:center;padding:35px 18px;border:2px dashed var(--b);border-radius:17px;background:var(--s2);outline:none;margin-top:20px}\r\n.dces-fast-upload:hover,.dces-fast-upload.drag{border-color:var(--p);background:rgba(19,94,242,.06)}\r\n.dces-fast-upload>strong{display:block;font-size:40px;color:var(--p)}.dces-fast-upload h3{margin:6px 0}.dces-fast-upload p{margin:0 0 14px;color:var(--m)}.dces-fast-upload small{display:block;margin-top:13px;color:var(--m)}\r\n.dces-fast-btn{border:0;border-radius:10px;padding:11px 16px;font-weight:800}.dces-fast-btn.primary{background:linear-gradient(135deg,var(--p),var(--p2));color:#fff}.dces-fast-btn.success{background:var(--g);color:#fff}.dces-fast-btn.light{background:var(--s2);color:var(--t);border:1px solid var(--b)}.dces-fast-btn.large{min-width:230px;padding:14px 22px}.dces-fast-btn:disabled{opacity:.45;cursor:not-allowed}\r\n.dces-fast-files{display:grid;gap:10px;margin-top:17px}.dces-fast-file{display:flex;align-items:center;gap:12px;padding:11px;border:1px solid var(--b);border-radius:12px}\r\n.dces-fast-file>span{display:grid;place-items:center;width:42px;height:42px;border-radius:10px;background:rgba(16,124,65,.1);color:#107c41;font-weight:900}\r\n.dces-fast-file div{flex:1;min-width:0}.dces-fast-file b{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dces-fast-file small{color:var(--m)}.dces-fast-file button{border:0;background:transparent;color:var(--r);font-size:21px}\r\n.dces-fast-options{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:13px;margin-top:19px}.dces-fast-field{display:flex;flex-direction:column;gap:7px}.dces-fast-field label{font-size:13px;font-weight:750}.dces-fast-field input,.dces-fast-field select,.dces-fast-field textarea{width:100%;border:1px solid var(--b);border-radius:10px;background:var(--s2);color:var(--t);padding:0 12px}.dces-fast-field input,.dces-fast-field select{height:43px}.dces-fast-field textarea{min-height:105px;padding-top:10px}.dces-fast-checks{grid-column:1\/-1;display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:9px}.dces-fast-checks label{padding:11px;border:1px solid var(--b);border-radius:10px;background:var(--s2)}\r\n.dces-fast-preview{margin-top:21px}.dces-fast-preview-head{display:flex;justify-content:space-between;align-items:center}.dces-fast-preview h3{margin:0}.dces-fast-preview small{color:var(--m)}.dces-fast-table-wrap{margin-top:8px;overflow:auto;max-height:320px;border:1px solid var(--b);border-radius:11px}.dces-fast-table-wrap table{border-collapse:collapse;width:100%;font-size:12px}.dces-fast-table-wrap th,.dces-fast-table-wrap td{padding:8px 9px;border-right:1px solid var(--b);border-bottom:1px solid var(--b);white-space:nowrap;max-width:180px;overflow:hidden;text-overflow:ellipsis}.dces-fast-table-wrap th{position:sticky;top:0;background:var(--s2);text-align:left}\r\n.dces-fast-progress{margin-top:19px}.dces-fast-progress>div{display:flex;justify-content:space-between;font-size:13px;font-weight:700}.dces-fast-progress em{display:block;height:9px;margin-top:6px;background:var(--s2);border-radius:999px;overflow:hidden}.dces-fast-progress em i{display:block;width:0;height:100%;background:linear-gradient(90deg,var(--p),#10a767)}\r\n.dces-fast-action{text-align:center;margin-top:23px}.dces-fast-result{text-align:center;margin-top:23px;padding:24px;border-radius:15px;background:rgba(18,130,90,.08);border:1px solid rgba(18,130,90,.25)}\r\n.dces-fast-result>span{display:grid;place-items:center;width:50px;height:50px;margin:auto;border-radius:50%;background:var(--g);color:#fff;font-size:27px}.dces-fast-result h3{margin:9px 0 4px}.dces-fast-result p{color:var(--m)}\r\n.dces-fast-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:11px;margin-top:19px}.dces-fast-kpi{padding:14px;border:1px solid var(--b);border-radius:12px;background:var(--s2)}.dces-fast-kpi b{display:block;font-size:24px}.dces-fast-kpi small{color:var(--m)}\r\n.hidden{display:none!important}\r\n@media(max-width:720px){#dces-fast-app{border-radius:0}.dces-fast-brand small{display:none}.dces-fast-brand strong{font-size:16px}.dces-fast-header{padding:13px}.dces-fast-tools{grid-template-columns:repeat(2,1fr)}.dces-fast-card{min-height:140px;padding:14px}.dces-fast-kpis{grid-template-columns:repeat(2,1fr)}.dces-fast-btn.large{width:100%}}\r\n<\/style>\r\n\r\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/xlsx@0.18.5\/dist\/xlsx.full.min.js\"><\/script>\r\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/jszip@3.10.1\/dist\/jszip.min.js\"><\/script>\r\n\r\n<script>\r\n(function(){\r\n'use strict';\r\nconst app=document.getElementById('dces-fast-app');\r\nif(!app||app.dataset.ready)return;\r\napp.dataset.ready='1';\r\n\r\nconst $=id=>document.getElementById(id);\r\nconst cfg={\r\n clean:['Clean Excel Data','Remove duplicate rows, blank rows and unnecessary spaces.',false,'Clean Data'],\r\n consolidateFiles:['Consolidate Workbooks','Append the same-format worksheet from multiple files with only one header.',true,'Consolidate Files'],\r\n consolidateSheets:['Consolidate Worksheets','Append all worksheets from one workbook without repeated headers.',false,'Consolidate Sheets'],\r\n compare:['Compare Excel Files','Compare two workbooks using a unique key column.',true,'Compare Files'],\r\n mapping:['Column Mapping','Rename and reorder columns into a standard format.',false,'Apply Mapping'],\r\n validate:['Key Validation','Find duplicate and missing business keys.',false,'Validate Keys'],\r\n split:['Split Workbook','Download every worksheet as a separate Excel file.',false,'Split Workbook'],\r\n profile:['Data Quality Profile','Analyze blanks, duplicate rows and unique values.',false,'Analyze Data'],\r\n format:['Format Columns','Standardize text, dates, phone numbers and numeric values.',false,'Format Data'],\r\n convert:['Convert Data','Convert the first worksheet to XLSX, CSV or JSON.',false,'Convert File']\r\n};\r\n\r\nlet state={tool:'clean',files:[],books:[],output:null,outputName:''};\r\n\r\nconst field=(id,label,value='',placeholder='')=>`<div class=\"dces-fast-field\"><label for=\"${id}\">${label}<\/label><input id=\"${id}\" value=\"${value}\" placeholder=\"${placeholder}\"><\/div>`;\r\nconst select=(id,label,options)=>`<div class=\"dces-fast-field\"><label for=\"${id}\">${label}<\/label><select id=\"${id}\">${options}<\/select><\/div>`;\r\n\r\nfunction showError(message){$('dces-fast-alert').textContent=message;$('dces-fast-alert').hidden=false}\r\nfunction clearError(){$('dces-fast-alert').hidden=true}\r\nfunction progress(value,text){$('dces-fast-progress').hidden=false;$('dces-fast-bar').style.width=value+'%';$('dces-fast-progress-pct').textContent=Math.round(value)+'%';$('dces-fast-progress-text').textContent=text}\r\nfunction hideProgress(){$('dces-fast-progress').hidden=true;$('dces-fast-bar').style.width='0%'}\r\nfunction human(bytes){const u=['B','KB','MB'];let i=0,n=bytes||0;while(n>=1024&&i<2){n\/=1024;i++}return `${n.toFixed(i?2:0)} ${u[i]}`}\r\nfunction safeName(s){return String(s).replace(\/[\\\\\/:*?\"<>|]\/g,'_')}\r\n\r\nfunction configure(){\r\n const c=cfg[state.tool];\r\n $('dces-fast-title').textContent=c[0];\r\n $('dces-fast-desc').textContent=c[1];\r\n $('dces-fast-input').multiple=c[2];\r\n $('dces-fast-process').textContent=c[3];\r\n $('dces-fast-process').disabled=true;\r\n renderOptions();\r\n}\r\nfunction reset(){\r\n state.files=[];state.books=[];state.output=null;state.outputName='';\r\n $('dces-fast-input').value='';$('dces-fast-files').innerHTML='';$('dces-fast-preview').hidden=true;\r\n $('dces-fast-result').hidden=true;$('dces-fast-kpis').innerHTML='';clearError();hideProgress();configure();\r\n}\r\nfunction renderOptions(){\r\n const t=state.tool;\r\n if(t==='clean'){\r\n  $('dces-fast-options').innerHTML=`<div class=\"dces-fast-checks\">\r\n   <label><input id=\"optDup\" type=\"checkbox\" checked> Remove duplicate rows<\/label>\r\n   <label><input id=\"optBlankRows\" type=\"checkbox\" checked> Remove blank rows<\/label>\r\n   <label><input id=\"optTrim\" type=\"checkbox\" checked> Trim spaces<\/label>\r\n   <label><input id=\"optCollapse\" type=\"checkbox\" checked> Replace repeated spaces<\/label>\r\n   <label><input id=\"optBlankCols\" type=\"checkbox\"> Remove blank columns<\/label>\r\n  <\/div>${select('optCase','Text case','<option value=\"none\">Keep original<\/option><option value=\"upper\">UPPERCASE<\/option><option value=\"lower\">lowercase<\/option><option value=\"title\">Title Case<\/option>')}`;\r\n }else if(t==='consolidateFiles'){\r\n  $('dces-fast-options').innerHTML=select('cfMode','Worksheet selection','<option value=\"first\">First worksheet from each file<\/option><option value=\"named\">Worksheet with the same name<\/option>')+\r\n  field('cfName','Worksheet name','','Required for same-name option')+field('cfOutput','Output sheet name','Consolidated Data')+\r\n  `<div class=\"dces-fast-checks\"><label><input id=\"cfSource\" type=\"checkbox\" checked> Add Source File column<\/label><label><input id=\"cfStrict\" type=\"checkbox\" checked> Stop on header mismatch<\/label><\/div>`;\r\n }else if(t==='consolidateSheets'){\r\n  $('dces-fast-options').innerHTML=field('csOutput','Output sheet name','Consolidated Sheets')+\r\n  `<div class=\"dces-fast-checks\"><label><input id=\"csSource\" type=\"checkbox\" checked> Add Source Sheet column<\/label><label><input id=\"csStrict\" type=\"checkbox\" checked> Stop on header mismatch<\/label><\/div>`;\r\n }else if(t==='compare'){\r\n  $('dces-fast-options').innerHTML=field('cmpKey','Unique key column','','Example: Employee ID, PR Number or Item Code');\r\n }else if(t==='mapping'){\r\n  $('dces-fast-options').innerHTML=`<div class=\"dces-fast-field\" style=\"grid-column:1\/-1\"><label for=\"mapText\">Column mapping \u2014 one per line<\/label><textarea id=\"mapText\" placeholder=\"Old Name = New Name&#10;Emp ID = Employee ID\"><\/textarea><\/div>\r\n  <div class=\"dces-fast-field\" style=\"grid-column:1\/-1\"><label for=\"mapOrder\">Output column order \u2014 comma separated<\/label><textarea id=\"mapOrder\" placeholder=\"Employee ID, Employee Name, Department\"><\/textarea><\/div>\r\n  <div class=\"dces-fast-checks\"><label><input id=\"mapKeep\" type=\"checkbox\"> Keep extra columns<\/label><label><input id=\"mapBlank\" type=\"checkbox\" checked> Add missing columns as blank<\/label><\/div>`;\r\n }else if(t==='validate'){\r\n  $('dces-fast-options').innerHTML=field('valKey','Key column name','','Example: Employee ID or Item Code')+\r\n  `<div class=\"dces-fast-checks\"><label><input id=\"valTrim\" type=\"checkbox\" checked> Trim key spaces<\/label><label><input id=\"valCase\" type=\"checkbox\" checked> Ignore case<\/label><label><input id=\"valValid\" type=\"checkbox\"> Include valid rows sheet<\/label><\/div>`;\r\n }else if(t==='format'){\r\n  $('dces-fast-options').innerHTML=field('fmtColumn','Column name','','Example: Date, Mobile, Employee Name')+\r\n  select('fmtType','Formatting action','<option value=\"upper\">UPPERCASE<\/option><option value=\"lower\">lowercase<\/option><option value=\"title\">Title Case<\/option><option value=\"date\">Date DD-MM-YYYY<\/option><option value=\"phone\">10-digit phone<\/option><option value=\"number\">Convert to number<\/option>');\r\n }else if(t==='convert'){\r\n  $('dces-fast-options').innerHTML=select('outFormat','Output format','<option value=\"xlsx\">Excel (.xlsx)<\/option><option value=\"csv\">CSV (.csv)<\/option><option value=\"json\">JSON (.json)<\/option>');\r\n }else{\r\n  $('dces-fast-options').innerHTML='';\r\n }\r\n}\r\n\r\nasync function readWorkbook(file){\r\n const data=await file.arrayBuffer();\r\n return XLSX.read(data,{type:'array',cellDates:true,dense:false});\r\n}\r\nfunction rowsOf(wb,sheetName){\r\n return XLSX.utils.sheet_to_json(wb.Sheets[sheetName],{header:1,defval:'',raw:false});\r\n}\r\nfunction firstSheet(wb){\r\n const name=wb.SheetNames[0];\r\n return [name,rowsOf(wb,name)];\r\n}\r\nasync function addFiles(fileList){\r\n clearError();\r\n try{\r\n  let files=[...fileList];\r\n  if(!cfg[state.tool][2])files=files.slice(0,1);\r\n  if(state.tool==='compare')files=files.slice(0,2);\r\n  files.forEach(f=>{\r\n   if(f.size>25*1024*1024)throw Error(`${f.name}: recommended browser limit is 25 MB.`);\r\n   if(!\/\\.(xlsx|xls|csv)$\/i.test(f.name))throw Error(`${f.name}: unsupported file format.`);\r\n  });\r\n  state.files=cfg[state.tool][2]?[...state.files,...files]:files;\r\n  if(state.tool==='compare')state.files=state.files.slice(0,2);\r\n  state.books=[];\r\n  for(let i=0;i<state.files.length;i++){\r\n   progress((i\/state.files.length)*88,`Reading ${state.files[i].name}`);\r\n   state.books.push(await readWorkbook(state.files[i]));\r\n   await new Promise(r=>setTimeout(r,0));\r\n  }\r\n  hideProgress();renderFiles();renderPreview();\r\n }catch(e){hideProgress();showError(e.message||'Unable to read file.')}\r\n}\r\nfunction renderFiles(){\r\n $('dces-fast-files').innerHTML='';\r\n state.files.forEach((f,i)=>{\r\n  const el=document.createElement('div');el.className='dces-fast-file';\r\n  el.innerHTML=`<span>XL<\/span><div><b>${safeName(f.name)}<\/b><small>${human(f.size)}<\/small><\/div><button type=\"button\">\u00d7<\/button>`;\r\n  el.querySelector('button').onclick=()=>{state.files.splice(i,1);state.books.splice(i,1);renderFiles();renderPreview()};\r\n  $('dces-fast-files').appendChild(el);\r\n });\r\n $('dces-fast-process').disabled=state.files.length===0||(state.tool==='compare'&&state.files.length!==2)||(state.tool==='consolidateFiles'&&state.files.length<2);\r\n}\r\nfunction renderPreview(){\r\n if(!state.books.length){$('dces-fast-preview').hidden=true;return}\r\n const [name,rows]=firstSheet(state.books[0]);\r\n if(!rows.length){$('dces-fast-preview').hidden=true;return}\r\n const maxRows=Math.min(rows.length,11),maxCols=Math.min(rows[0].length,12);\r\n let html='<thead><tr>';\r\n for(let c=0;c<maxCols;c++)html+=`<th>${rows[0][c]||'Column '+(c+1)}<\/th>`;\r\n html+='<\/tr><\/thead><tbody>';\r\n for(let r=1;r<maxRows;r++){html+='<tr>';for(let c=0;c<maxCols;c++)html+=`<td>${rows[r][c]??''}<\/td>`;html+='<\/tr>'}\r\n html+='<\/tbody>';\r\n $('dces-fast-table').innerHTML=html;\r\n $('dces-fast-preview-summary').textContent=`${name} \u2022 ${Math.max(0,rows.length-1)} rows \u2022 showing first ${maxRows-1}`;\r\n $('dces-fast-preview').hidden=false;\r\n}\r\nfunction sameHeaders(a,b){return JSON.stringify(a.map(x=>String(x).trim().toLowerCase()))===JSON.stringify(b.map(x=>String(x).trim().toLowerCase()))}\r\nfunction makeWorkbook(sheetRows,sheetName){\r\n const wb=XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(wb,XLSX.utils.aoa_to_sheet(sheetRows),sheetName.slice(0,31));\r\n return wb;\r\n}\r\nfunction workbookBlob(wb){\r\n return new Blob([XLSX.write(wb,{bookType:'xlsx',type:'array',compression:true})],{type:'application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});\r\n}\r\nfunction setResult(blob,name,details=''){\r\n state.output=blob;state.outputName=name;\r\n $('dces-fast-result-details').textContent=details||`${name} \u2022 ${human(blob.size)}`;\r\n $('dces-fast-result').hidden=false;\r\n $('dces-fast-download').onclick=()=>{\r\n  const url=URL.createObjectURL(blob),a=document.createElement('a');\r\n  a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();\r\n  setTimeout(()=>URL.revokeObjectURL(url),1200);\r\n };\r\n $('dces-fast-result').scrollIntoView({behavior:'smooth',block:'center'});\r\n}\r\n\r\nfunction cleanText(v){\r\n if(typeof v!=='string')return v;\r\n let s=v;\r\n if($('optTrim').checked)s=s.trim();\r\n if($('optCollapse').checked)s=s.replace(\/\\s+\/g,' ');\r\n const mode=$('optCase').value;\r\n if(mode==='upper')s=s.toUpperCase();\r\n if(mode==='lower')s=s.toLowerCase();\r\n if(mode==='title')s=s.toLowerCase().replace(\/\\b\\w\/g,x=>x.toUpperCase());\r\n return s;\r\n}\r\nfunction cleanRows(rows){\r\n let out=rows.map(r=>r.map(cleanText));\r\n if($('optBlankRows').checked)out=out.filter((r,i)=>i===0||r.some(v=>String(v??'').trim()!==''));\r\n if($('optBlankCols').checked&&out.length){\r\n  const keep=[];const width=Math.max(...out.map(r=>r.length));\r\n  for(let c=0;c<width;c++)if(out.some(r=>String(r[c]??'').trim()!==''))keep.push(c);\r\n  out=out.map(r=>keep.map(c=>r[c]??''));\r\n }\r\n if($('optDup').checked&&out.length>1){\r\n  const seen=new Set();\r\n  out=[out[0],...out.slice(1).filter(r=>{const k=JSON.stringify(r);if(seen.has(k))return false;seen.add(k);return true})];\r\n }\r\n return out;\r\n}\r\n\r\nasync function processTool(){\r\n clearError();$('dces-fast-result').hidden=true;$('dces-fast-kpis').innerHTML='';\r\n try{\r\n  progress(4,'Preparing data');\r\n  const t=state.tool;\r\n\r\n  if(t==='clean'){\r\n   const source=state.books[0],out=XLSX.utils.book_new();let removed=0;\r\n   for(let i=0;i<source.SheetNames.length;i++){\r\n    const name=source.SheetNames[i],rows=rowsOf(source,name),cleaned=cleanRows(rows);\r\n    removed+=rows.length-cleaned.length;\r\n    XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet(cleaned),name.slice(0,31));\r\n    progress(((i+1)\/source.SheetNames.length)*95,`Cleaning ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   setResult(workbookBlob(out),'cleaned-data.xlsx',`${removed} rows removed`);\r\n  }\r\n\r\n  if(t==='consolidateFiles'){\r\n   const mode=$('cfMode').value,named=$('cfName').value.trim(),strict=$('cfStrict').checked,addSource=$('cfSource').checked;\r\n   let combined=[],header=null,total=0;\r\n   for(let i=0;i<state.books.length;i++){\r\n    const wb=state.books[i],sheet=mode==='first'?wb.SheetNames[0]:named;\r\n    if(!sheet||!wb.Sheets[sheet])throw Error(`Worksheet \"${named}\" not found in ${state.files[i].name}.`);\r\n    const rows=rowsOf(wb,sheet);if(!rows.length)continue;\r\n    if(!header){header=rows[0];combined.push(addSource?['Source File',...header]:header)}\r\n    else if(strict&&!sameHeaders(header,rows[0]))throw Error(`Header mismatch in ${state.files[i].name}.`);\r\n    for(const row of rows.slice(1))combined.push(addSource?[state.files[i].name,...row]:row);\r\n    total+=Math.max(0,rows.length-1);\r\n    progress(((i+1)\/state.books.length)*95,`Appending ${state.files[i].name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   setResult(workbookBlob(makeWorkbook(combined,$('cfOutput').value||'Consolidated Data')),'consolidated-workbooks.xlsx',`${state.files.length} files \u2022 ${total} rows \u2022 one header`);\r\n  }\r\n\r\n  if(t==='consolidateSheets'){\r\n   const wb=state.books[0],strict=$('csStrict').checked,addSource=$('csSource').checked;\r\n   let combined=[],header=null,total=0;\r\n   for(let i=0;i<wb.SheetNames.length;i++){\r\n    const name=wb.SheetNames[i],rows=rowsOf(wb,name);if(!rows.length)continue;\r\n    if(!header){header=rows[0];combined.push(addSource?['Source Sheet',...header]:header)}\r\n    else if(strict&&!sameHeaders(header,rows[0]))throw Error(`Header mismatch in worksheet \"${name}\".`);\r\n    for(const row of rows.slice(1))combined.push(addSource?[name,...row]:row);\r\n    total+=Math.max(0,rows.length-1);\r\n    progress(((i+1)\/wb.SheetNames.length)*95,`Appending ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   setResult(workbookBlob(makeWorkbook(combined,$('csOutput').value||'Consolidated Sheets')),'consolidated-worksheets.xlsx',`${wb.SheetNames.length} sheets \u2022 ${total} rows \u2022 repeated headers removed`);\r\n  }\r\n\r\n  if(t==='compare'){\r\n   const key=$('cmpKey').value.trim();if(!key)throw Error('Enter a unique key column.');\r\n   const A=firstSheet(state.books[0])[1],B=firstSheet(state.books[1])[1];\r\n   const ia=A[0].findIndex(x=>String(x).trim().toLowerCase()===key.toLowerCase()),ib=B[0].findIndex(x=>String(x).trim().toLowerCase()===key.toLowerCase());\r\n   if(ia<0||ib<0)throw Error('Key column must exist in both files.');\r\n   const ma=new Map(A.slice(1).map(r=>[String(r[ia]),r])),mb=new Map(B.slice(1).map(r=>[String(r[ib]),r]));\r\n   const added=[],removed=[],changed=[],same=[];\r\n   mb.forEach((r,k)=>{if(!ma.has(k))added.push([k,...r]);else JSON.stringify(ma.get(k))===JSON.stringify(r)?same.push(r):changed.push([k,...ma.get(k),...r])});\r\n   ma.forEach((r,k)=>{if(!mb.has(k))removed.push([k,...r])});\r\n   const out=XLSX.utils.book_new();\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Key',...B[0]],...added]),'Added');\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Key',...A[0]],...removed]),'Removed');\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Key',...A[0].map(x=>'Old '+x),...B[0].map(x=>'New '+x)],...changed]),'Changed');\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Metric','Count'],['Added',added.length],['Removed',removed.length],['Changed',changed.length],['Unchanged',same.length]]),'Summary');\r\n   $('dces-fast-kpis').innerHTML=`<div class=\"dces-fast-kpis\"><div class=\"dces-fast-kpi\"><b>${added.length}<\/b><small>Added<\/small><\/div><div class=\"dces-fast-kpi\"><b>${removed.length}<\/b><small>Removed<\/small><\/div><div class=\"dces-fast-kpi\"><b>${changed.length}<\/b><small>Changed<\/small><\/div><div class=\"dces-fast-kpi\"><b>${same.length}<\/b><small>Unchanged<\/small><\/div><\/div>`;\r\n   setResult(workbookBlob(out),'excel-comparison-report.xlsx');\r\n  }\r\n\r\n  if(t==='mapping'){\r\n   const map={};$('mapText').value.split(\/\\n\/).forEach(line=>{const p=line.split('=');if(p.length>=2)map[p[0].trim().toLowerCase()]=p.slice(1).join('=').trim()});\r\n   const order=$('mapOrder').value.split(',').map(x=>x.trim()).filter(Boolean),keep=$('mapKeep').checked,makeBlank=$('mapBlank').checked;\r\n   const wb=state.books[0],out=XLSX.utils.book_new();\r\n   for(let i=0;i<wb.SheetNames.length;i++){\r\n    const name=wb.SheetNames[i],rows=rowsOf(wb,name);\r\n    if(!rows.length){XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet(rows),name.slice(0,31));continue}\r\n    const renamed=rows[0].map(h=>map[String(h).trim().toLowerCase()]||String(h).trim());\r\n    const wanted=order.length?order:renamed;\r\n    const indices=wanted.map(h=>renamed.findIndex(x=>x.toLowerCase()===h.toLowerCase()));\r\n    const extra=keep?renamed.map((h,j)=>({h,j})).filter(x=>!wanted.some(w=>w.toLowerCase()===x.h.toLowerCase())):[];\r\n    const head=[...wanted,...extra.map(x=>x.h)];\r\n    const body=rows.slice(1).map(row=>[...indices.map(j=>j>=0?row[j]:(makeBlank?'':undefined)),...extra.map(x=>row[x.j])]);\r\n    XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([head,...body]),name.slice(0,31));\r\n    progress(((i+1)\/wb.SheetNames.length)*95,`Mapping ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   setResult(workbookBlob(out),'standardized-columns.xlsx');\r\n  }\r\n\r\n  if(t==='validate'){\r\n   const keyName=$('valKey').value.trim();if(!keyName)throw Error('Enter a key column name.');\r\n   const wb=state.books[0],out=XLSX.utils.book_new(),issues=[['Worksheet','Row Number','Issue','Key Value']];\r\n   let missing=0,duplicates=0;\r\n   for(let i=0;i<wb.SheetNames.length;i++){\r\n    const name=wb.SheetNames[i],rows=rowsOf(wb,name);if(!rows.length)continue;\r\n    const idx=rows[0].findIndex(h=>String(h).trim().toLowerCase()===keyName.toLowerCase());\r\n    if(idx<0)throw Error(`Key column not found in ${name}.`);\r\n    const seen=new Map(),valid=[rows[0]];\r\n    rows.slice(1).forEach((row,j)=>{\r\n     let key=String(row[idx]??'');if($('valTrim').checked)key=key.trim();\r\n     const compare=$('valCase').checked?key.toLowerCase():key;\r\n     if(!key){missing++;issues.push([name,j+2,'Missing key',''])}\r\n     else if(seen.has(compare)){duplicates++;issues.push([name,j+2,`Duplicate of row ${seen.get(compare)}`,key])}\r\n     else{seen.set(compare,j+2);valid.push(row)}\r\n    });\r\n    if($('valValid').checked)XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet(valid),(`Valid ${name}`).slice(0,31));\r\n    progress(((i+1)\/wb.SheetNames.length)*92,`Validating ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet(issues),'Validation Issues');\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Metric','Count'],['Missing Keys',missing],['Duplicate Keys',duplicates],['Total Issues',missing+duplicates]]),'Summary');\r\n   $('dces-fast-kpis').innerHTML=`<div class=\"dces-fast-kpis\"><div class=\"dces-fast-kpi\"><b>${missing}<\/b><small>Missing keys<\/small><\/div><div class=\"dces-fast-kpi\"><b>${duplicates}<\/b><small>Duplicate keys<\/small><\/div><div class=\"dces-fast-kpi\"><b>${missing+duplicates}<\/b><small>Total issues<\/small><\/div><div class=\"dces-fast-kpi\"><b>${wb.SheetNames.length}<\/b><small>Sheets checked<\/small><\/div><\/div>`;\r\n   setResult(workbookBlob(out),'key-validation-report.xlsx');\r\n  }\r\n\r\n  if(t==='split'){\r\n   const wb=state.books[0],zip=new JSZip();\r\n   for(let i=0;i<wb.SheetNames.length;i++){\r\n    const name=wb.SheetNames[i],one=XLSX.utils.book_new();\r\n    XLSX.utils.book_append_sheet(one,wb.Sheets[name],name.slice(0,31));\r\n    zip.file(safeName(name)+'.xlsx',XLSX.write(one,{bookType:'xlsx',type:'array',compression:true}));\r\n    progress(((i+1)\/wb.SheetNames.length)*90,`Preparing ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   setResult(await zip.generateAsync({type:'blob',compression:'DEFLATE',compressionOptions:{level:3}}),'split-worksheets.zip');\r\n  }\r\n\r\n  if(t==='profile'){\r\n   const rows=firstSheet(state.books[0])[1];if(!rows.length)throw Error('No data found.');\r\n   const headers=rows[0],data=rows.slice(1),seen=new Set();let duplicateRows=0;\r\n   data.forEach(r=>{const k=JSON.stringify(r);seen.has(k)?duplicateRows++:seen.add(k)});\r\n   const stats=headers.map((h,c)=>{let blanks=0,numeric=0,unique=new Set();data.forEach(r=>{const v=r[c];if(v===''||v==null)blanks++;else{unique.add(String(v));if(!isNaN(Number(v)))numeric++}});return[h||`Column ${c+1}`,data.length,blanks,unique.size,numeric]});\r\n   const out=XLSX.utils.book_new();\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Column','Rows','Blank Cells','Unique Values','Numeric Values'],...stats]),'Data Profile');\r\n   XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet([['Metric','Value'],['Total Rows',data.length],['Total Columns',headers.length],['Duplicate Rows',duplicateRows],['Blank Cells',stats.reduce((s,x)=>s+x[2],0)]]),'Summary');\r\n   setResult(workbookBlob(out),'data-quality-profile.xlsx');\r\n  }\r\n\r\n  if(t==='format'){\r\n   const column=$('fmtColumn').value.trim(),type=$('fmtType').value;if(!column)throw Error('Enter a column name.');\r\n   const wb=state.books[0],out=XLSX.utils.book_new();let found=false;\r\n   for(let i=0;i<wb.SheetNames.length;i++){\r\n    const name=wb.SheetNames[i],rows=rowsOf(wb,name),idx=rows[0]?.findIndex(x=>String(x).trim().toLowerCase()===column.toLowerCase());\r\n    if(idx>=0){found=true;rows.slice(1).forEach(row=>{let v=row[idx];\r\n      if(type==='upper')v=String(v).toUpperCase();\r\n      if(type==='lower')v=String(v).toLowerCase();\r\n      if(type==='title')v=String(v).toLowerCase().replace(\/\\b\\w\/g,x=>x.toUpperCase());\r\n      if(type==='date'){const d=v instanceof Date?v:new Date(v);if(!isNaN(d))v=`${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()}`}\r\n      if(type==='phone')v=String(v).replace(\/\\D\/g,'').slice(-10);\r\n      if(type==='number')v=v===''?'':Number(String(v).replace(\/,\/g,''));\r\n      row[idx]=v;\r\n    })}\r\n    XLSX.utils.book_append_sheet(out,XLSX.utils.aoa_to_sheet(rows),name.slice(0,31));\r\n    progress(((i+1)\/wb.SheetNames.length)*93,`Formatting ${name}`);await new Promise(r=>setTimeout(r,0));\r\n   }\r\n   if(!found)throw Error('Column not found.');\r\n   setResult(workbookBlob(out),'formatted-data.xlsx');\r\n  }\r\n\r\n  if(t==='convert'){\r\n   const fmt=$('outFormat').value,wb=state.books[0],rows=firstSheet(wb)[1];\r\n   if(fmt==='xlsx')setResult(workbookBlob(wb),'converted.xlsx');\r\n   if(fmt==='csv')setResult(new Blob([XLSX.utils.sheet_to_csv(XLSX.utils.aoa_to_sheet(rows))],{type:'text\/csv;charset=utf-8'}),'converted.csv');\r\n   if(fmt==='json')setResult(new Blob([JSON.stringify(XLSX.utils.sheet_to_json(XLSX.utils.aoa_to_sheet(rows),{defval:''}),null,2)],{type:'application\/json'}),'converted.json');\r\n  }\r\n\r\n  progress(100,'Completed');setTimeout(hideProgress,650);\r\n }catch(e){hideProgress();showError(e.message||'Processing failed.')}\r\n finally{renderFiles()}\r\n}\r\n\r\n$('dces-fast-tools').onclick=e=>{\r\n const card=e.target.closest('.dces-fast-card');if(!card)return;\r\n state.tool=card.dataset.tool;\r\n document.querySelectorAll('#dces-fast-app .dces-fast-card').forEach(x=>x.classList.toggle('active',x===card));\r\n reset();$('dces-fast-title').scrollIntoView({behavior:'smooth'});\r\n};\r\n$('dces-fast-search').oninput=()=>{\r\n const q=$('dces-fast-search').value.toLowerCase().trim();\r\n document.querySelectorAll('#dces-fast-app .dces-fast-card').forEach(c=>c.classList.toggle('hidden',q&&!c.dataset.search.includes(q)&&!c.textContent.toLowerCase().includes(q)));\r\n};\r\n$('dces-fast-upload').onclick=()=>$('dces-fast-input').click();\r\n$('dces-fast-input').onchange=()=>addFiles($('dces-fast-input').files);\r\n['dragenter','dragover'].forEach(type=>$('dces-fast-upload').addEventListener(type,e=>{e.preventDefault();$('dces-fast-upload').classList.add('drag')}));\r\n['dragleave','drop'].forEach(type=>$('dces-fast-upload').addEventListener(type,e=>{e.preventDefault();$('dces-fast-upload').classList.remove('drag')}));\r\n$('dces-fast-upload').ondrop=e=>addFiles(e.dataTransfer.files);\r\n$('dces-fast-process').onclick=processTool;\r\n$('dces-fast-reset').onclick=reset;\r\n$('dces-fast-theme').onclick=()=>{\r\n app.classList.toggle('dark');\r\n localStorage.setItem('dces-fast-theme',app.classList.contains('dark')?'dark':'light');\r\n};\r\nif(localStorage.getItem('dces-fast-theme')==='dark'||(!localStorage.getItem('dces-fast-theme')&&matchMedia('(prefers-color-scheme:dark)').matches))app.classList.add('dark');\r\nconfigure();\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>XL Data Cleaning &#038; Excel Studio Fast browser-based Excel cleaning and consolidation \u25d0 FAST \u2022 PRIVATE \u2022 NO UPLOAD Clean, Consolidate and Validate Excel Data Optimized for quick processing of office workbooks without repeated headers or unnecessary browser load. \ud83e\uddf9Clean Excel DataRemove duplicates, blanks and extra spaces \ud83d\udcdaConsolidate WorkbooksAppend same-format files with one header \ud83d\udcd1Consolidate [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-699","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/pages\/699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/comments?post=699"}],"version-history":[{"count":10,"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/pages\/699\/revisions"}],"predecessor-version":[{"id":711,"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/pages\/699\/revisions\/711"}],"wp:attachment":[{"href":"https:\/\/vikassrivastava.in\/academy\/wp-json\/wp\/v2\/media?parent=699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}