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'), '.'); }