change template and import o use also sheet number of XLS
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user