'', 'rows' => [], 'columns' => [], 'template_id' => 0, 'filename' => '', 'apply_routine' => false]; try { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['excel_file'])) { $template_id = isset($_POST['template_id']) ? intval($_POST['template_id']) : 0; $header_row = isset($_POST['header_row']) ? intval($_POST['header_row']) : 1; $start_column = isset($_POST['start_column']) ? intval($_POST['start_column']) : 1; // Debug del template_id ricevuto error_log("Received template_id from POST: " . print_r($_POST['template_id'], true)); error_log("Converted template_id: $template_id"); $file = $_FILES['excel_file']; $fileError = $file['error']; if ($fileError === UPLOAD_ERR_OK) { // Recupera l'ID dell'utente loggato if (!isset($iduserlogin)) { $iduserlogin = 1; error_log("Warning: iduserlogin non definito, usando 1 come default"); } // Genera il nome del file rinominato $timestamp = date('YmdHis'); $originalFilename = basename($file['name']); $newFilename = "{$iduserlogin}-{$timestamp}-{$originalFilename}"; $importFolder = __DIR__ . '/imported_trf/'; if (!file_exists($importFolder)) { mkdir($importFolder, 0777, true); } $destination = $importFolder . $newFilename; // Sposta il file if (!move_uploaded_file($file['tmp_name'], $destination)) { throw new Exception("Errore durante lo spostamento del file in $destination"); } error_log("File spostato con successo in: $destination"); // Connessione al database $db = DBHandlerSelect::getInstance(); $pdo = $db->getConnection(); // Recupera il mapping da template_mapping $stmt = $pdo->prepare("SELECT field_id AS excel_column, field_id AS mysql_column, data_type, is_required, default_value, is_manual FROM template_mapping WHERE template_id = ?"); $stmt->execute([$template_id]); $mappings = $stmt->fetchAll(PDO::FETCH_ASSOC); // Also fetch excel_column labels for auto-detect $stmtLabels = $pdo->prepare("SELECT excel_column FROM template_mapping WHERE template_id = ? AND is_manual = 0 AND excel_column IS NOT NULL AND excel_column != ''"); $stmtLabels->execute([$template_id]); $templateLabels = array_map('trim', array_map('mb_strtolower', $stmtLabels->fetchAll(PDO::FETCH_COLUMN))); // Debug dei mapping error_log("Mappings found for template_id $template_id: " . print_r($mappings, true)); if (empty($mappings)) { $response['error'] = "Nessun mapping trovato per il template con ID $template_id"; } else { // Carica il file rinominato con PHPSpreadsheet $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($destination); $worksheet = $spreadsheet->getActiveSheet(); $highestRow = $worksheet->getHighestRow(); $highestColumn = $worksheet->getHighestColumn(); $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn); // ── Auto-detect header row and start column ── // Scan all rows/columns to find the best match against template excel_column labels if (!empty($templateLabels)) { $bestRow = max(1, $header_row); $bestCol = max(1, $start_column); $bestScore = 0; $scanLimit = min($highestRow, 50); for ($scanRow = 1; $scanRow <= $scanLimit; $scanRow++) { $score = 0; $firstMatchCol = $highestColumnIndex + 1; for ($col = 1; $col <= $highestColumnIndex; $col++) { $colLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col); $cellVal = $worksheet->getCell($colLetter . $scanRow)->getCalculatedValue(); $cellVal = mb_strtolower(trim((string)$cellVal)); if ($cellVal !== '' && in_array($cellVal, $templateLabels, true)) { $score++; if ($col < $firstMatchCol) $firstMatchCol = $col; } } if ($score > $bestScore) { $bestScore = $score; $bestRow = $scanRow; $bestCol = $firstMatchCol; } } $header_row = $bestRow; $start_column = $bestCol; error_log("Auto-detected header row: $header_row, start column: $start_column (score: $bestScore/" . count($templateLabels) . ")"); $response['auto_header_row'] = $header_row; $response['auto_header_score'] = $bestScore; $response['auto_header_total'] = count($templateLabels); } $startRow = max(1, $header_row); $startColumn = max(1, $start_column); // Debug dei parametri error_log("Processing - template_id: $template_id, startRow: $startRow, startColumn: $startColumn, highestRow: $highestRow, highestColumn: $highestColumn, highestColumnIndex: $highestColumnIndex"); // Validazione degli indici if ($startRow > $highestRow) { $response['error'] = "La riga di partenza ($startRow) supera il numero totale di righe ($highestRow)."; } elseif ($startColumn > $highestColumnIndex) { $response['error'] = "La colonna di partenza ($startColumn) supera il numero totale di colonne ($highestColumnIndex)."; } else { $excelData = []; // Estrai la riga degli header $headerRowData = []; for ($col = $startColumn; $col <= $highestColumnIndex; $col++) { $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col); $cell = $worksheet->getCell($columnLetter . $header_row); $cellValue = $cell ? $cell->getCalculatedValue() : ''; $headerRowData[] = $cellValue ?: ''; } // Find which header columns are non-empty (these are the "real" columns) $headerFilledIndices = []; foreach ($headerRowData as $idx => $hVal) { if (trim((string)$hVal) !== '') $headerFilledIndices[] = $idx; } // Require at least 2 filled header-columns (or 1 if only 1 exists) $minFilled = max(1, min(2, count($headerFilledIndices))); // Estrai i dati a partire dalla riga successiva, includendo excelrow for ($row = $startRow + 1; $row <= $highestRow; $row++) { $rowData = []; for ($col = $startColumn; $col <= $highestColumnIndex; $col++) { $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col); $cell = $worksheet->getCell($columnLetter . $row); $cellValue = $cell ? $cell->getCalculatedValue() : ''; $rowData[] = $cellValue ?: ''; } // Count how many "header columns" have data in this row $filledCount = 0; foreach ($headerFilledIndices as $idx) { if (isset($rowData[$idx]) && trim((string)$rowData[$idx]) !== '') { $filledCount++; } } if ($filledCount >= $minFilled) { $excelData[] = ['data' => $rowData, 'excelrow' => $row]; } } // Recupera routine dal template $stmt = $pdo->prepare("SELECT idroutine, idclient FROM excel_templates WHERE id = ?"); $stmt->execute([$template_id]); $template = $stmt->fetch(PDO::FETCH_ASSOC); if ($template && $template['idroutine']) { $stmtRoutine = $pdo->prepare("SELECT idroutine, name, filename, headerrow, instruction FROM routine WHERE idroutine = ?"); $stmtRoutine->execute([$template['idroutine']]); $routineData = $stmtRoutine->fetch(PDO::FETCH_ASSOC); if ($routineData) { $response['apply_routine'] = true; $response['routine_data'] = [ 'name' => $routineData['name'] ?? 'Routine Sconosciuta', 'instruction' => $routineData['instruction'] ?? 'Nessuna descrizione disponibile', 'filename' => $routineData['filename'] ?? '', 'headerrow' => $routineData['headerrow'] ?? $header_row ]; error_log("Routine rilevata per template {$template_id}: " . print_r($routineData, true)); } else { error_log("Errore: Nessuna routine trovata per idroutine {$template['idroutine']}"); } } else { error_log("Nessuna routine associata al template {$template_id}"); } // Aggiungi idclient alla risposta $response['idclient'] = $template['idclient'] ?? null; // Salva i dati in sessione $_SESSION['excel_data'] = $excelData; $_SESSION['template_id'] = $template_id; $_SESSION['headers'] = $headerRowData; $_SESSION['mappings'] = $mappings; // Includi excel_data nella risposta JSON in ogni caso $response['excel_data'] = $excelData; $response['rows'] = array_column($excelData, 'data'); $response['columns'] = $headerRowData; $response['template_id'] = $template_id; $response['filename'] = $newFilename; } } } else { $response['error'] = "Errore nell'upload del file: Codice errore $fileError."; } } else { $response['error'] = "Richiesta non valida."; } } catch (Exception $e) { $response['error'] = "Errore durante il caricamento del file: " . $e->getMessage(); error_log("Exception in process_import_xls2.php: " . $e->getMessage()); } // Pulisce qualsiasi output indesiderato ob_end_clean(); // Invia la risposta JSON header('Content-Type: application/json'); echo json_encode($response); exit;