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 PHP Discussion :

Effectuer un traitement sur 2 champs csv


Sujet :

Langage PHP

  1. #1
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut Effectuer un traitement sur 2 champs csv
    Bonjour à tous,

    j'ai un webservice qui me crache des données sous cette forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    "JAHR";"PERIODE";"VERSION";"EINHEIT";"PARTNER";"KATEGORIE";"GUV-KZ";"AUFTRAG";"BELEGNR";"BELEGART";"SATZNUMMER EINZELPOSTENSATZ";"LEDGER";"SATZART";"BUCHUNGSKREIS";"HERKUNFTSOBJEKT";"VORGANG";"EMPFAENGER OBJEKTART";"REFERENZBELEGNUMMER";"BUCHUNGSTEXT";"DEBITOR";"DEBITORNAME";"KREDITOR";"KREDITORNAME";"BETRAG IN EUR";"#VALUE"\r\n
    "2014";"5";"IST";"A100000";"Extern";"NA";"0000041310";"000050008680";"0011263941";"A";"000000000045695588";"8A";"0";"2383";"03";"RMRP";"00";"5105632164";"Kopierpapier ECONOMY, A4, 80 g/qm, ";"-194.25";"-0.19425"
    avec souvent beaucoup plus de lignes (et le nombre de colonnes peut être variable)

    mon but ce serait d'effectuer un traitement dans la seconde ligne sur les 2 dernières colonnes (entre autres remplacer le "." par une ",") ; en sortie j'ai besoin d'exactement du même format (avec les guillemets et les points virgules), c'est à dire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    "JAHR";"PERIODE";"VERSION";"EINHEIT";"PARTNER";"KATEGORIE";"GUV-KZ";"AUFTRAG";"BELEGNR";"BELEGART";"SATZNUMMER EINZELPOSTENSATZ";"LEDGER";"SATZART";"BUCHUNGSKREIS";"HERKUNFTSOBJEKT";"VORGANG";"EMPFAENGER OBJEKTART";"REFERENZBELEGNUMMER";"BUCHUNGSTEXT";"DEBITOR";"DEBITORNAME";"KREDITOR";"KREDITORNAME";"BETRAG IN EUR";"#VALUE"\r\n
    "2014";"5";"IST";"A100000";"Extern";"NA";"0000041310";"000050008680";"0011263941";"A";"000000000045695588";"8A";"0";"2383";"03";"RMRP";"00";"5105632164";"Kopierpapier ECONOMY, A4, 80 g/qm, ";"-194,25";"-0,19425"
    j'ai essayé plusieurs méthodes:

    1/ avec str_csv :
    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
    $mystring='"JAHR";"PERIODE";"VERSION";"EINHEIT";"PARTNER";"KATEGORIE";"GUV-KZ";"AUFTRAG";"BELEGNR";"BELEGART";"SATZNUMMER EINZELPOSTENSATZ";"LEDGER";"SATZART";"BUCHUNGSKREIS";"HERKUNFTSOBJEKT";"VORGANG";"EMPFAENGER OBJEKTART";"REFERENZBELEGNUMMER";"BUCHUNGSTEXT";"DEBITOR";"DEBITORNAME";"KREDITOR";"KREDITORNAME";"BETRAG IN EUR";"#VALUE"' . "\r\n";
    $mystring.='"2014";"5";"IST";"A100000";"Extern";"NA";"0000041310";"000050008680";"0011263941";"A";"000000000045695588";"8A";"0";"2383";"03";"RMRP";"00";"5105632164";"Kopierpapier ECONOMY, A4, 80 g/qm, ";"-194.25";"-0.19425"';
     
    $array1=str_getcsv($mystring,"\r\n");
     
    $array2=array_map(function ($theArray)
    {
    	$theArrayCsvToArray=str_getcsv($theArray,';','"');
     
    	$theValue1=$theArrayCsvToArray[count($theArrayCsvToArray)-1];
    	$theValue1=str_replace('.',',',$theValue1);
    	$theValue1=(strpos($orig,'E'))?substr($theValue1,0,strpos($theValue1,'E')):$theValue1;
     
    	$theValue2=$theArrayCsvToArray[count($theArrayCsvToArray)-2];
    	$theValue2=str_replace('.',',',$theValue2);
    	$theValue2=(strpos($orig,'E'))?substr($theValue2,0,strpos($theValue2,'E')):$theValue2;
     
    	$theArrayCsvToArray[count($theArrayCsvToArray)-1]=$theValue1;
    	$theArrayCsvToArray[count($theArrayCsvToArray)-2]=$theValue2;
    	return $theArrayCsvToArray;
    }
    ,$array1);
     
    print_r($array2);
    ça fonctionne mais il faut que je remette les guillemets et que je reimplose 2 fois, 1 pour les ";" et l'autre pour les \r\n. or pour des raisons de performances je souhaiterais me passer d'une ou deux itérations supplémentaire sur le tableau

    2/ en recherchant la position de chaque "\r\n" pour ensuite remonter aux 2 dernières colonnes mais ca n'est pas très pratique...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $mystring='"JAHR";"PERIODE";"VERSION";"EINHEIT";"PARTNER";"KATEGORIE";"GUV-KZ";"AUFTRAG";"BELEGNR";"BELEGART";"SATZNUMMER EINZELPOSTENSATZ";"LEDGER";"SATZART";"BUCHUNGSKREIS";"HERKUNFTSOBJEKT";"VORGANG";"EMPFAENGER OBJEKTART";"REFERENZBELEGNUMMER";"BUCHUNGSTEXT";"DEBITOR";"DEBITORNAME";"KREDITOR";"KREDITORNAME";"BETRAG IN EUR";"#VALUE"' . "\r\n";
    $mystring.='"2014";"5";"IST";"A100000";"Extern";"NA";"0000041310";"000050008680";"0011263941";"A";"000000000045695588";"8A";"0";"2383";"03";"RMRP";"00";"5105632164";"Kopierpapier ECONOMY, A4, 80 g/qm, ";"-194.25";"-0.19425"' . "\r\n";
    $mystring.='"2014";"5";"IST";"A100000";"Extern";"NA";"0000041310";"000050008680";"0011263941";"A";"000000000045695588";"8A";"0";"2383";"03";"RMRP";"00";"5105632164";"Kopierpapier ECONOMY, A4, 80 g/qm, ";"-194.25";"-0.19425"';
     
    $needle = "\r\n";
    $lastPos = 0;
    $positions = array();
     
    while (($lastPos = strpos($mystring, $needle, $lastPos))!== false) {
        $positions[] = $lastPos;
        $lastPos = $lastPos + strlen($needle);
    }
     
    print_r($positions);
    auriez vous une idée plus simple pour faire ça ?

    D'avance merci !
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

  2. #2
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Par défaut
    Tu utilise mal le deuxième paramètre de la fonction str_getcsv. C'est ce qui te permet de définir le délimiteur de chaque champ, et non de chaque ligne. Celui-ci est par défaut la virgule, or dans ton cas c'est le point virgule, voilà pourquoi il te faut faire deux fois l'extraction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $array1=str_getcsv($mystring,';');
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  3. #3
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut
    Bonjour Spartacusply et merci pour ta réponse,

    en fait selon moi je dois d'abord séparer les lignes (séparateur \r\n) puis les colonnes (séparateur ";") ; sinon comment identifier les 2 derniers champs de la ligne ?

    voilà pourquoi je fais 2 fois l'extraction avec 2 séparateurs différents

    ou alors je fais complètement fausse route ?
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

  4. #4
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Par défaut
    Ok, en effet je vois le problème.

    En fait, la première séparation (avec "\r\n") devrait être faites dans la fonction str_getcsv (enfin pour moi logiquement, ça devrait être le cas). Or, en lisant les commentaires (notamment celui-là, http://php.net//manual/fr/function.s...csv.php#101888) de la doc il s'avère que... non. Ce qui nécessite dans tous les cas deux séparations, tu n'as pas le choix, ta fonction n'est pas si mal que ça.

    Après pour le chemin inverse, je suppose que tu vas bien finir par l'écrire dans un fichier cette string, tu peut donc te simplifier la tâche en utilisant directement la fonction fputcsv.
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  5. #5
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut
    Ce qui nécessite dans tous les cas deux séparations, tu n'as pas le choix, ta fonction n'est pas si mal que ça.
    okay, alors qu'il en soit ainsi, je vais me débrouiller avec

    Après pour le chemin inverse, je suppose que tu vas bien finir par l'écrire dans un fichier cette string, tu peut donc te simplifier la tâche en utilisant directement la fonction fputcsv.
    en fait non, la chaine en bout de script est renvoyée dans une interface web qui a besoin de ce format pour l'interpréter.

    du coup fputcsv ne me semble pas utile içi. A moins de l'utiliser en combinaison avec les fonctions ob_* ? Est-ce possible du fait que fputcsv attend un fichier ouvert ?
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

  6. #6
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  7. #7
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut
    Ah impecc, merci beaucoup, je vais chercher de ce coté là !

    bonne journée
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Si par hasard les champs que tu vises sont les seules à contenir des points (c'est peu probable, mais si c'est le cas, ça serait dommage de passer à coté, car c'est ~500 fois plus rapide et plus court), la solution la plus rapide (et la plus simple) est d'utiliser strtr:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $result = strtr($mystring, '.', ',');
    Mais dans le monde réel, j'imagine que ce n'est pas le cas, donc tu peux t'en tirer avec ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $pattern = '~
    (?:                            # positions de départ:
        \G(?!\A)                   #  - contigue à la correspondance précédente (mais pas en début de chaîne)
      |                            # ou
        (?="[0-9.-]+";"[0-9.-]+"$) #  - position des deux derniers champs d\'une ligne contenants des nombres
    )
    [^.\r\n]*                      # zero ou plus de caractères n\'étant ni un point ni une nouvelle ligne
    \K                             # (Keep out): enlève tout ce qui a été trouvé précédement du résultat
    \.                             # pour ne garder que le point
    ~mx'; // le modificateur m fait que l'ancre $ signifie "fin de ligne", x autorise les espaces et les commentaires
    $result = preg_replace($pattern, ',', $mystring);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  9. #9
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut
    Salut CosmoKnacki,

    décidément les regexp sont vraiment le language des Dieux, j'espère un jour savoir le parler...

    ca fonctionne impeccable (et super bien documenté en plus )

    Merci infiniment à vous deux pour votre aide et vos conseils !
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

  10. #10
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Salut,

    les regexp sont vraiment le langage des Dieux
    oui dans le sens où elles peuvent faire autant de bien que de mal si elles sont mal utilisées ou mal codées (tout dépend du panthéon, du caractère et de l'humeur des dieux en question). Elle s'apprennent relativement facilement car il n'y a pas tant de fonctionnalités et de notions que ça, mais nécessitent de la pratique (elles sont donc accessible aux simples mortelles). Elles permettent de manière concise de réaliser des tâches complexes, mais elles ne font pas de miracle. Si elles se défendent bien contre bon nombre de paquets de nouilles soi-disant plus faciles à maintenir (et là pour le coup on rentre dans le prêchi-prêcha) et composés de boucles, de tests et de fonctions de traitement de chaînes (pourtant très rapides), elles peuvent aussi montrer leurs limites face à un bon algorithme avec un choix judicieux de fonctions qui lui n'est ni soumis au backtracking, ni limiter par une marche de gauche à droite (entre autres choses). C'est pour ça que j'ai suggéré strtr qui est absolument imbattable pour les remplacements de caractères (ou de chaînes fixes d'ailleurs).

    Quelques ressources:
    • Le tutoriel de Guillaume Rossolini: une introduction au regex PHP, bien pour connaitre le minimum syndicale.
    • Le manuel PHP: qui décrit la plupart des fonctionnalités mais pas tout.
    • La doc de PCRE: qui est le moteur de regex de PHP, donc exhaustif cette fois.
    • regular-expressions.info: un site assez bien fait sur les fonctionnalités regex pour divers langages.
    • www.rexegg.com: le blog de Jeff, décrit de manière détaillé plusieurs fonctionnalités et constructions avancés
    • Le livre "Mastering Regular Expressions" de Jeffrey Friedl chez O'Reilly: l'intérêt principale est la description précise du fonctionnement d'un moteur de regex, et comment composer et optimiser ses expressions. C'est un livre très complet, une référence. On trouve les anciennes éditions gratuitement sur le net.


    Pour tester:
    • www.regex101.com: coloration syntaxique, description des éléments de la pattern, avec débogueur (ce qui est juste indicatif, ne reflète ni le temps réel ni les optimisations en amont de l'analyse) et génération de code. Ne supporte pas le modificateur inline (?J) et renvoie un timeout avec (*UTF8). Permet de changer le délimiteur
    • regex.larsolavtorvik.com: un peu spartiate, une coloration des résultats un peu aléatoire. mais supporte preg_split, (?J), (*UTF8) mais pas (*UCP). Il affiche un array de résultat comme en PHP. Il permet de tester les expressions POSIX.
    • Le logiciel RegexBuddy: timer, debugger, coloration syntaxique, supporte plusieurs moteurs de regex...
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  11. #11
    Membre éclairé Avatar de laloune
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mai 2005
    Messages
    484
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Mai 2005
    Messages : 484
    Points : 873
    Points
    873
    Par défaut
    le tutoriel de Guillaume Rossolini est particulièrement bien informatif, car il compare toujours avec strpos, ce qui permet de bien comprendrece que chaque chose fait...

    merci encore
    laloune
    Consultant B.I.
    Spécialité(s): Excel, SQL, Business Intelligence (Jedox Palo, Talend)

    "A problem worthy of attack proves its worth by fighting back." Piet Hein

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/03/2017, 18h45
  2. effectuer un test sur deux champ
    Par patmar83 dans le forum VBA Access
    Réponses: 2
    Dernier message: 25/04/2009, 22h45
  3. Réponses: 3
    Dernier message: 07/08/2008, 11h17
  4. Réponses: 39
    Dernier message: 11/01/2007, 11h31
  5. [SQL2K][TSQL] effectuer un traitement sur un booléen
    Par pcdj dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 22/08/2006, 11h39

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