C# - LinqToExcel - Map type complexe

Utilisateur anonyme - 16 mai 2016 à 23:08 - Dernière réponse : Whismeril
Messages postés
12238
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
15 novembre 2018
- 17 mai 2016 à 23:47
Bonjour,

J'ai deux classes :

public class Customer
{
    public string FirstName { get; set; }
 
    public string LastName { get; set; }
 
    public Count Count { get; set; }
}
 
public class Count
{
    public string Property1 { get; set; }
 
    public int Number { get; set; }
}



Et un fichier excel :



Je veux créer une instance de ma classe depuis mon fichier excel.

J'utilise LinqToExcel Library (https://github.com/paulyoder/LinqToExcel) :

var excelFile = new ExcelQueryFactory(pathToExcelFile);
 
excelFile.AddMapping<Customer>(x => x.Count.Number, "Number");
 
var data = excelFile.Worksheet<Customer>(sheetName).Select(x => x).ToArray();



Mais la propriété Number est null malgré le AddMapping que j'ai rajouté

Comment faire ?

Merci
Afficher la suite 

Votre réponse

8 réponses

Whismeril
Messages postés
12238
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
15 novembre 2018
- 17 mai 2016 à 20:38
0
Merci
Bonsoir

comme LinqToExcel m'interresse aussi et même si je n'avais pas encore testé, je me suis penché sur ton problème.

Je pense que le happer ne te permets que de changer le nom d'un champ d'un type de base, pas de créer une instance d'une autre classe.
Pour étayer mon hypothèse, si on définit Count comme étant un int, ça marche.

J'ai donc trouvé une astuce, pas très propre, pour contourner le problème.

    public class Customer
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public Count Count { get; set; }

        private int monCompte;
        public int MonCompte
        {
            set
            {
                monCompte = value;
                Count = new Count { Number = monCompte, Property1 = "test" };
            }

            get { return monCompte; }
        }


        public static Customer[] LireFichier(string Filename)
        {
            ExcelQueryFactory excelFile = new ExcelQueryFactory(Filename);

            excelFile.AddMapping<Customer>(x => x.MonCompte, "Number");

            return (from x in excelFile.Worksheet<Customer>("Feuil1")
                    select x).ToArray();


        }
    }

Commenter la réponse de Whismeril
Utilisateur anonyme - 17 mai 2016 à 20:46
0
Merci
Merci pour ta réponse.

Passer par un propriété intermédiaire ne m'interrese pas. Si je dois faire ça pour toutes mes sous classe je suis mal barré....
Commenter la réponse de Utilisateur anonyme
Whismeril
Messages postés
12238
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
15 novembre 2018
- 17 mai 2016 à 21:17
0
Merci
En continuant, à gratter, j'ai vu qu'il y a une surcharge à la méthode AddMapping, permettant de spécifier une transformation.
Et aussi une méthode AddTransformation, dont la description contient un exemple de syntaxe.

Que l'on retrouve dans le code source
        /// <summary>
        /// Transforms a cell value in the spreadsheet to the desired property value
        /// </summary>
        /// <typeparam name="TSheetData">Class type to return row data as</typeparam>
        /// <param name="property">Class property value to transform</param>
        /// <param name="transformation">Lambda expression that transforms the original string value to the desired property value</param>
        /// <example>
        /// AddTransformation{Person}(p => p.IsActive, x => x == "Y");
        /// AddTransformation{Person}(p => p.IsYoung, x => DateTime.Parse(x) > new DateTime(2000, 1, 1));
        /// </example>



Et cela donne
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public Count Count { get; set; }

        public static Customer[] LireFichier(string Filename)
        {
            ExcelQueryFactory excelFile = new ExcelQueryFactory(Filename);

            excelFile.AddMapping<Customer>(x => x.Count, "Number",y =>  new Count { Number = Convert.ToInt32(y) });

            return (from x in excelFile.Worksheet<Customer>("Feuil1")
                    select x).ToArray();


        }
    }

Commenter la réponse de Whismeril
Utilisateur anonyme - 17 mai 2016 à 21:20
0
Merci
Merci énormément pour ta réponse et le travail que tu as fourni
pour m'aider !
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 17 mai 2016 à 21:24
0
Merci
Et donc comment faire pour mapper à la fois Number et Property1 ?
Merci encore
Whismeril
Messages postés
12238
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
15 novembre 2018
- 17 mai 2016 à 21:43
Sais pas.
Il faut commencer par expliquer d'où il sort.
Utilisateur anonyme - 17 mai 2016 à 21:44
De l'excel egalement, une des colonnes
Commenter la réponse de Utilisateur anonyme
Whismeril
Messages postés
12238
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
15 novembre 2018
- 17 mai 2016 à 23:47
0
Merci
A priori la transformation ne concerne qu'une cellule.
J'ai donc essayé d'ajouter un Mapper, en me disant qu'une fois l'instance crée on pourrait y ajouter des données, comme ça
            excelFile.AddMapping<Customer>(x => x.Count, "Number",y =>  new Count { Number = Convert.ToInt32(y) });
            excelFile.AddMapping<Customer>(x => x.Count.Property1, "Property1");



Mais ça ne marche pas, la solution de la propriété intermédiaire me parait la seule pour l'instant.

Pour que ce soit plus propre que ce que j'ai fait plus haut, et surtout pour que le reste du programme n'est accès qu'à ce qui est nécessaire, j'ai dérivé ta classe, mis les propriétés intermédiaires et retourné un tableau de la classe Customer

    public class Customer
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public Count Count { get; set; }

        public static Customer[] LireFichier(string Filename)
        {
            ExcelQueryFactory excelFile = new ExcelQueryFactory(Filename);

            excelFile.AddMapping<Customer>(x => x.Count, "Number",y =>  new Count { Number = Convert.ToInt32(y) });           

            return (from x in excelFile.Worksheet<ImportCustomer>("Feuil1")
                    select x.SetProperty1()).ToArray();
        }


    }

    class ImportCustomer:Customer
    {

        private string property1;

        public string Property1
        {
            get { return property1; }
            set { property1 = value; }
        }
        
        public Customer SetProperty1()
        {
            this.Count.Property1 = this.Property1;
            return (Customer)this;
        }
        
    }


J'ai été obligé d'ajouter la méthode SetProperty1, car directement à la propriété l'instance de Count n'était pas crée.
Cela peut venir de l'évaluation différée des requêtes Linq
https://msdn.microsoft.com/fr-fr/library/bb943859.aspx
Ou d'un je ne sais quoi de la lib LinqToExcel.

Commenter la réponse de Whismeril

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.