IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Remplacement de valeur dans DataTable


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut Remplacement de valeur dans DataTable
    Bonjour.
    Je suis un peu rouillé sur les DataTable et confronté à deux problèmes.
    soit le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    private static DataSet MergeTableLignesByField(DataSet dataSet, DataTable originalTable, int columnIndex)
            {
                if(originalTable.Rows.Count > 0 && originalTable.Rows[0].ItemArray[columnIndex] is string)
                {
                    DataTable newTable = originalTable.Clone();
                    newTable.Clear();
     
                    DataRow previousRow = null;
                    for(int i = 0; i < originalTable.Rows.Count; i++)
                    {
                        DataRow currentRow = originalTable.Rows[i];
                        bool matchLine = false;
                        if(previousRow != null)
                        {
                            // On compare les champs de deux lignes pour savoir si on peut les fusionner : tous les champs sont identiques sauf le champ spécifié
                            for(int j = 0; j < currentRow.ItemArray.Length; j++)
                                if(j != columnIndex)
                                {
                                    matchLine = (currentRow.ItemArray[j].ToString() == previousRow.ItemArray[j].ToString());
                                    if(!matchLine)
                                        break;
                                }
                            //Si les lignes sont identiques, on peut les fusionner et merger le champ voulu.
                            if(matchLine)
                            {
                                previousRow.BeginEdit();
                                string newValue = string.Concat(previousRow.ItemArray[columnIndex].ToString(), " | ", currentRow.ItemArray[columnIndex].ToString());
                                previousRow.ItemArray[columnIndex] = newValue;
                                previousRow.AcceptChanges();
                                previousRow.EndEdit();
                            }
                        }
     
                        if(!matchLine)
                        {
                            if(previousRow != null)
                                newTable.Rows.Add(previousRow.ItemArray);
                            previousRow = newTable.NewRow();
                            previousRow.ItemArray = currentRow.ItemArray;
                        }
     
                    }
                    //originalTable.Clear();
                    //originalTable.Merge(newTable, true);
                }
                return dataSet;
            }
    qui est censé faire :
    Dans une table d'un DataSet, parcourir toutes les lignes successives, si on trouve plusieurs lignes avec les mêmes valeurs (sauf pour le champ indiqué par columnIndex) on ne prend qu'une ligne et on concatène le contenu du champ [columnIndex] de toutes les lignes qui matches.
    C'est clair ?

    Premier problème : previousRow.ItemArray[columnIndex] = newValue; ne change pas de valeur.
    2ème pbm : c'est une usine à gaz... Il n'y aurait pas plus simple ?
    Merci


    p.s. :
    mes données sont du genre :
    nom1,prénom1,champ à concat 1, integer
    nom1,prénom1,champ à concat 2, integer
    nom2,prénom2,champ à concat 1, integer
    nom2,prénom2,champ à concat 2, integer
    nom3,prénom3,"texte", integer
    et je veux fusionner les lignes 1 & 2 , et 3 & 4

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Tu peux faire ça avec Linq, il faut juste créer un IEqualityComparer spécifique pour comparer les lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    void MergeTableLignesByField(DataTable table, int columnIndex)
    {
        var comparer = new DataRowComparer(columnIndex);
        var groups = table.AsEnumerable().GroupBy(r => r, comparer);
        foreach (var g in groups)
        {
            MergeRows(g, columnIndex);
        }
    }
     
     
    void MergeRows(IEnumerable<DataRow> rows, int columnToMerge)
    {
        string mergedValue = string.Join("|", rows.Select(r => r[columnToMerge]));
        int count = 0;
        foreach (var row in rows)
        {
            if (count == 0)
                row[columnToMerge] = mergedValue;
            else
                row.Delete();
            count++;
        }
    }
     
    class DataRowComparer : IEqualityComparer<DataRow>
    {
        private readonly int[] _excludedColumnIndexes;
        public DataRowComparer(params int[] excludedColumnIndexes)
        {
            _excludedColumnIndexes = excludedColumnIndexes;
        }
     
        public bool Equals(DataRow x, DataRow y)
        {
            for (int i = 0; i < x.Table.Columns.Count; i++)
            {
                if (_excludedColumnIndexes.Contains(i))
                    continue;
                if (!Equals(x[i], y[i]))
                    return false;
            }
            return true;
        }
     
        public int GetHashCode(DataRow row)
        {
            unchecked // Overflow is fine, just wrap
            {
                int hash = 17;
                for (int i = 0; i < row.Table.Columns.Count; i++)
                {
                    if (_excludedColumnIndexes.Contains(i))
                        continue;
                    object fieldValue = row[i];
                    int fieldHash = fieldValue != null ? fieldValue.GetHashCode() : 0;
                    hash = hash * 23 + fieldHash;
                }
                return hash;
            }
        }
    }
    (il faut référencer l'assembly System.Data.DataSetExtensions)

    Au passage, j'ai fait une autre modif : le paramètre dataSet de ta méthode n'est pas utilisé, il est juste renvoyé tel quel, donc je l'ai viré et j'ai mis le type de retour en void

  3. #3
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    J'ai modifié mon code, la substitution s'opère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    private static DataSet MergeTableLignesByField(DataSet dataSet, DataTable originalTable, int columnIndex)
            {
                if(originalTable.Rows.Count > 0 && originalTable.Rows[0].ItemArray[columnIndex] is string)
                {
                    DataTable newTable = originalTable.Clone();
                    newTable.Clear();
     
                    object[] newValues = null;
                    for(int i = 0; i < originalTable.Rows.Count; i++)
                    {
                        DataRow currentRow = originalTable.Rows[i];
                        bool matchLine = false;
                        if(newValues != null)
                        {
                            // On compare les champs de deux lignes pour savoir si on peut les fusionner : tous les champs sont identiques sauf le champ spécifié
                            for(int j = 0; j < currentRow.ItemArray.Length; j++)
                                if(j != columnIndex)
                                {
                                    matchLine = (currentRow.ItemArray[j].ToString() == newValues[j].ToString());
                                    if(!matchLine)
                                        break;
                                }
                            //Si les lignes sont identiques, on peut les fusionner et merger le champ voulu.
                            if(matchLine)
                            {
                                newValues[columnIndex] = string.Concat(newValues[columnIndex].ToString(), " | ", currentRow.ItemArray[columnIndex].ToString());
                               // previousRow.ItemArray = newValues;
                            }
                        }
     
                        if(!matchLine)
                        {
                            if(newValues != null)
                                newTable.Rows.Add(newValues);
                            newValues = currentRow.ItemArray;
                        }
     
                    }
                    originalTable.Clear();
                    originalTable.Merge(newTable, true);
                }
                return dataSet;
            }

    J'ai vu ton code, Tomlev, je testerai pour ma culture => le besoin n'existe plus, on s'est aperçu qu'il existe des cas pour lesquels le problème de ligne ne serait pas réglé comme ça.

    Mon DataSet, c'est parce que c'est du code appelé par 4 surcharges d'une méthode d'extension. Je pensais que c'était nécessaire :
    voici l'un des surcharges :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            public static DataSet MergeTableLignesByField(this DataSet dataSet, string tableName, string fieldName)
            {
                DataTable originalTable = dataSet.Tables[tableName];
                int columnIndex = originalTable.Columns[fieldName].Ordinal;
                return MergeTableLignesByField(dataSet, originalTable, columnIndex);
            }
    Merci à toi.

  4. #4
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    Tomlev
    Pour ma culture, j'ai testé ton code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    rows.Select(r => r[columnToMerge])
    me retourne null. Je ne comprends pas pourquoi.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par kheironn Voir le message
    Tomlev
    Pour ma culture, j'ai testé ton code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    rows.Select(r => r[columnToMerge])
    me retourne null. Je ne comprends pas pourquoi.
    Bizarre, pourtant j'ai testé et chez moi ça fonctionne bien...

    Qu'est-ce qui retourne null d'ailleurs ? Le Select ? normalement c'est pas possible, ça devrait renvoyer un IEnumerable<object>... Ou alors c'est juste r[columnToMerge] qui renvoie null pour certains r ? normalement c'est pas possible non plus, ça devrait renvoyer DBNull s'il n'y a pas de valeur

  6. #6
    Membre émérite Avatar de kheironn
    Homme Profil pro
    Chef de projets technique C# / MVC / .Net
    Inscrit en
    Février 2007
    Messages
    823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets technique C# / MVC / .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2007
    Messages : 823
    Par défaut
    rows contient mes trois lignes (normal) et ajoute une dernière ligne null.
    Ce serait donc la méthode de création des groupes qui ne va pas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Remplacer une valeur dans un tableau
    Par msahmi dans le forum Tcl/Tk
    Réponses: 1
    Dernier message: 22/03/2008, 23h12
  2. Remplace une valeur dans une colonne
    Par roger34 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 22/06/2007, 22h44
  3. Réponses: 5
    Dernier message: 12/01/2007, 21h40
  4. [MS SQL] Remplacer des valeurs dans plusieurs tables
    Par salmoliv dans le forum Langage SQL
    Réponses: 3
    Dernier message: 04/10/2006, 17h31
  5. [Tableaux] Remplacement de valeurs dans un texte
    Par JavaSearch dans le forum Langage
    Réponses: 7
    Dernier message: 16/01/2006, 23h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo