Spesso mi è capitato, e ancora oggi mi capita, di avere a che fare con file CSV (file di testo con “Campi Separati da Virgola”) che, aperti con Excel, vengono caricati senza separare i vari campi. In pratica, ogni riga (record) viene inserito nella corrisponte cella della prima colonna.
Il motivo è semplice: questi file CSV sono stati creati con sistemi le cui impostazioni internazionali sono impostate secondo il sistema americano, con la virgola per la separazione del campo e il punto per separare i valori interi dai decimali. Nelle impostazioni italiane, invece, ovviamente è diverso: la virgola è il separatore dei decimali, mentre il punto e virgola è il separatore dei campi.
Come risolvere questo problema per poter caricare i dati in un foglio Excel?
Una prima soluzione che ho tentato è quella di sostituire tutti i separatori direttamente in Excel, salvando poi nuovamente in file CSV. Il risultato è deludente, in quanto Excel registra, sì, le modifiche, ma circonda ciascuna riga da doppi apici, rendendo ugualmente impossibile la lettura campo per campo.
Una seconda soluzione è quella di aprire NotePad e fare la sostituzione manuale, prima da virgola a punto e virgola e poi da punto a virgola. Questa soluzione risolve il problema ma è macchinosa, un po’ difficile da ricordare e poi straordinariamente LENTA.
Da qui mi è venuto in mente che tutto questo lavoro può essere fatto in modo più efficace con un programmino di utilità, naturalmente in VB 2008 (anche la versione 2.0 del Framework .NET va bene, quindi si può fare anche in VB 2005).
Ho creato un nuovo progetto di tipo Applicazione Windows Form e ho inserito due controlli Label (il nome non ha importanza) e quattro caselle di testo: txtCartella e txtFile per caricare rispettivamente il nome della cartella (per aprire sempre la stessa cartella se i file da convertire sono più di uno) e il nome del file, nonché txtTestoDaConvertire e txtTestoConvertito, più grandi e multilinea, con ovvio significato.
Poi ho creato un menu per gestire le varie azioni da eseguire. Il menu ha la seguente struttura:
- File
… Apri
…… Cartella
…… File
… Salva
… Chiudi file
… Esci
- Conversione
… CSV inglese –> CSV italiano
… CSV italiano –> CSV inglese
Infine ho inserito i seguenti controlli, per gestire tutte le operazioni su file e nel menu: MenuStrip, StatusStrip, ToolStrip, FolderBrowserDialog, OpenFileDialog e SaveFileDialog.
Il form ha quindi il seguente aspetto finale:
Infine, il codice che ho inserito è il seguente:
Public Class Form1
Private Sub CartellaToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles CartellaToolStripMenuItem.Click
Dim nomeCartella As String = ""
If FolderBrowserDialog1.ShowDialog = _
Windows.Forms.DialogResult.OK Then
nomeCartella = FolderBrowserDialog1.SelectedPath
End If
Me.txtCartella.Text = nomeCartella
End Sub
Private Sub FileToolStripMenuItem1_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles FileToolStripMenuItem1.Click
Dim nomeFile As String = ""
OpenFileDialog1.InitialDirectory = Me.txtCartella.Text
If OpenFileDialog1.ShowDialog = _
Windows.Forms.DialogResult.OK Then
nomeFile = OpenFileDialog1.FileName
End If
Me.txtFile.Text = nomeFile
Me.txtTestoDaConvertire.Text = _
My.Computer.FileSystem.ReadAllText(Me.txtFile.Text)
End Sub
Private Sub ToolStripMenuItem2_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles ToolStripMenuItem2.Click
Dim nomeFile As String = Me.txtFile.Text
Dim nomeCompleto As String = ""
SaveFileDialog1.FileName = nomeFile
If SaveFileDialog1.ShowDialog = _
Windows.Forms.DialogResult.OK Then
nomeCompleto = SaveFileDialog1.FileName
My.Computer.FileSystem.WriteAllText( _
nomeCompleto, Me.txtTestoConvertito.Text, False)
Else
MessageBox.Show("Operazione annullata")
End If
End Sub
Private Sub Label2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Label2.Click
If Me.txtFile.Enabled = True Then
Me.txtFile.Enabled = False
Else
Me.txtFile.Enabled = True
End If
End Sub
Private Sub Label1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Label1.Click
If Me.txtCartella.Enabled = True Then
Me.txtCartella.Enabled = False
Else
Me.txtCartella.Enabled = True
End If
End Sub
Private Sub CSVIngleseCSVItalianoToolStripMenuItem_Click( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles CSVIngleseCSVItalianoToolStripMenuItem.Click
Me.txtTestoConvertito.Text = Me.txtTestoDaConvertire.Text
Me.txtTestoConvertito.Text = Me.txtTestoConvertito.Text.Replace(",", ";")
Me.txtTestoConvertito.Text = Me.txtTestoConvertito.Text.Replace(".", ",")
Me.txtTestoConvertito.Text = Me.txtTestoConvertito.Text.Replace( _
System.Environment.NewLine, System.Environment.NewLine)
End Sub
Private Sub CSVItalianoCSVIngleseToolStripMenuItem_Click( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles CSVItalianoCSVIngleseToolStripMenuItem.Click
Me.txtTestoConvertito.Text = Me.txtTestoDaConvertire.Text
Me.txtTestoConvertito.Text = Me.txtTestoConvertito.Text.Replace(",", ".")
Me.txtTestoConvertito.Text = Me.txtTestoConvertito.Text.Replace(";", ",")
End Sub
Private Sub EsciToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles EsciToolStripMenuItem.Click
Me.Close()
End Sub
Private Sub ChiudiFileToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles ChiudiFileToolStripMenuItem.Click
Me.txtTestoDaConvertire.Text = ""
Me.txtTestoConvertito.Text = ""
End Sub
End Class
Il punto chiave, è nei metodi CSVIngleseCSVItalianoToolstripMenuItem e nell’opposto CSVItalianoCSVIngleseToolStripMenuItem.
In questi metodi emerge chiaramente che la conversione “inversa” avviene non solo sostituendo i due valori da sostituire, nell’ambito della stessa istruzione di conversione, ma anche scambiando le due istruzioni che utilizzano il metodo Replace. Solo così, infatti, è possibile effettuare una conversione corretta ed eventualmente ripetere la conversione per ripristinare la situazione precedente.