let workbook = null; let processedSheets = {}; document.addEventListener('DOMContentLoaded', () => { const fileInput = document.getElementById('fileInput'); const loadBtn = document.getElementById('loadBtn'); const updateBtn = document.getElementById('updateBtn'); const generateReportBtn = document.getElementById('generateReportBtn'); const exportExcelBtn = document.getElementById('exportExcelBtn'); const exportCSVBtn = document.getElementById('exportCSVBtn'); const inputFields = document.getElementById('inputFields'); const reportContainer = document.getElementById('reportContainer'); // Load Excel file fileInput.addEventListener('change', (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { const data = new Uint8Array(e.target.result); workbook = XLSX.read(data, { type: 'array' }); loadBtn.disabled = false; }; reader.readAsArrayBuffer(file); }); // Process Excel file loadBtn.addEventListener('click', () => { if (!workbook) return; try { // Process each sheet workbook.SheetNames.forEach(sheetName => { const worksheet = workbook.Sheets[sheetName]; const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); processedSheets[sheetName] = { data: jsonData, formulas: detectFormulas(worksheet), editableCells: detectEditableCells(jsonData, worksheet) }; }); // Generate input fields for editable cells generateInputFields(); // Enable buttons updateBtn.disabled = false; generateReportBtn.disabled = false; exportExcelBtn.disabled = false; exportCSVBtn.disabled = false; // Show success message showToast('Planilha processada com sucesso!', 'success'); } catch (error) { console.error('Error processing workbook:', error); showToast('Erro ao processar a planilha', 'error'); } }); // Update values updateBtn.addEventListener('click', () => { if (!workbook) return; try { // Update values in processedSheets updateWorkbookValues(); // Recalculate formulas recalculateFormulas(); // Generate reports generateReports(); showToast('Valores atualizados com sucesso!', 'success'); } catch (error) { console.error('Error updating values:', error); showToast('Erro ao atualizar valores', 'error'); } }); // Generate reports generateReportBtn.addEventListener('click', () => { generateReports(); showToast('Relatório gerado com sucesso!', 'success'); }); // Export to Excel exportExcelBtn.addEventListener('click', () => { exportToExcel(); }); // Export to CSV exportCSVBtn.addEventListener('click', () => { exportToCSV(); }); // Helper functions function detectFormulas(worksheet) { const formulas = {}; for (const cell in worksheet) { if (cell[0] === '!') continue; if (worksheet[cell].f) { formulas[cell] = worksheet[cell].f; } } return formulas; } function detectEditableCells(jsonData, worksheet) { const editableCells = []; // Find cells without formulas and not empty for (let row = 0; row < jsonData.length; row++) { for (let col = 0; col < (jsonData[row]?.length || 0); col++) { const cellAddress = XLSX.utils.encode_cell({ r: row, c: col }); // Skip if cell has formula if (worksheet[cellAddress]?.f) continue; // Check if cell is a header (first row) if (row === 0) continue; // Consider cells with values (including empty strings) editableCells.push({ address: cellAddress, value: jsonData[row][col] || '', row, col, sheet: worksheet.name, header: jsonData[0][col] || `Coluna ${col+1}` }); } } return editableCells; } function generateInputFields() { inputFields.innerHTML = ''; // Group editable cells by sheet const sheetsWithEditableCells = {}; for (const sheetName in processedSheets) { if (processedSheets[sheetName].editableCells.length > 0) { sheetsWithEditableCells[sheetName] = processedSheets[sheetName].editableCells; } } // Create input fields for (const sheetName in sheetsWithEditableCells) { const sheetDiv = document.createElement('div'); sheetDiv.className = 'mb-6'; const sheetTitle = document.createElement('h3'); sheetTitle.className = 'text-lg font-medium text-gray-800 mb-2'; sheetTitle.textContent = `Planilha: ${sheetName}`; sheetDiv.appendChild(sheetTitle); const fieldsContainer = document.createElement('div'); fieldsContainer.className = 'space-y-3'; sheetsWithEditableCells[sheetName].forEach((cell, index) => { const groupDiv = document.createElement('div'); groupDiv.className = 'input-group'; const label = document.createElement('label'); label.htmlFor = `input-${sheetName}-${index}`; label.className = 'text-sm font-medium text-gray-700'; label.textContent = `${cell.header}:`; label.title = `Célula ${cell.address}`; let input; if (typeof cell.value === 'string' && cell.value.includes('|')) { // CSV-like input input = document.createElement('textarea'); input.id = `input-${sheetName}-${index}`; input.className = 'w-full'; input.rows = 3; input.dataset.type = 'csv'; input.value = cell.value; } else { // Regular input input = document.createElement('input'); input.id = `input-${sheetName}-${index}`; input.type = typeof cell.value === 'number' ? 'number' : 'text'; input.value = cell.value; } input.dataset.sheet = sheetName; input.dataset.address = cell.address; groupDiv.appendChild(label); groupDiv.appendChild(input); fieldsContainer.appendChild(groupDiv); }); sheetDiv.appendChild(fieldsContainer); inputFields.appendChild(sheetDiv); } if (inputFields.children.length === 0) { inputFields.innerHTML = '
Nenhum campo editável encontrado na planilha.
'; } } function updateWorkbookValues() { const inputs = inputFields.querySelectorAll('input, textarea'); inputs.forEach(input => { const sheetName = input.dataset.sheet; const cellAddress = input.dataset.address; const value = input.dataset.type === 'csv' ? input.value : input.type === 'number' ? Number(input.value) : input.value; // Update in processedSheets const sheet = processedSheets[sheetName]; const cellPos = XLSX.utils.decode_cell(cellAddress); // Ensure row exists while (sheet.data.length <= cellPos.r) { sheet.data.push([]); } // Ensure column exists in row while (sheet.data[cellPos.r].length <= cellPos.c) { sheet.data[cellPos.r].push(''); } sheet.data[cellPos.r][cellPos.c] = value; }); } function showDataInputModal(sheetName) { const modal = document.createElement('div'); modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50'; modal.innerHTML = `
Insira os dados no formato CSV, separados por | (pipe).
Exemplo: Valor1|Valor2|Valor3
Total de linhas: ${sheet.data.length-1}
Colunas: ${sheet.data[0].length}
Fórmulas: ${Object.keys(sheet.formulas).length}
Campos editáveis: ${sheet.editableCells.length}
`; reportDiv.appendChild(tableContainer); reportDiv.appendChild(stats); reportContainer.appendChild(reportDiv); } } function exportToExcel() { try { // Create a new workbook with updated data const newWorkbook = XLSX.utils.book_new(); for (const sheetName in processedSheets) { const sheet = processedSheets[sheetName]; const worksheet = XLSX.utils.aoa_to_sheet(sheet.data); // Reapply formulas (simplified - in real app would need proper handling) for (const cell in sheet.formulas) { if (worksheet[cell]) { worksheet[cell].f = sheet.formulas[cell]; } } XLSX.utils.book_append_sheet(newWorkbook, worksheet, sheetName); } // Export XLSX.writeFile(newWorkbook, 'athina_processed.xlsx'); showToast('Exportado para Excel com sucesso!', 'success'); } catch (error) { console.error('Error exporting to Excel:', error); showToast('Erro ao exportar para Excel', 'error'); } } function exportToCSV() { try { // For simplicity, we'll export the first sheet const firstSheetName = workbook.SheetNames[0]; const sheet = processedSheets[firstSheetName]; // Convert to CSV const csv = XLSX.utils.sheet_to_csv(XLSX.utils.aoa_to_sheet(sheet.data), { FS: '|' // Use | as delimiter }); // Download const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); saveAs(blob, 'athina_data.csv'); showToast('Exportado para CSV com sucesso!', 'success'); } catch (error) { console.error('Error exporting to CSV:', error); showToast('Erro ao exportar para CSV', 'error'); } } function showToast(message, type = 'info') { const toast = document.createElement('div'); toast.className = `fixed bottom-4 right-4 px-4 py-2 rounded-md shadow-lg text-white ${ type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : 'bg-blue-500' }`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.classList.add('opacity-0', 'transition', 'duration-300'); setTimeout(() => toast.remove(), 300); }, 3000); } });