diff --git a/public/userarea/import_xls2.php b/public/userarea/import_xls2.php
index ad7fe20..dcf3202 100644
--- a/public/userarea/import_xls2.php
+++ b/public/userarea/import_xls2.php
@@ -167,7 +167,12 @@ error_log("Loaded template: " . print_r($template, true));
= htmlspecialchars($template['name']) ?>
- Template ID: = $id ?>, Start Row: = $template['header_row'] ?>, Start Column: = $template['start_column'] ?>
+
+ Template ID: = $id ?>,
+ Sheet Number: = (int)($template['xls_sheet_index'] ?? 0) ?>,
+ Start Row: = $template['header_row'] ?>,
+ Start Column: = $template['start_column'] ?>
+
@@ -244,8 +249,9 @@ error_log("Loaded template: " . print_r($template, true));
const templateId = = $id ?>;
console.log('Template ID passed to formData:', templateId);
formData.append('template_id', templateId);
- formData.append('header_row', = $template['header_row'] ?>);
- formData.append('start_column', = $template['start_column'] ?>);
+ formData.append('header_row', = (int)$template['header_row'] ?>);
+ formData.append('start_column', = json_encode($template['start_column']) ?>);
+ formData.append('xls_sheet_index', = (int)($template['xls_sheet_index'] ?? 0) ?>);
fetch('process_import_xls2.php', {
method: 'POST',
diff --git a/public/userarea/mapping_template_xls_scheme2.php b/public/userarea/mapping_template_xls_scheme2.php
index a9f8d92..028e9b1 100644
--- a/public/userarea/mapping_template_xls_scheme2.php
+++ b/public/userarea/mapping_template_xls_scheme2.php
@@ -15,8 +15,9 @@ $stmt = $pdo->prepare("
start_column,
target_table,
source_type,
+ xls_sheet_index,
sample_xlsx,
- idclient,
+ idclient,
clientname,
idschema,
schemaname,
@@ -39,6 +40,14 @@ if (!in_array($sourceType, ['XLS', 'API', 'PDF'], true)) {
$sourceType = 'XLS';
}
+$xlsSheetIndex = isset($template['xls_sheet_index']) && $template['xls_sheet_index'] !== null
+ ? (int)$template['xls_sheet_index']
+ : 0;
+
+if ($xlsSheetIndex < 0) {
+ $xlsSheetIndex = 0;
+}
+
$clientName = $template['clientname'] ?: '';
$schemaName = $template['schemaname'] ?: '';
$schemajson = $template['schemajson'] ? json_decode($template['schemajson'], true) : [];
@@ -267,7 +276,8 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
Source:
|
- Header Row: |
+ Sheet Number: |
+ Header Row: |
Start Column:
@@ -656,7 +666,30 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
let workbook = XLSX.read(data, {
type: 'array'
});
- let sheet = workbook.Sheets[workbook.SheetNames[0]];
+
+ const selectedSheetIndex = ;
+
+ if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
+ alert("No sheets found in this XLS file.");
+ return;
+ }
+
+ if (!workbook.SheetNames[selectedSheetIndex]) {
+ alert(
+ "The selected sheet number " + selectedSheetIndex +
+ " does not exist in this XLS file. Available sheets: " +
+ workbook.SheetNames.map((name, index) => index + " = " + name).join(", ")
+ );
+ return;
+ }
+
+ const selectedSheetName = workbook.SheetNames[selectedSheetIndex];
+ let sheet = workbook.Sheets[selectedSheetName];
+
+ console.log("Selected XLS sheet:", {
+ index: selectedSheetIndex,
+ name: selectedSheetName
+ });
// Read sheet range to determine column offset
const sheetRange = XLSX.utils.decode_range(sheet['!ref'] || 'A1');
@@ -745,7 +778,8 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
const uniqueLabels = [...new Set(knownLabels)];
console.group('🔍 Auto-detect header row');
- console.log('Sheet name:', workbook.SheetNames[0]);
+ console.log('Sheet index:', selectedSheetIndex);
+ console.log('Sheet name:', selectedSheetName);
console.log('Total rows in sheet:', sheetData.length);
console.log('Labels from schema field titles:', knownLabels);
console.log('Unique labels to match against:', uniqueLabels);
@@ -884,8 +918,10 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
function saveXlsHeaders(headers, headerRow, startColumn) {
const payload = {
template_id: ,
- xls_headers: JSON.stringify(headers)
+ xls_headers: JSON.stringify(headers),
+ xls_sheet_index:
};
+
if (headerRow !== undefined) payload.header_row = headerRow;
if (startColumn !== undefined) payload.start_column = startColumn;
@@ -897,8 +933,18 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
body: JSON.stringify(payload)
}).then(response => response.json())
.then(data => {
- if (!data.success) console.error("❌ Error saving XLS headers:", data.message);
- else console.log("✅ Saved headers, header_row:", headerRow, "start_column:", startColumn);
+ if (!data.success) {
+ console.error("❌ Error saving XLS headers:", data.message);
+ } else {
+ console.log(
+ "✅ Saved headers, header_row:",
+ headerRow,
+ "start_column:",
+ startColumn,
+ "xls_sheet_index:",
+
+ );
+ }
})
.catch(error => console.error("❌ Fetch error:", error));
}
diff --git a/public/userarea/process_import_xls2.php b/public/userarea/process_import_xls2.php
index afd0cf0..407ea08 100644
--- a/public/userarea/process_import_xls2.php
+++ b/public/userarea/process_import_xls2.php
@@ -11,17 +11,105 @@ session_start();
require_once '../../vendor/autoload.php';
require_once __DIR__ . '/class/db-functions.php';
-$response = ['error' => '', 'rows' => [], 'columns' => [], 'template_id' => 0, 'filename' => '', 'apply_routine' => false];
+use PhpOffice\PhpSpreadsheet\IOFactory;
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
+
+$response = [
+ 'error' => '',
+ 'rows' => [],
+ 'columns' => [],
+ 'template_id' => 0,
+ 'filename' => '',
+ 'apply_routine' => false
+];
+
+/**
+ * Converts a column value to a PhpSpreadsheet 1-based column index.
+ * Accepted values:
+ * - "A" => 1
+ * - "B" => 2
+ * - "AA" => 27
+ * - "1" => 1
+ * - 1 => 1
+ */
+function normalizeColumnIndex($value): int
+{
+ $value = trim((string)$value);
+
+ if ($value === '') {
+ return 1;
+ }
+
+ if (ctype_digit($value)) {
+ return max(1, (int)$value);
+ }
+
+ $value = strtoupper($value);
+
+ if (preg_match('/^[A-Z]+$/', $value)) {
+ return Coordinate::columnIndexFromString($value);
+ }
+
+ return 1;
+}
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;
+
+ if ($template_id <= 0) {
+ throw new Exception("Template ID non valido.");
+ }
+
+ // Connessione al database
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ /*
+ * Recuperiamo i parametri direttamente dal template.
+ * Così non dipendiamo solo dal form e siamo sicuri di usare i dati salvati.
+ */
+ $stmt = $pdo->prepare("
+ SELECT
+ id,
+ header_row,
+ start_column,
+ xls_sheet_index,
+ idroutine,
+ idclient
+ FROM excel_templates
+ WHERE id = ?
+ ");
+ $stmt->execute([$template_id]);
+ $template = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$template) {
+ throw new Exception("Template non trovato.");
+ }
+
+ $header_row = isset($template['header_row']) && $template['header_row'] !== null
+ ? (int)$template['header_row']
+ : 1;
+
+ $start_column_raw = $template['start_column'] ?? 'A';
+ $start_column = normalizeColumnIndex($start_column_raw);
+
+ $xlsSheetIndex = isset($template['xls_sheet_index']) && $template['xls_sheet_index'] !== null
+ ? (int)$template['xls_sheet_index']
+ : 0;
+
+ if ($header_row <= 0) {
+ $header_row = 1;
+ }
+
+ if ($xlsSheetIndex < 0) {
+ $xlsSheetIndex = 0;
+ }
// 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");
+ error_log("Template XLS settings - header_row: $header_row, start_column_raw: $start_column_raw, start_column_index: $start_column, xls_sheet_index: $xlsSheetIndex");
$file = $_FILES['excel_file'];
$fileError = $file['error'];
@@ -38,23 +126,32 @@ try {
$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 = $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);
@@ -65,19 +162,45 @@ try {
$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();
+ $spreadsheet = IOFactory::load($destination);
+
+ $sheetCount = $spreadsheet->getSheetCount();
+ $sheetNames = $spreadsheet->getSheetNames();
+
+ if ($sheetCount <= 0) {
+ throw new Exception("Il file XLS non contiene fogli.");
+ }
+
+ if ($xlsSheetIndex >= $sheetCount) {
+ throw new Exception(
+ "Il foglio XLS selezionato non esiste. " .
+ "Sheet Number selezionato: {$xlsSheetIndex}. " .
+ "Fogli disponibili: " . implode(", ", array_map(
+ fn($name, $index) => "{$index}={$name}",
+ $sheetNames,
+ array_keys($sheetNames)
+ ))
+ );
+ }
+
+ // Usa il foglio configurato nel template
+ $worksheet = $spreadsheet->getSheet($xlsSheetIndex);
+ $selectedSheetName = $worksheet->getTitle();
+
+ error_log("Selected XLS sheet - index: {$xlsSheetIndex}, name: {$selectedSheetName}");
+
$highestRow = $worksheet->getHighestRow();
$highestColumn = $worksheet->getHighestColumn();
- $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
+ $highestColumnIndex = Coordinate::columnIndexFromString($highestColumn);
$startRow = max(1, $header_row);
$startColumn = max(1, $start_column);
- // Advance startColumn to first non-empty cell in header row (match JS behavior)
+ // Advance startColumn to first non-empty cell in header row, matching JS behavior
for ($sc = $startColumn; $sc <= $highestColumnIndex; $sc++) {
- $cl = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($sc);
+ $cl = Coordinate::stringFromColumnIndex($sc);
$cv = trim((string)($worksheet->getCell($cl . $header_row)->getCalculatedValue() ?? ''));
+
if ($cv !== '') {
$startColumn = $sc;
break;
@@ -85,24 +208,32 @@ try {
}
// Debug dei parametri
- error_log("Processing - template_id: $template_id, startRow: $startRow, startColumn: $startColumn, highestRow: $highestRow, highestColumn: $highestColumn, highestColumnIndex: $highestColumnIndex");
+ error_log(
+ "Processing - template_id: $template_id, " .
+ "sheetIndex: $xlsSheetIndex, sheetName: $selectedSheetName, " .
+ "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).";
+ $response['error'] = "La riga di partenza ($startRow) supera il numero totale di righe ($highestRow) del foglio '$selectedSheetName'.";
} elseif ($startColumn > $highestColumnIndex) {
- $response['error'] = "La colonna di partenza ($startColumn) supera il numero totale di colonne ($highestColumnIndex).";
+ $response['error'] = "La colonna di partenza ($startColumn) supera il numero totale di colonne ($highestColumnIndex) del foglio '$selectedSheetName'.";
} else {
$excelData = [];
// Build merge map for header row: physCol -> mergeStartCol
$mergeStartMap = [];
+
foreach ($worksheet->getMergeCells() as $range) {
[$startCell, $endCell] = explode(':', $range);
- $mStartCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString(preg_replace('/\d+/', '', $startCell));
- $mEndCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString(preg_replace('/\d+/', '', $endCell));
+
+ $mStartCol = Coordinate::columnIndexFromString(preg_replace('/\d+/', '', $startCell));
+ $mEndCol = Coordinate::columnIndexFromString(preg_replace('/\d+/', '', $endCell));
$mStartRow = (int)preg_replace('/[A-Z]+/i', '', $startCell);
$mEndRow = (int)preg_replace('/[A-Z]+/i', '', $endCell);
+
if ($header_row >= $mStartRow && $header_row <= $mEndRow) {
for ($c = $mStartCol; $c <= $mEndCol; $c++) {
$mergeStartMap[$c] = $mStartCol;
@@ -111,12 +242,17 @@ try {
}
// Build logical columns: each merge = one column
- $logicalCols = []; // array of physical column indices (one per logical column)
+ $logicalCols = []; // array of physical column indices, one per logical column
$seen = [];
+
for ($col = $startColumn; $col <= $highestColumnIndex; $col++) {
if (isset($mergeStartMap[$col])) {
$ms = $mergeStartMap[$col];
- if (in_array($ms, $seen, true)) continue;
+
+ if (in_array($ms, $seen, true)) {
+ continue;
+ }
+
$seen[] = $ms;
$logicalCols[] = $ms;
} else {
@@ -127,38 +263,48 @@ try {
// Build header row using logical columns
$headerRowData = [];
$logicalNum = 0;
+
foreach ($logicalCols as $physCol) {
$logicalNum++;
- $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($physCol);
+
+ $columnLetter = Coordinate::stringFromColumnIndex($physCol);
$cell = $worksheet->getCell($columnLetter . $header_row);
$cellValue = trim((string)($cell ? $cell->getCalculatedValue() : ''));
$cellValue = preg_replace('/[\r\n\t]+/', ' ', $cellValue);
+
// Empty headers get __empty_N__ to match mapping page
$headerRowData[] = ($cellValue !== '') ? $cellValue : '__empty_' . $logicalNum . '__';
}
error_log("Logical headers: " . json_encode($headerRowData));
- error_log("Logical cols (physical indices): " . json_encode($logicalCols));
+ error_log("Logical cols physical indices: " . json_encode($logicalCols));
// Find which logical columns have real headers
$headerFilledIndices = [];
+
foreach ($headerRowData as $idx => $hVal) {
- if (!str_starts_with($hVal, '__empty_')) $headerFilledIndices[] = $idx;
+ if (!str_starts_with($hVal, '__empty_')) {
+ $headerFilledIndices[] = $idx;
+ }
}
+
$minFilled = max(1, min(2, count($headerFilledIndices)));
// Extract data rows using logical columns
for ($row = $startRow + 1; $row <= $highestRow; $row++) {
$rowData = [];
+
foreach ($logicalCols as $physCol) {
- $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($physCol);
+ $columnLetter = Coordinate::stringFromColumnIndex($physCol);
$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++;
@@ -166,17 +312,25 @@ try {
}
if ($filledCount >= $minFilled) {
- $excelData[] = ['data' => $rowData, 'excelrow' => $row];
+ $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 = ?");
+ if ($template && !empty($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);
@@ -188,6 +342,7 @@ try {
'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']}");
@@ -204,6 +359,8 @@ try {
$_SESSION['template_id'] = $template_id;
$_SESSION['headers'] = $headerRowData;
$_SESSION['mappings'] = $mappings;
+ $_SESSION['xls_sheet_index'] = $xlsSheetIndex;
+ $_SESSION['xls_sheet_name'] = $selectedSheetName;
// Includi excel_data nella risposta JSON in ogni caso
$response['excel_data'] = $excelData;
@@ -211,6 +368,8 @@ try {
$response['columns'] = $headerRowData;
$response['template_id'] = $template_id;
$response['filename'] = $newFilename;
+ $response['xls_sheet_index'] = $xlsSheetIndex;
+ $response['xls_sheet_name'] = $selectedSheetName;
}
}
} else {
diff --git a/public/userarea/update_xls_headers.php b/public/userarea/update_xls_headers.php
index 752d9af..d4c8bba 100644
--- a/public/userarea/update_xls_headers.php
+++ b/public/userarea/update_xls_headers.php
@@ -6,22 +6,57 @@ error_reporting(E_ALL);
require_once(__DIR__ . '/class/db-functions.php');
-$db = DBHandlerSelect::getInstance();
-$pdo = $db->getConnection();
-
-$data = json_decode(file_get_contents("php://input"), true);
-
-if (!$data || !isset($data['template_id'], $data['xls_headers'])) {
- echo json_encode(["success" => false, "message" => "Invalid or missing data"]);
- exit;
-}
-
-$templateId = $data['template_id'];
-$xlsHeaders = $data['xls_headers'];
-$headerRow = isset($data['header_row']) ? (int)$data['header_row'] : null;
-$startColumn = isset($data['start_column']) ? (int)$data['start_column'] : null;
-
try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $data = json_decode(file_get_contents("php://input"), true);
+
+ if (!$data || !isset($data['template_id'], $data['xls_headers'])) {
+ echo json_encode(["success" => false, "message" => "Invalid or missing data"]);
+ exit;
+ }
+
+ $templateId = (int)$data['template_id'];
+ $xlsHeaders = $data['xls_headers'];
+
+ $headerRow = isset($data['header_row']) && $data['header_row'] !== ''
+ ? (int)$data['header_row']
+ : null;
+
+ $startColumn = isset($data['start_column']) && $data['start_column'] !== ''
+ ? (int)$data['start_column']
+ : null;
+
+ $xlsSheetIndex = isset($data['xls_sheet_index']) && $data['xls_sheet_index'] !== ''
+ ? (int)$data['xls_sheet_index']
+ : null;
+
+ if ($templateId <= 0) {
+ echo json_encode(["success" => false, "message" => "Invalid template ID"]);
+ exit;
+ }
+
+ if ($xlsHeaders === '') {
+ echo json_encode(["success" => false, "message" => "XLS headers cannot be empty"]);
+ exit;
+ }
+
+ if ($headerRow !== null && $headerRow <= 0) {
+ echo json_encode(["success" => false, "message" => "Header row must be greater than 0"]);
+ exit;
+ }
+
+ if ($startColumn !== null && $startColumn <= 0) {
+ echo json_encode(["success" => false, "message" => "Start column must be greater than 0"]);
+ exit;
+ }
+
+ if ($xlsSheetIndex !== null && $xlsSheetIndex < 0) {
+ echo json_encode(["success" => false, "message" => "XLS sheet number cannot be negative"]);
+ exit;
+ }
+
$sql = "UPDATE excel_templates SET xls_headers = ?";
$params = [$xlsHeaders];
@@ -29,11 +64,18 @@ try {
$sql .= ", header_row = ?";
$params[] = $headerRow;
}
+
if ($startColumn !== null) {
$sql .= ", start_column = ?";
$params[] = $startColumn;
}
+ if ($xlsSheetIndex !== null) {
+ $sql .= ", xls_sheet_index = ?";
+ $params[] = $xlsSheetIndex;
+ }
+
+ $sql .= ", updated_at = NOW()";
$sql .= " WHERE id = ?";
$params[] = $templateId;
@@ -45,8 +87,18 @@ try {
exit;
}
- echo json_encode(["success" => true, "message" => "XLS headers saved successfully"]);
+ echo json_encode([
+ "success" => true,
+ "message" => "XLS headers saved successfully",
+ "debug" => [
+ "template_id" => $templateId,
+ "header_row" => $headerRow,
+ "start_column" => $startColumn,
+ "xls_sheet_index" => $xlsSheetIndex
+ ]
+ ]);
} catch (Exception $e) {
echo json_encode(["success" => false, "message" => "Error: " . $e->getMessage()]);
}
+
exit;