-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
155 lines (135 loc) · 6.26 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
document.addEventListener('DOMContentLoaded', () => {
const uploadForm = document.getElementById('uploadForm');
const previewSection = document.getElementById('previewSection');
const mappingSection = document.getElementById('mappingSection');
const mappingForm = document.getElementById('mappingForm');
const downloadSection = document.getElementById('downloadSection');
const generateBtn = document.getElementById('generateBtn');
let dataContent = '';
let templateHeaders = [];
let dataHeaders = [];
uploadForm.addEventListener('submit', async (e) => {
e.preventDefault();
const dataFile = document.getElementById('dataFile').files[0];
const templateFile = document.getElementById('templateFile').files[0];
if (!dataFile || !templateFile) {
alert('Please select both CSV files.');
return;
}
const dataCSV = await readCSV(dataFile);
const templateCSV = await readCSV(templateFile);
displayPreview(dataCSV, templateCSV);
createMappingForm(dataCSV[0], templateCSV[0]);
previewSection.classList.remove('hidden');
mappingSection.classList.remove('hidden');
downloadSection.classList.remove('hidden');
dataContent = dataCSV.slice(1).map(row => row.join(',')).join('\n');
templateHeaders = templateCSV[0];
dataHeaders = dataCSV[0];
});
async function readCSV(file) {
const content = await file.text();
return content.split('\n').map(row => row.split(',').map(cell => cell.trim()));
}
function displayPreview(dataCSV, templateCSV) {
const dataPreview = document.getElementById('dataPreview');
const templatePreview = document.getElementById('templatePreview');
dataPreview.innerHTML = createTable(dataCSV[0], dataCSV.slice(1, 6));
templatePreview.innerHTML = createTable(templateCSV[0], templateCSV.slice(1, 6));
}
function createTable(headers, rows) {
let table = '<table class="min-w-full divide-y divide-gray-200"><thead><tr>';
headers.forEach(header => {
table += `<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">${header}</th>`;
});
table += '</tr></thead><tbody>';
rows.forEach((row, index) => {
table += `<tr class="${index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}">`;
row.forEach(cell => {
table += `<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${cell}</td>`;
});
table += '</tr>';
});
table += '</tbody></table>';
return table;
}
function createMappingForm(dataHeaders, templateHeaders) {
mappingForm.innerHTML = '';
templateHeaders.forEach(templateHeader => {
const div = document.createElement('div');
div.className = 'mb-4';
div.innerHTML = `
<label for="${templateHeader}" class="block mb-2 font-bold">${templateHeader}:</label>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="${templateHeader}_field" class="block mb-1">Field:</label>
<select id="${templateHeader}_field" name="${templateHeader}_field" class="block w-full mt-1 rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">-- Select --</option>
${dataHeaders.map(dataHeader => `<option value="${dataHeader}">${dataHeader}</option>`).join('')}
</select>
</div>
<div>
<label for="${templateHeader}_format" class="block mb-1">
<input type="checkbox" id="${templateHeader}_format" name="${templateHeader}_format" class="mr-2">
Format as decimal (up to 2 places)
</label>
</div>
</div>
`;
mappingForm.appendChild(div);
});
}
generateBtn.addEventListener('click', () => {
const mapping = {};
const formData = new FormData(mappingForm);
templateHeaders.forEach(header => {
const field = formData.get(`${header}_field`);
const format = formData.get(`${header}_format`) === 'on';
if (field) {
mapping[header] = {
field: field,
format: format
};
}
});
const mappedCSV = generateMappedCSV(mapping, dataContent, templateHeaders, dataHeaders);
downloadCSV(mappedCSV, 'mapped_data.csv');
});
function generateMappedCSV(mapping, dataContent, templateHeaders, dataHeaders) {
const dataRows = dataContent.split('\n').map(row => row.split(','));
const output = [templateHeaders];
dataRows.forEach(row => {
const mappedRow = templateHeaders.map(header => {
if (header in mapping) {
const mapInfo = mapping[header];
const dataIndex = dataHeaders.indexOf(mapInfo.field);
let value = row[dataIndex] || '';
if (mapInfo.format) {
value = formatDecimal(value);
}
return value;
}
return '';
});
output.push(mappedRow);
});
return output.map(row => row.join(',')).join('\n');
}
function formatDecimal(value) {
const num = parseFloat(value);
return isNaN(num) ? value : num.toFixed(2);
}
function downloadCSV(content, fileName) {
const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
if (link.download !== undefined) {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', fileName);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
});