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

  1. #1
    Candidat au Club
    Recherche d'une variable dans une feuille Excel avec Perl
    Bonjour,

    je suis débutant en Perl et j'essaye de de manipuler un fichier Excel avec quelques difficultés.
    Mon besoin est de rechercher dans la première colonne d'un fichier Excel un mot ou chiffre chargé au préalable dans une variable.
    Si la correspondance est trouvée j'aimerais renvoyer dans une variable i ( par exemple ) le nombre d'occurence de la recherche et dans une autre variable x ( toujours par exemple ) la ligne complète du tableau Excel correspondant à la valeur recherchée.

    Voici un début de code que j'ai écris :

    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
    my $essai;					        #classeur excel
    my $sheet; 							#feuilles excel
    my $Symb;								#valeur dans la case du tableau exel
    my $col;								#Colone dans le tableau excel
    my $row;								#ligne
    my $FileName = 'C:\Users\essai\essai.xls';
     
    $i=0;
     
    #Lecture
    my $parser   = Spreadsheet:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arseExcel->new();
    my $essai= $parser->parse($FileName);	#ouverture et lecture du classeur essai.xls
     
    #Vérification
    if ( !defined $essai) {
        die "Parsing error: ", $parser->error(), ".\n";
     
    }
     
    print "=========================================\n";
    print "FILE  :", $essai->{File} , "\n";
    print "COUNT :", $essai->{SheetCount} , "\n";
    print "AUTHOR:", $essai->{Author} , "\n";
    print "=========================================\n";
     
    $sheet=$essai->{Worksheet}[0]; #sélectionne la première feuille 
    $col=$sheet->{sheet}[1]; #sélectionne la première colonne 
     
    print "=========================================\n";    
    print "--------- SHEET:", $sheet->{Name}, "\n"; 		              #affiche le nom des feuilles excel
    print "=========================================\n";		
     
    if ($aff==1){print "symbole recherche = $recherche\n";} #pour mode debug affiche la variable $recherche( symbole recherché )
     
    	foreach $row ($sheet->{MinRow}+1 .. $sheet->{MaxRow}) { #on saute la 1ere ligne
    	           $Symb = $sheet->{Cells}[$row][$col];
                print "( $row ) =>", $Symb->Value, "\n" if($Symb);}
     
    			foreach ($Symb eq $recherche){ #recherche du symbole dans la colonne A du fichier Excel
    			$i++; #incrémentation de la variable lors d'une occurence
                }
     
    ....


    Je suis un peu perdu pour la suite, si une âme charitable pouvait me donner un coup de pouce.

    Cordialement,

  2. #2
    Expert confirmé
    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
    use strict;
    use warnings;
     
    use Spreadsheet:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arseExcel;
     
    my $essai;					        
    my $sheet; 							
     
    my $col;    						
    my $row;							
    my $fileName = './croctarts.xls';
     
    my $i = 0;
    my $recherche = 'Z';
     
    my $aff = 1;
     
    #Lecture
    my $parser = Spreadsheet:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arseExcel->new();
    my $essai = $parser->parse($fileName);
     
    #Vérification
    if ( !defined $essai ) {  
        die "Parsing error: ", $parser->error(), ".\n";
    }
     
    print "=========================================\n";
    print "FILE   : ", $essai->{File} , "\n";
    print "COUNT  : ", $essai->{SheetCount} , "\n";
    print "AUTHOR : ", $essai->{Author} , "\n";
    print "=========================================\n\n";
     
    $sheet = $essai->Worksheet(0); #sélectionne la première feuille 
    $col = $sheet->{MinCol}; #sélectionne la première colonne 
     
    print "=========================================\n";    
    print "--------- SHEET:", $sheet->{Name}, "\n"; 		              #affiche le nom des feuilles excel
    print "=========================================\n";		
     
    if ( $aff == 1 ) {
        print "symbole recherche = $recherche\n";
    } 
     
    $recherche = quotemeta($recherche);
     
    my $pattern = qr{$recherche};
     
    for my $row ($sheet->{MinRow} + 1 .. $sheet->{MaxRow}) { # on saute la 1ere ligne
        my $cell = $sheet->get_cell($row, $col);
        if ( $cell->value() =~ $pattern ) {
            $i++;
            print "( $row ) => ",
            join(',', map { $sheet->get_cell($row, $_)->value() } $sheet->{MinCol} .. $sheet->{MaxCol}),
            "\n";
        }
    }
     
    print "nombre de lignes : $i\n";


    À adapter à ton usage.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Candidat au Club
    Bonjour,

    tout d'abord merci pour le coup de main.
    Je suis un peu perdu dans les modifications que tu m'as fourni, pourrais tu m'apporter quelques précisions supplémentaires sur celles-ci en fonction des commentaires du code ci-dessous.

    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
    use strict;
    use warnings;
     
    use Spreadsheet:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arseExcel;
     
    my $essai;					        
    my $sheet; 							
     
    my $col;    						
    my $row;							
    my $fileName = './croctarts.xls';
     
    my $i = 0;
    my $recherche = 'Z';
     
    my $aff = 1;


    déclaration des variables jusque là tout va bien

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #Lecture
    my $parser = Spreadsheet:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />arseExcel->new();
    my $essai = $parser->parse($fileName);
     
    #Vérification
    if ( !defined $essai ) {  
        die "Parsing error: ", $parser->error(), ".\n";
    }


    lecture et vérification du fichier Excel

    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
    print "=========================================\n";
    print "FILE   : ", $essai->{File} , "\n";
    print "COUNT  : ", $essai->{SheetCount} , "\n";
    print "AUTHOR : ", $essai->{Author} , "\n";
    print "=========================================\n\n";
     
    $sheet = $essai->Worksheet(0); #sélectionne la première feuille 
    $col = $sheet->{MinCol}; #sélectionne la première colonne 
     
    print "=========================================\n";    
    print "--------- SHEET:", $sheet->{Name}, "\n"; 		              #affiche le nom des feuilles excel
    print "=========================================\n";		
     
    if ( $aff == 1 ) {
        print "symbole recherche = $recherche\n";
    }


    sélection feuille et colonne et affichage de la variable $recherche
    Bon jusqu'ici tout reste à ma portée.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    $recherche = quotemeta($recherche);
     
    my $pattern = qr{$recherche};


    Les ennuis commencent peux tu me détailler rapidement l'utilité de ces deux lignes

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for my $row ($sheet->{MinRow} + 1 .. $sheet->{MaxRow}) { # on saute la 1ere ligne
        my $cell = $sheet->get_cell($row, $col);
        if ( $cell->value() =~ $pattern ) {
            $i++;

    on ignore la première ligne du tableau Excel puis on compare chaque valeur de cellule à la variable $pattern et on incrémente la variable $i à chaque itération
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
            print "( $row ) => ",
            join(',', map { $sheet->get_cell($row, $_)->value() } $sheet->{MinCol} .. $sheet->{MaxCol}),
            "\n";

    on affiche la ligne correspondant à la valeur recherchée, le code est un peu obscure pourrais tu me l'expliquer

    Voilà désolé mais j'aime bien comprendre plutot que de recopier bêtement.

    De plus lorsque je lance ton script en ayant au préalable créé un fichier xls contenant Z dans une cellule ( pour reprendre ton exemple ) voici les erreurs renvoyées :

    "my" variable $essai masks earlier declaration in same scope at essai.pl line 20.
    Can't call method "value" on an undefined value at essai.pl line 53.

    Merci pour tes lumières.

    Cordialement,

  4. #4
    Expert confirmé
    Citation Envoyé par Rhapsödie Voir le message
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    $recherche = quotemeta($recherche);
     
    my $pattern = qr{$recherche};


    Les ennuis commencent peux tu me détailler rapidement l'utilité de ces deux lignes
    C'est deux lignes ne servent peut être à rien. Comme tu es évasive sur la nature de ce qui est recherché et qu'il n'y a pas l'ombre de la queue d'un exemple de ton fichier excel, j'ai pondu une pattern regex, à modifier suivant le contexte, où figure pour l'instant juste $recherche dont les caractères spéciaux sont échappés grâce à quotemeta(). En l'état, tu pourrais très bien te passer de regex et utiliser index($cell->value(), $recherche)!=-1 (et en virant quotemeta()) à la place de $cell->value =~ $pattern pour vérifier que la cellule contient bien ce que tu recherches.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for my $row ($sheet->{MinRow} + 1 .. $sheet->{MaxRow}) { # on saute la 1ere ligne
        my $cell = $sheet->get_cell($row, $col);
        if ( $cell->value() =~ $pattern ) {
            $i++;

    on ignore la première ligne du tableau Excel puis on compare chaque valeur de cellule à la variable $pattern et on incrémente la variable $i à chaque itération
    C'est inexacte, mais c'est peut-être ce que tu voulais dire: on itère sur les lignes du tableau Excel en ignorant la première ligne (c'est tiré de ton code), si une correspondance de la pattern est trouvée dans la première cellule d'une ligne, alors on incrémente $i (sinon non).

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
            print "( $row ) => ",
            join(',', map { $sheet->get_cell($row, $_)->value() } $sheet->{MinCol} .. $sheet->{MaxCol}),
            "\n";

    on affiche la ligne correspondant à la valeur recherchée, le code est un peu obscure pourrais tu me l'expliquer
    Oui, c'est bien ça. Pour ce qui est de join() tu devrais t'en sortir avec la doc Perl.
    map permet d'appliquer une transformation à tous les éléments d'une liste et de renvoyer une liste modifiée. Ces éléments sont ici les numéros de colonne. La transformation $sheet->get_cell($row, $_)->value() est simple, elle renvoie le contenu de chaque cellule pour chaque numéro de colonne pour la ligne dont il est question. $_ prendra successivement la valeur de chaque numéro de colonne.
    Je te conseille le tutoriel de Lolo78 sur la programmation fonctionnelle à ce sujet.

    "my" variable $essai masks earlier declaration in same scope at essai.pl line 20.
    C'est un oublie retire la déclaration de la ligne 6. D'ailleurs tu peux aussi virer la déclaration my $row; ligne 10.

    Can't call method "value" on an undefined value at essai.pl line 53.
    Ça signifie que $sheet->get_cell($row, $_) est indéfini, reste à trouver pourquoi.
    Et comme je n'ai pas le problème, difficile de faire des tests à ta place. Commence par relancer le script avec les modifications précédentes.
    Si ça persiste, vérifie que tu n'as pas redéfini $row pour une quelconque raison dans la boucle. Fait des print pour voir ce qui n'est pas normal. Bref, la base et le pain noir du débuggage.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Candidat au Club
    Tout d'abord un grand merci pour toutes ces précisions.
    Etant débutant sur Perl je ne reste pas avare de questions surtout que j'aime bien comprendre ce que je fais.

    N'ayant pas accès à mon PC ce weekend je te tiendrais au courant de l'évolution du programme.
    Effectivement je n'ai pas forcément précisé mais le tableau Excel en question contient plusieurs colonnes et lignes contenant des caractères alphanumériques et des caractères de ponctuation comme le point ou le tiret.
    Je ne peux pas fournir le fichier original en question puisqu'il est confidentiel et est lié à mon travail, mais voici un exemple basique de ce qu'il pourrait contenir.



    Dans l'idée je traite plusieurs fichiers dans une autre partie du programme ou j’extrais une donnée alphanumérique "flottante" ( elle peut changer à chaque fois que je lance le script ) que je charge dans une variable. c'est ensuite cette variable que je viens rechercher dans mon tableau.

    Pour l'itération c'est effectivement ce que j'avais en tête donc on se comprend bien sur différents langages

    Oui, c'est bien ça. Pour ce qui est de join() tu devrais t'en sortir avec la doc Perl.
    j'ai été voir en parallèle du coup c'est plutôt simple puisque la fonction permet de séparer des éléments à l'aide d'un caractère ici en l’occurrence la virgule qui séparera chaque contenu de cellule.

    Bon weekend,

    Cordialement,

  6. #6
    Candidat au Club
    Voici quelques nouvelles j'ai enfin pu terminer le code, il ne me reste plus qu'à le tester en condition réelle.
    Merci pour ton aide qui m'a été précieuse et qui je dois dire m'a permi d'arriver à cette solution .
    Pour info le problème "Can't call method "value" on an undefined value at essai.pl line 53." était du à une accolade mal placée.

    Bonne fêtes de fin d'année,

    Cordialement,

  7. #7
    Expert confirmé
    Merci pour ton retour.

    Weihnachten, Weihnachten, Wei Wei Weihnachten!
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus