Creazione di un file CSV da un file Excel tramite VB.Net e C#

Articolo che illustra una valida tecnica per creare un file CSV partendo da un file Excel in maniera dinamica.

il
Sviluppatore Microsoft .Net, Collaboratore di IProgrammatori

In questo articolo vedremo come realizzare una procedura  o meglio una “Windows Application” che dato un file Excel genera un file di tipo CSV.

La particolarità di questo progetto è una parte dinamica, nel senso che può essere utilizzata  per la versione di Excel 2007 o inferiore, e che la lettura delle colonne avviene tramite indice delle colonne (le lettere, a, b, c, d).

Prima di tutto bisogna creare un file Excel, nella prima colonna precisamente in A1 mettete la dicitura Nome, nella seconda colonna (B1) mettete Cognome, e nella terza colonna (C1) mettete età.
A questo punto valorizzare i vari campi al di sotto, inserendo i dati a vostro piacimento.
Ora non ci resta che aprire Visual Studio 2010 e  realizzare tale procedura.

Creazione del progetto

Si crea un nuovo progetto di tipo “Windows Application” tramite il linguaggio di programmazione di proprio interesse (VB.Net  o C#) a questo punto, nella form inseriamo quattro controlli Label, quattro controlli TextBox ed un pulsante, il tutto come illustrato in figura 1.



Figura 1 – la form con i vari controlli

Valorizziamo i vari campi con i dati di nostro interesse.
La prima casella conterrà il file CSV da generare, la seconda casella il percorso e nome del file Excel dove estrapolare i dati, il terzo campo, il nome del foglio su cui leggere le informazione, mentre nel quarto ed ultimo campo le colonne su cui leggere i dati.

Ora passiamo in visualizzazione codice facendo doppio sul pulsante con la dicitura "Genera", in modo che vi viene visualizzato l’evento del pulsante.

Qui di seguito si riporta il codice dell’evento click del pulsante.

VB.Net
Private Sub BtnGenera_Click(sender As System.Object, e As System.EventArgs) Handles BtnGenera.Click
        EseguiElaborazione(TxtFileExcel.Text, TxtCsv.Text, TxtFoglio.Text, TxtColonne.Text)
        MessageBox.Show("Operazione completata")
    End Sub
C#
private void BtnGenera_Click(object sender, EventArgs e)
        {
            EseguiElaborazione(TxtFileExcel.Text, TxtCsv.Text, TxtFoglio.Text, TxtColonne.Text);
            MessageBox.Show("Operazione completata");
        }



Come si vede dal codice, viene eseguita una funzione ,a cui sono passati i vari parametri, riguardante i valori inseriti nelle varie caselle di testo.


Di seguito elenchiamo le varie funzioni.

La funzione qui di seguito, permette di generare il file Csv passando il percorso e nome del file e come secondo parametro il testo da scrivere.

VB.Net
Private Shared Sub CreaFileCsv(NomeFileCSV As String, Testo As String)
        Try
            Using ScriviFile As New System.IO.StreamWriter(NomeFileCSV, False)
                ScriviFile.WriteLine(Testo)
            End Using
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
C#
private static void CreaFileCsv(string  NomeFileCSV, string  Testo)
        {
            try
            {
                using (System.IO.StreamWriter ScriviFile = new System.IO.StreamWriter(NomeFileCSV, false))
                {
                    ScriviFile.WriteLine(Testo);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


La funzione qui di seguito, permette di rilevare il nome delle colonne o meglio i campi della select che andremmo ad eseguire per estrapolare i dati dal file Excel.

L’algoritmo prendendo il nome dagli indici delle colonne (a,b,c,etc) rileva tali campi.

VB.Net
Private Shared Function OttieniNomeColonne(pColonne As DataTable, LetteraColonna As String) As String
        Dim LettereExcel As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        '26
        Dim Colonne As String() = LetteraColonna.Split(","c)
        Dim NomeColonna As String = ""
        For ContaColonne As Integer = 0 To Colonne.Length - 1
            If ContaColonne > 0 Then
                NomeColonna += ","
            End If
            Dim Indice As Integer = -1
            If Colonne(ContaColonne).Trim().Length > 1 Then
                For ContaElementi As Integer = 0 To Colonne(ContaColonne).Length - 1
                    If ContaElementi > 0 Then
                        Indice += 25 + LettereExcel.IndexOf(Colonne(ContaColonne).Trim().Substring(ContaElementi + 1))
                    Else
                        Indice = LettereExcel.IndexOf(Colonne(ContaColonne).Trim().Substring(ContaElementi + 1)) + 1
                    End If
                Next
            Else
                Indice = LettereExcel.IndexOf(Colonne(ContaColonne).Trim())
            End If
            NomeColonna += pColonne.Columns(Indice).ColumnName.Trim()
        Next
        Return NomeColonna
    End Function
C#
private   string OttieniNomeColonne(DataTable pColonne, string  LetteraColonna)
        {
            string  LettereExcel = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //26
            string[] Colonne = LetteraColonna.Split(',');
            string  NomeColonna = "";
            for (int ContaColonne = 0; ContaColonne < Colonne.Length; ContaColonne++)
            {
                if (ContaColonne > 0)
                {
                    NomeColonna += ",";
                }
                int  Indice = -1;
                if (Colonne[ContaColonne].Trim().Length > 1)
                {
                    for (int ContaElementi = 0; ContaElementi < Colonne[ContaColonne].Length; ContaElementi++)
                    {
                        if (ContaElementi > 0)
                        {
                            Indice += 25 + LettereExcel.IndexOf(Colonne[ContaColonne].Trim().Substring(ContaElementi + 1));
                        }
                        else
                        {
                            Indice = LettereExcel.IndexOf(Colonne[ContaColonne].Trim().Substring(ContaElementi + 1)) + 1;
                        }
                    }
                }
                else
                {
                    Indice = LettereExcel.IndexOf(Colonne[ContaColonne].Trim());
                }
                NomeColonna += pColonne.Columns[Indice].ColumnName.Trim();
            }
            return NomeColonna;
        }




Siamo giunti alla conclusione della stesura del codice, qui di seguito la funzione più importante, quella che ci permette di eseguire le query nel file di Excel ed estrapolare i dati.



VB.Net
Private Sub EseguiElaborazione(PercorsoFileExcel As String, PercorsoFileCsv As String, NomeFoglio As String, Colonne As String)
        Try
            Dim strConnectionString As String = ""
            If PercorsoFileExcel.Trim().EndsWith(".xlsx") Then
                strConnectionString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=" & ChrW(34) & "Excel 8.0;HDR=Yes;IMEX=1" & ChrW(34), PercorsoFileExcel)
            ElseIf PercorsoFileExcel.Trim().EndsWith(".xls") Then
                strConnectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=Yes"";", PercorsoFileExcel)
            End If
            'mi connetto alla base dati
            Using ObJConnection As New OleDbConnection(strConnectionString)
                ObJConnection.Open()
                Dim DtrRecord As OleDbDataReader
                Dim DtaQuery As New OleDbDataAdapter("Select top 1 * from [" & NomeFoglio & "$]  ;", ObJConnection)
                Dim DttDati As New DataTable()
                DtaQuery.Fill(DttDati)
                'Rilevo l'intestazione delle colonne
                Colonne = OttieniNomeColonne(DttDati, Colonne)
                'Ottengo i dati dopo aver rilevato i nomi delle colonne
                Dim DbCommandQuery As New OleDbCommand("Select " & Colonne & "  from [" & NomeFoglio & "$]  ;")
                DbCommandQuery.Connection = ObJConnection
                DtrRecord = DbCommandQuery.ExecuteReader()
                Dim DttDatiRisultato As New DataTable()
                'Rendo le colonne di tipo string
                Dim lNomeColonna As String() = Colonne.Split(",")
                For Each Colonna As String In lNomeColonna
                    DttDatiRisultato.Columns.Add(Colonna, GetType(String))
                Next
                DttDatiRisultato.Load(DtrRecord)
                Dim TestoDaScrivere As String = ""
                For Each Elemento As DataRow In DttDatiRisultato.Rows
                    For ContaColonne As Integer = 0 To Elemento.ItemArray.Length - 2
                        TestoDaScrivere += Elemento(ContaColonne).ToString() & ";"
                    Next
                    If TestoDaScrivere.Substring(TestoDaScrivere.Length - 1, 1) = ";" Then
                        TestoDaScrivere = TestoDaScrivere.Substring(0, TestoDaScrivere.Length - 1)
                    End If
                    TestoDaScrivere += vbCr & vbLf
                Next
                CreaFileCsv(PercorsoFileCsv, TestoDaScrivere)
            End Using
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
C #
        private   void EseguiElaborazione(string  PercorsoFileExcel, string PercorsoFileCsv, string NomeFoglio, string Colonne)
        {
            try
            {
                string strConnectionString = "";
                if (PercorsoFileExcel.Trim().EndsWith(".xlsx"))
                    strConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=" + (char)34 + "Excel 8.0;HDR=Yes;IMEX=1" + (char)34, PercorsoFileExcel);
                else if (PercorsoFileExcel.Trim().EndsWith(".xls"))
                {
                    strConnectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes\";", PercorsoFileExcel);
                }
                //mi connetto alla base dati
                using (OleDbConnection ObJConnection = new OleDbConnection(strConnectionString))
                {
                    ObJConnection.Open();
                    OleDbDataReader DtrRecord;
                    OleDbDataAdapter DtaQuery = new OleDbDataAdapter("Select top 1 * from [" + NomeFoglio + "$]  ;", ObJConnection);
                    DataTable DttDati = new DataTable();
                    DtaQuery.Fill(DttDati);
                    //Rilevo l'intestazione delle colonne
                    Colonne = OttieniNomeColonne(DttDati, Colonne);
                    //Ottengo i dati dopo aver rilevato i nomi delle colonne
                    OleDbCommand DbCommandQuery = new OleDbCommand("Select " + Colonne + "  from [" + NomeFoglio + "$]  ;");
                    DbCommandQuery.Connection = ObJConnection;
                    DtrRecord = DbCommandQuery.ExecuteReader();
                    DataTable DttDatiRisultato = new DataTable();
                    //Rendo le colonne di tipo string
                    string[] lNomeColonna = Colonne.Split(',');
                    foreach (var Colonna in lNomeColonna)
                    {
                        DttDatiRisultato.Columns.Add(Colonna, typeof(string));
                    }
                    DttDatiRisultato.Load(DtrRecord);
                    string TestoDaScrivere = "";
                    foreach (DataRow Elemento in DttDatiRisultato.Rows)
                    {
                        for (int ContaColonne = 0; ContaColonne < Elemento.ItemArray.Length - 1; ContaColonne++)
                        {
                            TestoDaScrivere += Elemento[ContaColonne].ToString()+ ";";
                        }
                        if (TestoDaScrivere.Substring(TestoDaScrivere.Length - 1, 1) == ";")
                        {
                            TestoDaScrivere = TestoDaScrivere.Substring(0, TestoDaScrivere.Length - 1);
                        }
                        TestoDaScrivere += "\r\n";
                    }
                    CreaFileCsv(PercorsoFileCsv, TestoDaScrivere);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

Conclusioni

L’articolo ha fornito al lettore delle ottime indicazioni di come creare un programma di tipo Windows Application, flessibile e dinamico per la lettura dei dati da un file di tipo Excel, di qualsiasi versione e generare un file di tipo CSV.

Tramite le classi di Ado.Net e precisamente di OleDB, possiamo lavorare sui file di tipo Excel.

Tramite la parola Download è possibile scaricare il progetto utilizzato in questo articolo.