Formati CSV ed Excel
Formati supportati
FileFormato è il discriminator type per i formati gestiti dalla libreria:
type FileFormato = 'csv' | 'xlsx' | 'xls' | 'json'
| Formato | Estensione | Parser | Import | Export |
|---|---|---|---|---|
| CSV | .csv | papaparse (server) + parser interno (client) | Sì | Sì |
| Excel 2007+ | .xlsx | exceljs | Sì | Sì |
| Excel 97-2003 | .xls | exceljs | Sì | No |
| JSON | .json | JSON.parse | Sì | Sì |
Validazione lato client
Il componente ImportStepUpload applica le seguenti regole prima di inoltrare il file all'API:
| Vincolo | Valore |
|---|---|
| Estensioni accettate | csv, xlsx, xls, json |
| MIME types accettati | text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, application/json, text/plain, '' (fallback browser) |
| Dimensione massima | 50 MB |
Se il file non rispetta i vincoli, viene mostrato un Message di errore senza chiamare l'API.
Opzioni CSV
Per i file CSV è disponibile la struttura CsvOpzioni, configurabile dall'utente tramite il componente FormatOptions:
interface CsvOpzioni {
separatore: string
delimitatoreTesto: string
encoding: string
rigaIniziale: number
haIntestazione: boolean
}
| Campo | Default | Valori UI |
|---|---|---|
separatore | , | ,, ;, \t, ` |
delimitatoreTesto | " | testo libero |
encoding | UTF-8 | UTF-8, ISO-8859-1, Windows-1252 |
rigaIniziale | 1 | numero (1-based) |
haIntestazione | true | boolean |
Parser CSV interno
La utility parseCSV è esportata anche pubblicamente per poter parsare CSV lato client senza chiamare il backend (per esempio per leggere headers e anteprima):
import { parseCSV } from '@pzeta/vue-importexport'
const csv = 'Name,Age\n"Smith, John",30\nJane,25'
const result = parseCSV(csv)
// result.headers = ['Name', 'Age']
// result.rows = [['Smith, John', '30'], ['Jane', '25']]
// result.lineCount = 3
CSVParseOptions
| Opzione | Default | Descrizione |
|---|---|---|
delimiter | , | Separatore colonne |
quote | " | Delimitatore testo per campi con separatori |
skipEmptyLines | true | Salta righe vuote |
trimFields | true | Trim spazi bianchi sui campi |
removeBOM | true | Rimuove BOM UTF-8 se presente |
CSVParseResult
| Campo | Tipo | Descrizione |
|---|---|---|
headers | string[] | Headers estratti dalla prima riga |
rows | string[][] | Righe dati (escluso header) |
lineCount | number | Numero totale righe parsate (header + data) |
Esempi
CSV con separatore punto e virgola:
const csv = 'Nome;Età\nMario;30'
const result = parseCSV(csv, { delimiter: ';' })
CSV con BOM e quote escapate:
const csv = '"Nome","Note"\n"Mario","Lui ha detto ""ciao"""'
const result = parseCSV(csv)
// result.rows = [['Mario', 'Lui ha detto "ciao"']]
Detection formula injection
Per protezione contro CSV-injection (formule Excel iniettate via =, +, -, @), la libreria espone:
import { detectFormulaInjection, detectFormulaInjectionWarnings } from '@pzeta/vue-importexport'
detectFormulaInjection('=CMD|"/C calc"!A0') // true
detectFormulaInjection('Mario Rossi') // false
const warnings = detectFormulaInjectionWarnings(rows, headers)
// → [{ riga: 2, colonna: 'Nome', valore: '=...' }, ...]
I caratteri sospetti sono: =, +, -, @, \t, \r. Tipicamente queste celle vanno prefissate con un apice (') prima dell'export per disabilitare la formula in Excel.
Excel (XLSX/XLS)
Il parsing XLSX è gestito server-side dal microservizio node-excel-import tramite exceljs. Lato client, la libreria si limita a leggere headers e anteprima delle prime righe (per la UI di mapping) tramite readFileHeaders, che usa exceljs direttamente nel browser:
// Comportamento interno di useImport.upload():
const fileHeaders = await readFileHeaders(file, opzioniCsv)
// fileHeaders.colonne → string[] (headers riga 1)
// fileHeaders.anteprimaRighe → Record<string, unknown>[] (prime N righe)
Per file XLSX viene letto il primo worksheet del workbook. Le colonne sono i valori della prima riga; le righe successive vengono trasformate in oggetti { header: valore }.
JSON
Per i file JSON la libreria si aspetta un array di oggetti con chiavi uniformi:
[
{ "nome": "Mario", "email": "mario@example.com", "eta": 30 },
{ "nome": "Anna", "email": "anna@example.com", "eta": 25 }
]
Le chiavi del primo oggetto vengono usate come "colonne sorgente" per il mapping.