From 0b9d5f5b406fab30d209a45856b50ab246bae582 Mon Sep 17 00:00:00 2001 From: solocla Date: Mon, 26 Oct 2026 13:56:01 +0100 Subject: [PATCH] fixed import foglio di lavoro --- public/userarea/import_worksheet_xlsx.php | 102 ++++++++++++++- public/userarea/manage-worksheet.php | 8 ++ public/userarea/ws_packaging_parser.php | 143 ++++++++++++++++++++++ 3 files changed, 250 insertions(+), 3 deletions(-) create mode 100644 public/userarea/ws_packaging_parser.php diff --git a/public/userarea/import_worksheet_xlsx.php b/public/userarea/import_worksheet_xlsx.php index 526b9b56..071a5d09 100644 --- a/public/userarea/import_worksheet_xlsx.php +++ b/public/userarea/import_worksheet_xlsx.php @@ -177,6 +177,97 @@ function dotdec_to_comma($v) return preg_replace('/(\d)\.(\d)/', '$1,$2', (string)$v); } +/* ---- sezione "Imballo e confezionamento" ---- */ + +/** primo numero intero della cella ("80", "160 m", "12 o 14" -> 12) */ +function first_int($v) +{ + if (is_int($v) || is_float($v)) return (int)round($v); + if (preg_match('/\d+(?:[.,]\d+)?/', (string)$v, $m)) return (int)round((float)str_replace(',', '.', $m[0])); + return null; +} + +/** la cella ha più numeri alternativi? ("12 o 14") */ +function has_multi_num($v) +{ + return preg_match_all('/\d+/', (string)$v) > 1; +} + +function is_tolerance_txt($v) +{ + $v = strtolower((string)$v); + return strpos($v, 'toll') !== false || preg_match('/[+-]\s*\d/', $v); +} + +function fmt_num($n) +{ + $f = (float)$n; + return (floor($f) == $f) ? (string)(int)$f : rtrim(rtrim(number_format($f, 2, '.', ''), '0'), '.'); +} + +/** "Toll Metrat. + 1,5m/-0" -> "-0/+1.5m" "+/- 4m" -> "+/- 4m" */ +function parse_tolerance($v) +{ + $s = str_replace(',', '.', (string)$v); + $num = '(\d+(?:\.\d+)?)'; + if (preg_match('/\+\s*\/\s*-\s*' . $num . '/', $s, $m) || preg_match('/±\s*' . $num . '/u', $s, $m)) { + return '+/- ' . fmt_num($m[1]) . 'm'; + } + $plus = preg_match('/\+\s*' . $num . '/', $s, $mp) ? fmt_num($mp[1]) : null; + $minus = preg_match('/-\s*' . $num . '/', $s, $mm) ? fmt_num($mm[1]) : null; + if ($plus !== null || $minus !== null) return '-' . ($minus ?? '0') . '/+' . ($plus ?? '0') . 'm'; + return trim((string)$v); // formato non riconosciuto: testo originale +} + +function extract_packaging($grid) +{ + $out = [ + 'meters_per_package' => null, + 'meters_per_package_tolerance' => '', + 'meters_per_package_notes' => '', + 'packages_or_pieces_per_box' => null, + 'meters_per_box' => null, + 'boxes_or_packages_per_pallet' => null, + ]; + $notes = []; + + // metri/confezione: valore in D, note in E, tolleranza in E o nelle righe sotto senza etichetta + $r = row_by_label($grid, 'metri/confezione'); + if ($r) { + $d = cell($grid, $r, 'D'); + $out['meters_per_package'] = first_int($d); + + $cand = [cell($grid, $r, 'E')]; + for ($i = $r + 1; $i <= $r + 3 && norm(cell($grid, $i, 'A')) === ''; $i++) { + $cand[] = cell($grid, $i, 'D'); + $cand[] = cell($grid, $i, 'E'); + } + if (is_tolerance_txt($d) && has_multi_num($d)) $cand[] = $d; // "80 +1,5/-0" nella stessa cella + foreach ($cand as $c) { + if ($c === '') continue; + if ($out['meters_per_package_tolerance'] === '' && is_tolerance_txt($c)) { + $out['meters_per_package_tolerance'] = parse_tolerance($c); + } elseif (!is_tolerance_txt($c)) { + $notes[] = $c; // es. "40x2" + } + } + } + + $v = val_at_label($grid, 'n confezioni o pezzi per scatola', 'D'); + $out['packages_or_pieces_per_box'] = first_int($v); + if (has_multi_num($v)) $notes[] = 'Conf. x scatola ' . $v; + + $out['meters_per_box'] = first_int(val_at_label($grid, 'metri/scatola', 'D')); + + // "12 o 14": nel campo numerico va 12, il testo completo nelle note + $v = val_at_label($grid, 'n confezioni o scatole per bancale', 'D'); + $out['boxes_or_packages_per_pallet'] = first_int($v); + if (has_multi_num($v)) $notes[] = 'Scatole x Bancale ' . $v; + + $out['meters_per_package_notes'] = implode('. ', array_unique($notes)); + return $out; +} + function extract_fields($grid) { $out = []; @@ -229,8 +320,8 @@ function extract_fields($grid) $out['pkg_scatola_raw'] = val_at_label($grid, 'tipo scatola', 'D'); $out['pkg_bancale_raw'] = val_at_label($grid, 'tipo di bancale', 'D'); - $out['packages_or_pieces_per_box'] = num_or_null(val_at_label($grid, 'n confezioni o pezzi per scatola', 'D')); - $out['boxes_or_packages_per_pallet'] = num_or_null(val_at_label($grid, 'n confezioni o scatole per bancale', 'D')); + // metri/confezione, tolleranza, note, pezzi per scatola, metri/scatola, scatole per bancale + $out = array_merge($out, extract_packaging($grid)); // velocità $out['speed_expected_kg_h'] = null; @@ -250,7 +341,8 @@ function extract_fields($grid) // note: annotazioni libere colonna E + righe istruzione in fondo $noteBits = []; - foreach (['confezione richiesta', 'metri/confezione', 'metri/scatola'] as $lbl) { + // (metri/confezione colonna E ora va in "Note metri/confezione") + foreach (['confezione richiesta', 'metri/scatola'] as $lbl) { $rr = row_by_label($grid, $lbl); if ($rr && cell($grid, $rr, 'E') !== '') $noteBits[] = cell($grid, $rr, 'E'); } @@ -523,6 +615,10 @@ try { 'profile_type_code' => $fields['profile_type_code'], 'marking' => $fields['marking'], 'prod_control_measure_settings' => $fields['prod_control_measure_settings'], + 'meters_per_package' => $fields['meters_per_package'], + 'meters_per_package_tolerance' => $fields['meters_per_package_tolerance'], + 'meters_per_package_notes' => $fields['meters_per_package_notes'], + 'meters_per_box' => $fields['meters_per_box'], 'packages_or_pieces_per_box' => $fields['packages_or_pieces_per_box'], 'boxes_or_packages_per_pallet' => $fields['boxes_or_packages_per_pallet'], 'speed_expected_kg_h' => $fields['speed_expected_kg_h'], diff --git a/public/userarea/manage-worksheet.php b/public/userarea/manage-worksheet.php index 1aec219c..48228802 100644 --- a/public/userarea/manage-worksheet.php +++ b/public/userarea/manage-worksheet.php @@ -2207,6 +2207,14 @@ $isEdit = ($worksheet_id > 0); setVal('profile_type_code', h.profile_type_code); setVal('marking', h.marking); setVal('prod_control_measure_settings', h.prod_control_measure_settings); + setVal('meters_per_package', h.meters_per_package); + setVal('meters_per_package_tolerance', h.meters_per_package_tolerance); + setVal('meters_per_package_notes', h.meters_per_package_notes); + setVal('meters_per_box', h.meters_per_box); + setVal('meters_per_package', h.meters_per_package); + setVal('meters_per_package_tolerance', h.meters_per_package_tolerance); + setVal('meters_per_package_notes', h.meters_per_package_notes); + setVal('meters_per_box', h.meters_per_box); setVal('packages_or_pieces_per_box', h.packages_or_pieces_per_box); setVal('boxes_or_packages_per_pallet', h.boxes_or_packages_per_pallet); setVal('speed_expected_kg_h', h.speed_expected_kg_h); diff --git a/public/userarea/ws_packaging_parser.php b/public/userarea/ws_packaging_parser.php new file mode 100644 index 00000000..a4db1cc6 --- /dev/null +++ b/public/userarea/ws_packaging_parser.php @@ -0,0 +1,143 @@ +toArray(null, true, false, false)). + * Restituisce solo le chiavi trovate: + * meters_per_package, meters_per_package_tolerance, meters_per_package_notes, + * packages_or_pieces_per_box, meters_per_box, boxes_or_packages_per_pallet + */ +function ws_parse_packaging(array $rows): array +{ + $out = []; + $notes = []; + + // indicizza le righe: etichetta (colonne A-C) + valori (dalla colonna D) + $list = []; + foreach ($rows as $r) { + $r = array_values((array)$r); + $label = ws_pk_norm(implode(' ', array_map('strval', array_slice($r, 0, 3)))); + $vals = []; + foreach (array_slice($r, 3) as $v) { + $v = trim((string)$v); + if ($v !== '') $vals[] = $v; + } + $list[] = ['label' => $label, 'vals' => $vals]; + } + + $n = count($list); + for ($i = 0; $i < $n; $i++) { + $label = $list[$i]['label']; + $vals = $list[$i]['vals']; + if ($label === '') continue; + + // righe successive senza etichetta (continuazione: tolleranze, note) + $extra = []; + for ($j = $i + 1; $j < $n && $list[$j]['label'] === ''; $j++) { + $extra = array_merge($extra, $list[$j]['vals']); + } + + // --- metri / confezione --- + if (preg_match('/^metri\s*\/?\s*confezion/', $label)) { + $first = $vals[0] ?? ''; + $num = ws_pk_int($first); + if ($num !== null) $out['meters_per_package'] = $num; + + $tol = null; + foreach (array_merge(array_slice($vals, 1), $extra) as $v) { + if ($tol === null && ws_pk_is_tolerance($v)) { + $tol = ws_pk_tolerance($v); + } elseif (!ws_pk_is_tolerance($v)) { + $notes[] = $v; // es. "40x2" + } + } + // la tolleranza a volte è nella stessa cella del valore + if ($tol === null && ws_pk_is_tolerance($first)) $tol = ws_pk_tolerance($first); + if ($tol !== null) $out['meters_per_package_tolerance'] = $tol; + continue; + } + + // --- n° confezioni o pezzi per scatola --- + if (strpos($label, 'per scatola') !== false && strpos($label, 'confezion') !== false) { + $num = ws_pk_int($vals[0] ?? ''); + if ($num !== null) $out['packages_or_pieces_per_box'] = $num; + if (ws_pk_multi($vals[0] ?? '')) $notes[] = 'Conf. x scatola ' . $vals[0]; + continue; + } + + // --- metri / scatola --- + if (preg_match('/^metri\s*\/?\s*scatol/', $label)) { + $num = ws_pk_int($vals[0] ?? ''); + if ($num !== null) $out['meters_per_box'] = $num; + continue; + } + + // --- n° confezioni o scatole per bancale --- + if (strpos($label, 'bancale') !== false && strpos($label, 'tipo') === false) { + $num = ws_pk_int($vals[0] ?? ''); + if ($num !== null) $out['boxes_or_packages_per_pallet'] = $num; + // "12 o 14": nel campo numerico va 12, il testo completo nelle note + if (ws_pk_multi($vals[0] ?? '')) $notes[] = 'Scatole x Bancale ' . $vals[0]; + continue; + } + } + + if ($notes) { + $out['meters_per_package_notes'] = implode('. ', array_unique($notes)); + } + return $out; +} + +function ws_pk_norm($s): string +{ + $s = mb_strtolower(trim((string)$s), 'UTF-8'); + $s = str_replace(['°', 'º'], '', $s); + return trim(preg_replace('/\s+/', ' ', $s)); +} + +/** primo numero intero della cella ("80", "80.0", "12 o 14", "160 m") */ +function ws_pk_int($v): ?int +{ + if (is_int($v) || is_float($v)) return (int)round($v); + if (preg_match('/\d+(?:[.,]\d+)?/', (string)$v, $m)) { + return (int)round((float)str_replace(',', '.', $m[0])); + } + return null; +} + +/** la cella contiene più numeri alternativi? ("12 o 14", "12/14") */ +function ws_pk_multi($v): bool +{ + return preg_match_all('/\d+/', (string)$v) > 1; +} + +function ws_pk_is_tolerance($v): bool +{ + $v = mb_strtolower((string)$v, 'UTF-8'); + return strpos($v, 'toll') !== false || preg_match('/[+-]\s*\d/', $v) || strpos($v, '+/-') !== false; +} + +/** "Toll Metrat. + 1,5m/-0" → "-0/+1.5m" "+/- 4m" → "+/- 4m" */ +function ws_pk_tolerance($v): string +{ + $s = str_replace(',', '.', (string)$v); + $num = '(\d+(?:\.\d+)?)'; + + if (preg_match('/\+\s*\/\s*-\s*' . $num . '/', $s, $m) || preg_match('/±\s*' . $num . '/u', $s, $m)) { + return '+/- ' . ws_pk_num($m[1]) . 'm'; + } + $plus = preg_match('/\+\s*' . $num . '/', $s, $mp) ? ws_pk_num($mp[1]) : null; + $minus = preg_match('/-\s*' . $num . '/', $s, $mm) ? ws_pk_num($mm[1]) : null; + if ($plus !== null || $minus !== null) { + return '-' . ($minus ?? '0') . '/+' . ($plus ?? '0') . 'm'; + } + return trim((string)$v); // formato non riconosciuto: testo originale +} + +function ws_pk_num($n): string +{ + $f = (float)$n; + return (floor($f) == $f) ? (string)(int)$f : rtrim(rtrim(number_format($f, 2, '.', ''), '0'), '.'); +}