2017-09-19 6 views
0

J'essaye de développer un outil qui prendra un fichier CSV et l'importera dans un datatable avec la première colonne dans le datatable étant un compteur de ligne.C#: Lire un fichier CSV structuré variable dans un datatable avec un compteur de lignes

Les fichiers CSV proviennent de clients différents et ont donc des structures différentes. Certains ont une ligne d'en-tête; certains ont plusieurs lignes d'en-tête; certains n'ont pas de ligne d'en-tête. Ils ont aussi des colonnes variables.

Jusqu'ici, j'ai le code ci-dessous.

public void Import_CSV() 
    { 
     OpenFileDialog dialog = new OpenFileDialog(); 
     dialog.Filter = "CSV Files (*.csv)|*.csv"; 
     bool? result = dialog.ShowDialog(); 

     if (result ?? false) 
     { 
      string[] headers; 

      string CSVFilePathName = dialog.FileName; 

      string delimSelect = cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString(); 

      // If user hasn't selected a delimiter, assume comma 
      if (delimSelect == "") 
      { 
       delimSelect = ","; 
      } 

      string[] delimiterType = new string[] {cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString()}; 

      DataTable dt = new DataTable(); 

      // Read first line of file to get number of fields and create columns and column numbers in data table 
      using (StreamReader sr1 = new StreamReader(CSVFilePathName)) 
      { 
       headers = sr1.ReadLine().Split(delimiterType, StringSplitOptions.None); 

       //dt.Columns.Add("ROW", typeof(int)); 
       //dt.Columns["ROW"].AutoIncrement = true; 
       //dt.Columns["ROW"].AutoIncrementSeed = 1; 
       //dt.Columns["ROW"].AutoIncrementStep = 1; 

       int colCount = 1; 

       foreach (string header in headers) 
       { 
        dt.Columns.Add("C" + colCount.ToString()); 
        colCount++; 
       } 
      } 

      using (StreamReader sr = new StreamReader(CSVFilePathName)) 
      { 
       while (!sr.EndOfStream) 
       { 
        string[] rows = sr.ReadLine().Split(delimiterType, StringSplitOptions.None); 

        DataRow dr = dt.NewRow(); 

        for (int i = 0; i < headers.Length; i++) 
        { 

          dr[i] = rows[i]; 
        } 

        dt.Rows.Add(dr); 
       } 
      } 

      dtGrid.ItemsSource = dt.DefaultView; 

      txtColCount.Text = dtGrid.Columns.Count.ToString(); 
      txtRowCount.Text = dtGrid.Items.Count.ToString(); 
     } 
    } 

Cela fonctionne, dans la mesure où elle crée des en-têtes de colonnes (C1, C2 .... selon combien il y a dans le fichier csv) et les lignes sont écrites, mais je veux ajouter une colonne à l'extrême gauche avec un numéro de ligne lorsque les lignes sont ajoutées. Dans le code, vous pouvez voir que j'ai une section commentée qui crée une colonne de numéro automatique, mais je suis totalement bloqué sur la façon dont les lignes sont écrites dans le datatable. Si je ne commente pas cette section, j'obtiens des erreurs car la première colonne du fichier csv essaie d'écrire dans un champ int. Je sais que vous pouvez spécifier quel champ dans chaque ligne peut aller dans quelle colonne, mais cela n'aidera pas ici car les colonnes sont inconnues à ce stade. J'en ai juste besoin pour lire n'importe quel fichier, quelle que soit la structure, mais avec le compteur de lignes.

Espérons que cela a du sens.

Répondre

1

Vous écrivez dans votre question, que la décompression du code qui ajoute la première colonne conduit à des erreurs. C'est à cause de votre boucle: elle commence à 0, mais la 0-ème colonne est celle que vous avez ajoutée manuellement. Il vous suffit donc de l'ignorer dans votre boucle, en commençant à 1. Cependant, le tableau source doit être traité à partir du 0-ème élément.

La solution est donc:

D'abord, décommentez la ligne ajouter du code.

Ensuite, dans votre boucle, introduire un décalage de quitter la première colonne intacte:

for (int i = 0; i < headers.Length; i++) 
{ 
    dr[i + 1] = rows[i]; 
} 
+0

Cela pourrait faire avec un peu plus d'explications, mais il est la bonne réponse. – Flater

+0

Hey Dymanoid, merci pour l'entrée! Et la réponse! Si simple à la fin. Merci encore. – Mark