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

Langage Perl Discussion :

Problème de remplissage d'un tableau de hash


Sujet :

Langage Perl

  1. #1
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut Problème de remplissage d'un tableau de hash
    Bonsoir

    j'essaie de faire un tit script qui permet de faire des calculs, j'ai besoin d'utiliser des tables de hash, pour récupérer des données d'un fichier excel.
    le problème : j'ai du mal avec la syntaxe
    sérieux, j'essaie de faire un code pour récupérer des données provenant d'une cellule, qui contient des éléments répétitives, je dois avoir finalement un tableau avec des données du genre {"valeur"=>nb,..}
    sachant que valeur est chaque valeur unique, et nb le nombre d'occurrence de cette valeur.
    voilà j'ai essayé avec ce code ci-dessus, mais j'ai du mal à remplir les tableaux..etc

    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
    63
    64
    65
    #!D:\Perl\bin
    use strict;
    use Win32::OLE qw(in with);
    use Win32::OLE::Const 'Microsoft Excel';
     
    $Win32::OLE::Warn = 3;                                # die on errors...
     
    # get already active Excel application or open new
    my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
        || Win32::OLE->new('Excel.Application', 'Quit');  
     
    # open Excel file
    my $Book = $Excel->Workbooks->Open("D:/PL/test1.xls"); 
    my $Sheet=$Book->Worksheets(1);
    my $table=$Sheet->Range("F1:F40")->{'Value'};
     
    my %recept_table =();
    my $i=0;
    my %hash_recept=();
     
    # fonction pour remplir un tableau d'élément 
    sub remplir 
    {
    my $recept_table=@_;
    foreach my $ref (@$table)
    {
         foreach my $scalar( @$ref)
         {  $i++;
            $recept_table->{$i}=$scalar ;
     
         }
     
    }
     
    }
     
    # la fonction pour remplir le tableau qui contient les éléments avec une clé pour chaque élément unique
    sub  hash_
    {
     (my $hash_recept,my $recept_table)=@_;
     
     
    foreach my $ref (@$recept_table)
      {
             foreach my $scalar( @$ref)
             {
              $hash_recept->{$scalar}=$i ;
              $i++;
     
             }
     
      }
    }
    #appel des fonctions 
    &remplir(\%recept_table);
    &hash_(\%hash_recept,\%recept_table);
     
    # pour tester ::
    while ((my $val, my $cle)=each %hash_recept )
    {
    print "la clé : " .$cle. " valeur ".$val."\n";
     
    }
     
    $Book->Close;
    l'erreur quand m'affiche c'est :
    Can't use string ("1") as a HASH ref while "strict refs" in use at new6.pl line 29.
    alors je ne peux pas faire sans référence, j'ai besoin des référence pour pouvoir parcourir après pour faire des calculs..etc
    j'étais un peu frustrée par la doc
    finalement j'opte pour la doc celle du package ActivePerl

    thx?
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  2. #2
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Bonjour,

    Ton problème n'est pas clair, je ne suis pas certaine d'avoir compris.
    je dois avoir finalement un tableau avec des données du genre {"valeur"=>nb,..}
    sachant que valeur est chaque valeur unique, et nb le nombre d'occurrence de cette valeur
    Donc un hash classique.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    foreach my $ref (@$table)
    {
         foreach my $scalar( @$ref)
         {  $i++;
            $recept_table->{$i}=$scalar ;
     
         }
     
    }
    Tu sembles vouloir créer un hash dont la valeur est celle récupée de excel et ta clé un nombre incrémenté.

    Can't use string ("1") as a HASH ref while "strict refs" in use at new6.pl line 29.
    Ton message d'erreur vient du faite que dans l'expression
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $recept_table->{$i}=$scalar ;
    $recept_table devrait être une référence de hash. Ici, $recept_table est un scalaire contenant la valeur1.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    sub remplir
    {
        my $recept_table=@_;
        ...
     
    }
    #appel des fonctions
    &remplir(\%recept_table);
    $recept_table est uns calaire qui va prendre comme valeur le nombre d'éléments contenanu dans @_
    Pour correctement récupérer ta référence tu dois faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $recept_table=$_[0];
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (my $recept_table)=(@_)


    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
    my $table=$Sheet->Range("F1:F40")->{'Value'};
    my %recept_table =();
     
    # fonction pour remplir un tableau d'élément 
    sub remplir 
    {
    my $recept_table=@_;
    foreach my $ref (@$table)
    {
         foreach my $scalar( @$ref)
         {  $i++;
            $recept_table->{$i}=$scalar ;
     
         }
     
    }
    &remplir(\%recept_table);
    Tu ne dois pas faire ainsi :
    Ton code n'est pas bien écrit. Tu déclares tes tableaux vides dans le script principal, tu les passes à tes sous programmes qui les remplissent mais ne renvoient rien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    sub remplir{
        my $table = $_[0];
        my %recept_table;
        foreach my $ref (@{$table}){
             map{$recept_table{$_}++}@{$ref};
        }
        my $ref = \%recept_table;
        return($ref)
    }
     
    my $ref_hash_recept = remplir($table);
    Tu passes à ton sous-programme les valeurs à traiter contenues dans $table et après le traitement tu renvoies le tableau contenant les résultats.
    Si tu veux compter le nombre d'occurence de chacune de tes valeurs, tu ne dois pas utiliser un $i++ mais directement faire un ++ dans ton tableau. Ici, %recept_table contient comme tu voulais la valeur excel comme clé et ne nombre d'occurences de celle-ci en valeur.


    Que doit faire ta fonction hash_ ?
    J'ai l'impression que tu te compliques les choses, tu crées un tableau listant simplement les valeurs avec ton premier sous-programme 'remplir' et ton second 'hash_' essaie de compter le nombre de fois que chaque valeur y est représentée.
    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
    my %recept_table =();
    my $i=0;
    my %hash_recept=();
     
    sub  hash_
    {
     (my $hash_recept,my $recept_table)=@_;
     
     
    foreach my $ref (@$recept_table)
      {
             foreach my $scalar( @$ref)
             {
              $hash_recept->{$scalar}=$i ;
              $i++;
     
             }
     
      }
    }
    Il y a déjà le problème que tu déclares un hash puis que tu le changes en array.
    -- Jasmine --

  3. #3
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Voici un script qui récupère les valeurs du tableau excel et calcule le nombre d'occurences de chacune d'elle.

    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
    #!D:\Perl\bin
    use strict;
    use Win32::OLE qw(in with);
    use Win32::OLE::Const 'Microsoft Excel';
    $Win32::OLE::Warn = 3;
     
     
    # fonction pour remplir un tableau d'élément
    sub remplir{
        my $table = $_[0];
        my %recept_table;
        foreach my $ref (@{$table}){
             map{$recept_table{$_}++}@{$ref};
        }
        my $ref = \%recept_table;
        return($ref)
    }
     
     
     
    # get already active Excel application or open new
    my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
        || Win32::OLE->new('Excel.Application', 'Quit');
     
    # open Excel file
    my $Book = $Excel->Workbooks->Open("D:/PL/test1.xls") or die "IMPOSSIBLE D'OUVRIR LE FICHIER\n"; 
    my $Sheet=$Book->Worksheets(1);
    my $table=$Sheet->Range("F1:F40")->{'Value'};
     
     
     
    my $ref_hash_recept;
    $ref_hash_recept = remplir($table);
     
    # pour tester ::
    while ((my $val, my $cle)=each %{$ref_hash_recept} ){
        print "valeur exl: " .$cle. " nbr occurences ".$val."\n";
    }
     
    $Book->Close;
    N'hésite pas à me poser des questions.
    -- Jasmine --

  4. #4
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    Il y a déjà le problème que tu déclares un hash puis que tu le changes en array.
    Je ne change pas un hash en array, mais je le traite comme si ça été un array, ça vient du problème que je ne trouve pas la bonne syntaxe, je galère avec la doc, et j'ai du mal avec la syntaxe, mais j'essaie toujours d'apprendre des choses d'après la doc, que je la trouve frustrante, je ne trouve que des choses dont j'ai pas besoin pour l'instant.
    Pour mon problème j'ai essayé de faire différemment avec une manière plus simple, et plus correcte.
    Je reviendrais Jasmine sur tes notifications plustard (j'ajouterai cette discussion à mes favoris pour que je m'en rappel XD)
    pour l'instant j'ai résolu le problème de remplissage du tableau de hash qui contient les données :
    clé=>valeur, clé est les données de la colonne, valeur est le nombre d'occurrence de cette clé.
    je dois récupérérer les lignes qui contient un nombre définit qui est le 80 pourcent des lignes qui contiennent la clé, aussi bien le reste des lignes qui représentent les 20 pourcent restantes (cette clé représente bien chaque valeur unique dans cette ensemble de données de cette colonne, cette colonne est sous le nom receptionnaire)
    je parle toujours d'un fichier excel qui contient plusieurs colonnes, parmi ces colonne celle dont j'ai crée un tableau de hash, pour faire un calcul par pourcentage, pour récupérer les 80 pourcents des lignes par receptionnaire.
    Finalement je dois récupérer deux fichiers un fichier, qui contient les 80 pourcents, un deuxième qui contient le reste cad les 20 pourcents.
    j'espère que c'est assez clair
    j'ai pu récupéré le nombre de lignes du fichier, il me reste celui des colonnes.
    ça c'est un problème, le deuxième problème et c'est ce que j'essaie de résoudre pour l'instant, et que j'arrive pas à ecrire dans les nouveaux fichiers xl80 et xl20, pour l'instant je fais juste le fichier xl80
    le 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
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    sub full_recept_table 
    {
     my $recept=@_;
     my $i=0;
     #my $file=@_;
     my $Excel = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');
     my $Workbook = $Excel->Workbooks->Open("C:/PL/APV.xls"); 
     my $Sheet = $Workbook->Worksheets(1);
     my $numRows = $Sheet->UsedRange->Find({What=>"*",SearchDirection=>xlPrevious,SearchOrder=>xlByRows})->{Row};
       # my $numCols=$Sheet->UsedRange->Find({What=>"*",SearchDirection=>xlPrevious,SearchOrder=>xlByCols})->{Col}; # ça me renvoie l'erreur ... [FONT=Georgia]Can't use an undefined value as a HASH reference at s.pl line 26[/FONT]
       # print $numRows ." ".$numCols;
       ################################## add new
       # création d'un nouveau classeur pour les 80 pourcent 
       $xl80 = Win32::OLE->new('Excel.Application');
       $xl80->{Visible} = 1;
       # nouveau workbook
       $xlbook80= $xl80->Workbooks->Add;
        my $i = 1;
    ###########################
     
     for (my $row=2;$row<=$numRows;$row++) 
     {
      my $nom_recep= $Sheet->Range("O".$row)->{'Value'};
      $recept->{$nom_recep}{'all'}++;
     }
     # pour ajouter des clés
     
     
     foreach my $f(keys %{$recept})
     {
      $recept->{$f}{'80'} = round ($recept->{$f}{'all'} * 80/100); 
      $recept->{$f}{'20'} = round ($recept->{$f}{'all'} * 20/100); 
     }   
     
     # vérifier les résultats 
     foreach my $f(keys %{$recept})
      {
      $nb_all+=$recept->{$f}{'r'} ;
     #print "\t".$f ."\tNBFiches = ".$recept->{$f}{'all'}."\t 80 = ".$recept->{$f}{'80'}."\n";
      }
     # print "tous = ".$nb_all."\n";
     
      #
     for (my $row=2;$row<=$numRows; $row++) 
      {
      my $recept_name = $Sheet->Range("O".$row)->{'Value'};
      if ($recept->{$recept_name}{'80'} > 0 )
      {
       for (my $col=1 ; $col<=15 ; $col++)
             {
        # ajouter la cellule à la colonne qui convient les 80 pourcent
        $x180->Range($col.$i)->{'Value'}= $Sheet->Range($col.$row)->{'Value'}
       } 
       #$i++;
       $recept->{$recept_name}{'80'}-=1;
      }
                 #print $line;
     
        #$count_80++; # combien y a t il des 80 pourcent 
        #print$recept->{$Sheet->Range("O".$row)->{'Value'}}{'80'}."\n";
        #ajout des données 
     
      elsif  ($recept->{$Sheet->Range("O".$row)->{'Value'}}{'20'}>0)
      {
       # ajouter dans le deuxième fichier excel les 20 pourcent 
       $recept->{$Sheet->Range("O".$row)->{'Value'}}{'20'}-=1;
       #$count_20++; # combien y a de 20 pourcent 
     
                }
     
     
     
         $i++;   
                     }
     
     
     # Clean up
     
         $xlbook80->{Saved} = 1;
         $xl80->Close;
         $xlbook80 = 0;
         $xl80 = 0;
     
      }
    Merci Jasmine
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  5. #5
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Pour le problème des colonnes, as-tu besoin du nombre d'occurences par colonne?

    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
    sub remplir{
        my $table = $_[0];
        my %recept_table;
        foreach my $ref (@{$table}){
            for (my $col=0; $col<@{$ref}; $col++){
                if((${$ref}[$col]) && (${$ref}[$col] =~ /\d+/)){
                $recept_table{$col}++;}
            }
        }
        my $ref = \%recept_table;
        return($ref)
    }
     
     
    ...
     
     
    my $ref_hash_recept;
    $ref_hash_recept = remplir($table);
     
    # pour tester ::
    while ((my $val, my $cle)=each %{$ref_hash_recept} ){
        print "Nombre d'occurences : " .$cle. " \t de la colonne".$val."\n";
    }
    Ce script devrait compter le nombre d'occurences par colonne. (il le fait mais j'y regarderai demain car là j'ai un RDv et je n'ai plus le temps).
    -- Jasmine --

  6. #6
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    Bonjour Jasmine

    my $table = $_[0]; # ça initialise un tableau avec une valeur..?
    my %recept_table; # c'est juste une déclaration sans initialisation?
    foreach my $ref (@{$table}){ # parcourir un tableau avec un indice ref, ça ne doit pas être un hash le table, sinon pourquoi un tableau?
    for (my $col=0; $col<@{$ref}; $col++){
    if($col){
    $recept_table{$col}++;}
    }
    }
    my $ref = \%recept_table; # ici je ne comprends pas ce que t'affectes
    return($ref)

    Finalement je n'essaie pas de trouver l'occurence des différents colonne que j'ai, les colonnes du fichier sont toutes uniques, je veux avoir combien j'ai de colonne, pour pouvoir les parcourir...
    mais le problème que j'ai pour l'instant c'est j'arrive pas à modifier le nouveau fichier par les valeurs que je récupére du fichier source.
    thx
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  7. #7
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    my $table = $_[0]; # ça initialise un tableau avec une valeur..?
    Quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ref_hash_recept = remplir($table);
    $ref_hash_recept contiendra le retour de la fonction (ici $ref)
    $ table est ce que j'envoie comme données à la fonction. Ces données sont envoyées via la variable spéciale de perl @_. Celle-ci est un array, pour accéder à ses éléments, on fait comme avec n'importe quel array en utilisant $_[index].
    my $table = $_[0]; passe donc $table du programme principale à $table du sous-programme.

    my %recept_table; # c'est juste une déclaration sans initialisation?
    Initialiser une variable signifie lui donner une valeur après l'avoir déclarée. Donc, en effet dans ce cas-ci, c'est une déclaration sans initialisation. Les variables sans initialisation ont une valeur spéciale qui est 'undef'.

    foreach my $ref (@{$table}){ # parcourir un tableau avec un indice ref, ça ne doit pas être un hash le table, sinon pourquoi un tableau?
    $table est une référence vers un array de array, je t'expliquerai plus loin.

    my $ref = \%recept_table; # ici je ne comprends pas ce que t'affectes
    return($ref)
    $ref est la référence vers %recept_table, déclarée par un \. Tu pourrais directement renvoyer la référence avec => return(\%recept_table)

    En fait $table est une référence vers un tableau complexe, un array de array.
    Admettons que dans excel tu aies 3 colonnes de 3 chiffres :
    1 4 7
    2 5 8
    3 6 9
    Voici ce que perl récupère dans $table (vue après avoir utilisé la fonction Dumper)
    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
    $VAR1 = [
              [
                '1',
                '4',
                '7'
              ],
              [
                '2',
                '5',
                '8'
              ],
              [
                '3',
                '6',
                '9'
              ]
            ];
    Cela équivaut en Perl à (façon de créer l'array équivalente dans le code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my @table= ( [
           [1,4,7],
           [2,5, 8],
           [3,6, 9], ]
           );
    Ton tableau $table, contient un array contenant lui même 3 arrays (1, 4, 7), (2, 5, 8) et (3, 6, 9) qui correspondent à tes 3 lignes.
    Si tu veux obtenir le tableau que j'affiche ici à l'écran tu dois faire (fais attention que ton tableau n'aies pas trop de données pour l'affichage à l'écran)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    use Data::Dumper;
    print Dumper $table;
    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    sub remplir_ligne{
        my $table = $_[0];
        my %recept_table;
        foreach my $ref (@{$table}){
             map{$recept_table{$_}++}@{$ref};
        }
        my $ref = \%recept_table;
        return($ref)
    }
    foreach my $ref (@{$table})
    => tu parcours le premier niveau d'array, l'array principale : @{$table}.
    map{$recept_table{$_}++}@{$ref};
    => tu parcours chaque sous niveau d'array @{$ref} (ici, 3)

    C'est un peu compliqué, donc n'hésite pas à me poser des questions, je ferais pour un mieux afin de te répondre.
    Voici un cours bien fait
    http://perso.univ-rennes1.fr/francoi...ERLnode15.html


    je veux avoir combien j'ai de colonne, pour pouvoir les parcourir...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        foreach my $ref (@{$table}){
             map{$recept_table{$_}++}@{$ref};
        }
    Ton nombre de lignes est le nombre de fois que tu rentres dans la boucle foreach my $ref (@{$table}) et donc de $ref (nombre d'éléments de @{$table}) que tu as.
    Ton nombre de colonnes est le nombre d'éléments que tu as par ligne et donc que tu as dans @{$ref}; (attention aux colonnes de tailles différentes).
    -- Jasmine --

  8. #8
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Je viens de repérer une erreur dans ton script
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    # pour tester ::
    while ((my $val, my $cle)=each %hash_recept ){
         print "la clé : " .$cle. " valeur ".$val."\n";
    }
    Tu dois inverser $val et $cle. Ici, $val prend tes valeurs de clés et $cle celles de tes valeurs.


    Pour ce qui est du nombre de colonnes
    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
    sub remplir{
        my $table = $_[0];
        my $nb_col;
        my $nb_lig = 0;
        my %recept_table;
        foreach my $ref (@{$table}){
            $nb_lig++;
            for (my $col = 0; $col<@{$ref}; $col++){
                if((${$ref}[$col]) && (${$ref}[$col] =~ /\d+/)){
                    $recept_table{${$ref}[$col]}++;
                    $nb_col = $col;
                }
            }
        }
        return(\%recept_table, $nb_col, $nb_lig)
    }
     
     
    my ($ref_recept_table, $nb_col, $nb_lig) = remplir($table);
    $nb_col++;  # car le nombre d'éléments d'un array est sont dernier indice + 1
     
    # pour tester :
    foreach my $key (sort {$a<=>$b} keys %{$ref_recept_table}){
        print "valeur excel : " .$key. " \tnombre d'occurences ".${$ref_recept_table}{$key}."\n";
    }
     
    my $nombre_val = (keys %{$ref_recept_table});
    print "nombre de valeurs différentes de mon tableau excel : $nombre_val\n";
    print "nombre de colonnes de mon tableau excel : $nb_col\n";
    print "nombre de lignes de mon tableau excel : $nb_lig\n";


    Pour ce qui est de ton problème de fichier de sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    sub full_recept_table 
    {
     my $recept=@_;
    Tu as déjà une erreur à la première ligne, tu ne récupèreras pas ta référence de cette façon, je t'ai déjà bien expliqué en détails le pourquoi dans un de mes précédents post. Que contient le tableau dont la référence est $recept, est-il vide à cette ligne comme la fois passée? Je t'ai également expliqué comment faire avec tes argurments et tes élements retournés par le sous-programme. Tu passes en arguments les données et tu renvoies les résultats au lieu de créer un tableau vide que tu passes à ton sous-programme afin de le remplir.
    -- Jasmine --

  9. #9
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    C'est un peu compliqué, donc n'hésite pas à me poser des questions, je ferais pour un mieux afin de te répondre.
    Voici un cours bien fait
    Oui c'est un peu pas assez clair pour l'instant, mais c'est pas grave je préfére peut être faire autrement...
    Ton nombre de lignes est le nombre de fois que tu rentres dans la boucle foreach my $ref (@{$table}) et donc de $ref (nombre d'éléments de @{$table}) que tu as.
    Ton nombre de colonnes est le nombre d'éléments que tu as par ligne et donc que tu as dans @{$ref}; (attention aux colonnes de tailles différentes).
    je ne me rappelle pas que j'ai dis que le nombre de colonne est égale au nombre différents que j'ai dans la colonne receptionnaire, ça n'a rien à voir avec le nombre de colonne que je cherche à récupérer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     for (my $col = 0; $col<@{$ref}; $col++){
                if((${$ref}[$col]) && (${$ref}[$col] =~ /\d+/)){
                    $recept_table{${$ref}[$col]}++;
                    $nb_col = $col;
                }
            }
    je ne comprends pas bien ce bout de code.
    Au cas ou ce code récupére juste l'indice de la colonne receptionnaire, c'est pas vraiment ce que je cherche à avoir, je veux pas l'indice, je veux savoir combien y a t il des colonnes, parce que le fichier que j'utilise peut avoir 15 colonne comme 10 ..etc
    alors que les lignes c'est encore pareil.
    Autre chose j'ai du mal à créer un nouveau fichier, pour l'instant je le créer manuellement pour le modifier par les résultats récupérés.
    Je cherche donc la méthode de création et de sauvegarde des données ajoutées.

    je dois dire que j'ai déjà résolu le problème de récupération des données pour les deux fichiers les 80% et les 20% des fiches, le 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
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    #!D:\Perl\bin
    use Win32::OLE qw(in with);
    use Win32::OLE::Const 'Microsoft Excel';
    use Math::Round qw(:all);
    my %recept=();
    my $count_80=0;
    my $count_20=0;
    my $nb_all=0;
    my @alpha=('A','B','C','D','E','F','G','H','I','J','K','L','M','N','M','O','P','Q','R','S','T');
    #my $file="C:/PL/VN.xls";
    &full_recept_table(\%recept);
    sub full_recept_table 
    {
     my $recept=@_;
     my $i=1;
     my $j=1;
     ##my $file=@_;
     my $Excel = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');
     my $Workbook = $Excel->Workbooks->Open("C:/PL/APV.xls"); 
     my $Sheet = $Workbook->Worksheets(1);
     my $numRows = $Sheet->UsedRange->Find({What=>"*",SearchDirection=>xlPrevious,SearchOrder=>xlByRows})->{Row};
        # #my $numCols=$Sheet->UsedRange->Find({What=>"*",SearchDirection=>xlPrevious,SearchOrder=>xlByCols})->{Col};
        # #print $numRows ." ".$numCols;
        ################################## add new
        ##création d'un nouveau classeur pour les 80 pourcent 
        my $xl80 = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');
        ## nouveau workbook  
        my $w80=$xl80->Workbooks->Open("C:/80.xls");
        my $Sheet80=$w80->Worksheets(1);
     
       ##un nouveau classeur pour les 20 pourcent
        my $xl20 = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');
        # #nouveau workbook  
        my $w20=$xl20->Workbooks->Open("C:/20.xls");
        my $Sheet20=$w20->Worksheets(1);
     
       ###########################
     
     for (my $row=2;$row<=$numRows;$row++) 
     {
      my $nom_recep= $Sheet->Range("O".$row)->{'Value'};
      $recept->{$nom_recep}{'all'}++;
     }
     # #pour ajouter des clés
     
     foreach my $f(keys %{$recept})
     {
      $recept->{$f}{'80'} = round ($recept->{$f}{'all'} * 80/100); 
      $recept->{$f}{'20'} = round ($recept->{$f}{'all'} * 20/100); 
     }   
     
     ## vérifier les résultats 
     #foreach my $f(keys %{$recept})
     # {
     # $nb_all+=$recept->{$f}{'r'} ;
     #print "\t".$f ."\tNBFiches = ".$recept->{$f}{'all'}."\t 80 = ".$recept->{$f}{'80'}."\n";
     # }
     ## print "tous = ".$nb_all."\n";
     
     for (my $row=2;$row<=$numRows; $row++) 
      {
      my $recept_name = $Sheet->Range("O".$row)->{'Value'};
     
      if ($recept->{$recept_name}{'80'} > 0 )
      {
       for (my $col=0 ; $col<=15 ; $col++)
             {
        ## ajouter la cellule à la colonne qui convient les 80 pourcent
        ##print $Sheet->Range($alpha[$col].$row)->{'Value'}."\n";
        $Sheet80->Range($alpha[$col].$i)->{'Value'}= $Sheet->Range($alpha[$col].$row)->{'Value'};
     
       } 
       $i++;
       $recept->{$recept_name}{'80'}-=1;
      }
                # #print $line;
     
        ##$count_80++; # combien y a t il des 80 pourcent 
        ##print$recept->{$Sheet->Range("O".$row)->{'Value'}}{'80'}."\n";
        ##ajout des données 
     
       elsif  ($recept->{$Sheet->Range("O".$row)->{'Value'}}{'20'}>0)
                      {
               ## ajouter dans le deuxième fichier excel les 20 pourcent 
        for (my $col=0 ; $col<=15 ; $col++)
     
           {
               ##$count_20++; # combien y a des 20 pourcent 
                $Sheet20->Range($alpha[$col].$j)->{'Value'}= $Sheet->Range($alpha[$col].$row)->{'Value'};
     
     
                         }
         $recept->{$recept_name}{'20'}-=1;
         $j++; 
          } 
     
     
                     }
     
     
     
     ## Clean up
     
         $Sheet80->Saved;
      $Sheet20->Saved;
         $w80->Close; 
         $w20->Close;
         ##$Sheet80 = 0;
         ##$w80 = 0;
     
      }
     
     
     
     ##print "nb fiches80 = ".$count_80."\t nbfiches20 = ".$count_20."\n";
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  10. #10
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    je ne me rappelle pas que j'ai dis que le nombre de colonne est égale au nombre différents que j'ai dans la colonne receptionnaire, ça n'a rien à voir avec le nombre de colonne que je cherche à récupérer.
    Je ne comprends pas le chinois, quelle est la traduction en français?

    je ne comprends pas bien ce bout de code.
    Au cas ou ce code récupére juste l'indice de la colonne receptionnaire, c'est pas vraiment ce que je cherche à avoir, je veux pas l'indice, je veux savoir combien y a t il des colonnes, parce que le fichier que j'utilise peut avoir 15 colonne comme 10 ..etc
    Vu que chaque colonne se voit attribuer un nouvel indice, cela est équivalent sauf dans le cas où tu as des colonnes vides dans ton fichier excel.
    Tant que tu n'auras pas essayé de comprendre mes explications au sujet de l'array d'array, tu ne comprendras pas mon script.
    -- Jasmine --

  11. #11
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    je ne me rappelle pas que j'ai dis que le nombre de colonne est égale au nombre différents que j'ai dans la colonne receptionnaire, ça n'a rien à voir avec le nombre de colonne que je cherche à récupérer.
    Citation Envoyé par Jasmine80 Voir le message
    Je ne comprends pas le chinois, quelle est la traduction en français?
    En écrivant ça je me rappelle bien que je faisais deux autres choses en parallèle, je parlais à mes collègues au boulot, et je répondais à un mail et je lisais ton message

    Citation Envoyé par Jasmine80 Voir le message
    Voici ce que perl récupère dans $table (vue après avoir utilisé la fonction Dumper) .......Cela équivaut en Perl à (façon de créer l'array équivalente dans le code)
    Je pense que je ne suis pas la seule à parler chinois
    Tu ne précises pas de quel code tu parles, on parle toujours du langage perl ..sinon de quel autre façon tu parles...

    Je n'avais pas assez de temps pour lire tout ce que tu expliquais en haut, je devais résoudre le problème rapidement, pour moi, résoudre des problèmes, gérer des imprévus, trouver une solution rapide ça fait parti de mon boulot, qui prend la totalité de mon temps, et qui n'est pas forcément de la programmation...j'ai fais ce code à l'arrache lol

    je devais dire dès le début que cette façon de récupérer les données d'une colonne d'un fichier excel n'est pas la bonne, la variable $table que j'ai utilisé la première fois ne retourne qu'une seule valeur de la première ligne de la colonne receptionnaire!!
    Ce qui veut dire que ce tableau ne doit pas être rempli de cette façon...
    la fonction range ne permet pas d'extraire les données d'une seule colonne, ça doit extraire une tranche de cellule, lignes+colonnes ...
    genre my $table=$Sheet->Range("A1:N40")->{'Value'};
    Ok c'est sur que je dois parcourir tout le fichier, puisque finalement je cherche à récupérer le nombre de lignes et le nombre de colonnes, pour le nombre de lignes j'ai déjà utilisé une fonction, pour les colonnes...je cherche toujours...
    Le code que tu m'as envoyé prend la cellule qui contient comme valeur des chiffres, comme cellule receptionnaire!
    c'est déjà ce que j'ai remarqué avec la condition que t'as utilisé ..
    foreach my $ref (@{$table}){
    $nb_lig++;
    for
    (my $col = 0; $col<@{$ref}; $col++){
    if((${$ref}[$col]) && (${$ref}[$col] =~ /\d+/)){
    $recept_table{${$ref}[$col]}++;
    $nb_col = $col;
    }
    }
    }
    pourquoi cette condition :(${$ref}[$col]) et tu cherches la colonne qui contient comme valeur des chiffres? (${$ref}[$col] =~ /\d+/)
    la colonne que je veux traiter c'est une colonne de format string, ce sont juste des noms.
    j'ai un autre souci, mais je dois le mettre dans un new thread.

    ++
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  12. #12
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    je devais dire dès le début que cette façon de récupérer les données d'une colonne d'un fichier excel n'est pas la bonne, la variable $table que j'ai utilisé la première fois ne retourne qu'une seule valeur de la première ligne de la colonne receptionnaire!!
    J'arrive à récupérer un tableau excel composé de plusieurs lignes et de plusieurs colonnes pourtant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $table=$Sheet->Range("F1:F40")->{'Value'};
    Tu dois indiquer la première ligne de ta première colonne (coin supérieur gauche du tableau excel) et la dernière ligne de ta dernière colonne (coin inférieur droit du tableau). Avec Range("F1:F40") tu ne récupères que les 40 lignes de ta première colonne. Est-ce clair?

    cellule receptionnaire!
    Que veux-tu dire?

    pourquoi cette condition ${$ref}[$col]) et tu cherches la colonne qui contient comme valeur des chiffres? (${$ref}[$col] =~ /\d+/)
    la colonne que je veux traiter c'est une colonne de format string, ce sont juste des noms.
    (${$ref}[$col]) afin de vérifier que la valeur soit définie
    (${$ref}[$col] =~ /\d+/) afin de vérifier que la valeur soit un chiffre, remplace cela par (${$ref}[$col] =~ /\w+/) afin de vérifier que ce soit un string.
    -- Jasmine --

  13. #13
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    ...Avec Range("F1:F40") tu ne récupères que les 40 lignes de ta première colonne. Est-ce clair?
    .....
    (${$ref}[$col]) afin de vérifier que la valeur soit définie
    (${$ref}[$col] =~ /\d+/) afin de vérifier que la valeur soit un chiffre, remplace cela par (${$ref}[$col] =~ /\w+/) afin de vérifier que ce soit un string.
    D'accord pour le range, je comprends que ça peut récupérer les données de la première colonne de cette façon, si la colonne se trouve au milieu ça devient compliqué...
    Le problème c'est la variable $col, celle ci ne prend que le nombre des colonnes qui précede la colonne receptionnaire, qui est censé être la première colonne du fichier, ce qui veut dire que ça prendrai comme valeur 0 et que ça ne résout pas le problème du nombre de colonne du fichier qui est pour l'instant 15 et qui pourra être moins ou plus....
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

  14. #14
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Le problème c'est la variable $col, celle ci ne prend que le nombre des colonnes qui précede la colonne receptionnaire, qui est censé être la première colonne du fichier, ce qui veut dire que ça prendrai comme valeur 0 et que ça ne résout pas le problème du nombre de colonne du fichier qui est pour l'instant 15 et qui pourra être moins ou plus....
    Désolée, mais je ne comprends pas, je suis même complètement larguée. Dans mon fichier excel, j'ai 3 colonnes et $col prend bien la valeur 3. Qu'appelles-tu colonne réceptionnaire? Sur mon fichier excel contenant plusieurs colonnes et plusieurs lignes, toutes les données sont récupérées et tout fonctionne comme je pensais que tu voulais que cela le fasse. Je ne vois pas du problème dont tu veux parler. Explique la structure de tes données excel que je teste mon programme sur un fichier similaire au tien et explique concrètement ce que tu dois récupérer comme informations dans ce fichier.
    -- Jasmine --

  15. #15
    Membre actif Avatar de CKLN00
    Homme Profil pro
    Bioinformaticien Java/Perl
    Inscrit en
    Avril 2008
    Messages
    210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Bioinformaticien Java/Perl
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2008
    Messages : 210
    Points : 263
    Points
    263
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    Explique la structure de tes données excel que je teste mon programme sur un fichier similaire au tien et explique concrètement ce que tu dois récupérer comme informations dans ce fichier.
    +1
    je suis tes post depuis qq temps witch17 et je doit avouer que j'ai du mal à comprendre ce que tu veut faire. donc le mieux serais que tu nous montre un extrait de fichier Excel, et que tu nous dise par rapport à ce fichier ce que tu voudrais récupérer exactement
    CKL
    N°°b forever
    --
    may the be with you

  16. #16
    Membre averti
    Avatar de witch
    Inscrit en
    Mai 2007
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 37

    Informations forums :
    Inscription : Mai 2007
    Messages : 346
    Points : 335
    Points
    335
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    Désolée, mais je ne comprends pas, je suis même complètement larguée. Dans mon fichier excel, j'ai 3 colonnes et $col prend bien la valeur 3. Qu'appelles-tu colonne réceptionnaire? Sur mon fichier excel contenant plusieurs colonnes et plusieurs lignes, toutes les données sont récupérées et tout fonctionne comme je pensais que tu voulais que cela le fasse. Je ne vois pas du problème dont tu veux parler. Explique la structure de tes données excel que je teste mon programme sur un fichier similaire au tien et explique concrètement ce que tu dois récupérer comme informations dans ce fichier.
    Bonjour Jasmine

    oui ça marche aussi bien pour moi, là j'ai l'avantage d'avoir deux solutions au lieu d'une seule grace à toi.
    Le problème de récupérer le nombre de colonnes du fichier, n'est toujours pas résolu, mais le plus important est fait
    le fichier excel, est un simple fichier qui contient plusieurs colonnes, ça commence par ces champs:
    intitule tel date achat model version famille client ..etc

    Ils sont quasiment des string, le champ date est de type date, le champ tel ça peut être de type entier, le reste c'est du text.

    Le script ça fonctionne très bien sauf pour la récupération du nombre de colonne, ça prend comme valeur 1, ça prend toujours cette valeur même si j'enleve la condition (${$ref}[$col] =~ /\w+/)

    thx
    If a pretty poster and a cute saying are all it takes to motivate you, you probably have a very easy job. The kind robots will be doing soon.

Discussions similaires

  1. Problème avec un hash de tableau de hash
    Par hy00ga dans le forum Langage
    Réponses: 1
    Dernier message: 21/10/2011, 15h10
  2. Problème de remplissage d'un tableau
    Par Peedro dans le forum Collection et Stream
    Réponses: 1
    Dernier message: 02/10/2008, 18h38
  3. Réponses: 16
    Dernier message: 01/06/2008, 20h01
  4. Réponses: 3
    Dernier message: 08/02/2008, 20h10
  5. Problème de récupération de tableau dans hash DBM
    Par siaoly dans le forum Langage
    Réponses: 1
    Dernier message: 01/05/2006, 16h00

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