Fichier CSV : Colonnes qui disparaissent

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Fichier CSV : Colonnes qui disparaissent

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 26 juin 2015, 18:28

Salut, alors pour les notes à 0, la comme ça aucune idée. A priori avec le code que je t'ai proposé, il n'y a pas de raison.
Et pour les noms et prénoms en majuscule, if suffit de l'ajouter lors du prepare_datas :

Code : Tout sélectionner

$students[$student_id] = array( 'login' => $type == 'other' ? $login_converter[substr($login, 0, 2)].substr($login, 2) : $login, 'nom' => strtoupper($nom), 'prenom' => strtoupper($prenom) );
Le code complet repris et corrigé (avec arrondi à une décimal sur la note) :

Code : Tout sélectionner

/* tableau de convertion des logins */ $login_converter = array(); $chars = 'abcdefghijklmnopqrstuvwxyz'; for($i = 0; $i < strlen($chars); $i++) $login_converter['i'.$chars[$i]] = 208 + $i; /* fonction de préparation des données pour comparaisons */ function prepare_datas($datas, $type) { global $login_converter; $students = array(); foreach(explode("\n", $datas) as $student) { /* saute la première ligne du fichier */ if(strtolower(substr($student, 0, 5)) == 'login') continue ; /* extrais les colonnes de la ligne */ list($login, $nom, $prenom, $note_1, $note_2, $note_3, $note_4, $note_5) = explode(';', $student); /* stocke les données sous une forme exploitable pour les comparaisons */ /* indexe les données sur nom-prenom pour un accès simple lors des comparaisons */ $student_id = strtoupper($nom).'-'.strtoupper($prenom); $students[$student_id] = array( 'login' => $type == 'other' ? $login_converter[substr($login, 0, 2)].substr($login, 2) : $login, 'nom' => strtoupper($nom), 'prenom' => strtoupper($prenom) ); /* stocke les notes en remplaçant les , par des . dans le cas d'apogée (pour comparaison numérique) et en les mettant /20 dans l'autre cas */ for($i = 1; $i < 6; $i++) { $varname = 'note_'.$i; $note = $$varname; $students[$student_id][$varname] = $type == 'other' ? number_format(substr($note, 0, -2), 1, ',', '') / 5 : $note; } } return $students; } /* charge les fichiers */ $students_a = prepare_datas(file_get_contents('A.csv'), 'apogee'); $students_b = prepare_datas(file_get_contents('B.csv'), 'other'); /* compare les données et met à jour $a en fonction des comparaisons faites avec $b */ foreach($students_a as $student_id => $student_a) { /* si l'élève n'existe pas dans B on saute la ligne */ if(!isset($students_b[$student_id])) continue ; $student_b = $students_b[$student_id]; /* mets à jour le login le cas échéant */ if($student_b['login'] != $student_a['login']) $student_a['login'] = $student_b['login']; /* mets à jour les notes le cas échéant */ for($i = 1; $i < 6; $i++) { if(str_replace(',', '.', $student_b['note_'.$i]) > str_replace(',', '.', $student_a['note_'.$i])) $student_a['note_'.$i] = $student_b['note_'.$i]; } /* met à jour l'étudiant dans le tableau d'origine */ $students_a[$student_id] = $student_a; } /* enregistre les données à jour */ $students = array('Login;Nom;Pr_nom;Note;Note;Note;Note;Note'); foreach($students_a as $student) $students[] = implode(';', $student); file_put_contents('C.csv', implode("\n", $students)); /* traitement des étudiants présents dans B mais pas dans A */ $students_d = array(); foreach($students_b as $student_id => $student_b) { /* si l'élève n'existe pas dans A on l'ajoute dans D */ if(!isset($students_a[$student_id])) $students_d[] = $student_b;// inutile de mettre l'id en index car l'index ne sera jamais utilisé } /* enregistrement */ $students = array('Login;Nom;Pr_nom;Note;Note;Note;Note;Note'); foreach($students_d as $student) $students[] = implode(';', $student); file_put_contents('D.csv', implode("\n", $students));

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 26 juin 2015, 16:42

C'est encore moi :3
Le programmeur assisté par excellence.

Dis moi, saurais tu pourquoi mon fichier D.csv m'affiche des notes à zéro?
Aussi je n'ai pas réussi à afficher en majuscule les noms et prénoms, malgré un strtoupper, un array_map, ou encore un enieme tableau
http://www.innovativephp.com/converting ... functions/

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 25 juin 2015, 11:25

Salut, alors pour forcer l'affichage des erreurs tu peux essayer d'ajouter ça au début du fichier :
ini_set('display_errors', 1);
error_reporting(E_ALL);
Mais une syntaxe error ne s'affichera pas. étant donné que le script ne sera pas exécuté dans ce cas.
Tu peux faire un tail -f sur le fichier de log d'erreurs dans le terminal.
Tu peux modifier la directive de configuration display_errors dans le php.ini.

Sinon j'ai l'impression qu'il y a un petit problème d'accolades, 3 fermantes pour 2 ouvrantes.
Il ne sert à rien de comparer $student_b et $student_d puisque tu pousses $student_b dans $students_d. $student_d est donc strictement identique à $student_b.
De plus tu utilises $student_d alors qu'il n'est jamais défini (attention au s à student, avec un s c'est le tableau, sans s c'est une ligne du tableau).
La boucle que je t'ai proposée dans mon post précédent est suffisante, il n'y a rien de plus à faire (à part éventuellement remettre des , à la place des . si c'est nécessaire).

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 25 juin 2015, 11:04

Bon je t'embête un dernière fois :P

Vu que je fais ca dans le cadre d'un stage, je dois bosser sous Mac et il m'est impossible d'afficher les erreurs quand je run le script :D ( a part de simples arrays vides)

Brievement, cela te sembles-t-il correct ?

Code : Tout sélectionner

$students_d = array(); foreach($students_b as $student_id =>$student_b) { /* si l'elève n'existe pas dans A on l'ajoute dans D */ if(!isset($students_a[$student_id])) $students_d[] = $student_b; if($student_b['login'] != $student_d['login']) $student_d['login'] = $student_b['login']; for($i = 1; $i<6; $i++){ if($student_b['note_'.$i] > $student_d['note_'.$i]) $student_d['note_'.$i] = $student_b['note_'.$i]; } $students_d[$student_id] = $student_d; } } // Fichier D avec présence des étudiants du B $handle = fopen('D.csv', 'w'); fputcsv($handle, array('Login','Nom','Prenom','Note','Note','Note','Note','Note'),';','"'); foreach ($students_d as $student) { fputcsv($handle, $student, ';', '"'); } fclose($handle); ?>

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 24 juin 2015, 17:11

J'en pense que le code ne fait pas ce que tu énonces ! ;)
Et j'ai dit une bêtise dans mon post précédent.

Ce que le test suivant permet de faire c'est de savoir qu'un étudiant du fichier A n'existe pas dans B et donc cela permettrait de stocker ces dits étudiants dans un troisième fichier.
/* si l'élève n'existe pas dans B on saute la ligne */
if(!isset($students_b[$student_id]))
  continue ;
Toi tu veux stocker dans un troisième fichier les étudiants présents dans B mais pas dans A.
Or la boucle ne passe jamais sur ces étudiants puisqu'elle boucle sur les étudiants de A.

Il faudrait donc ajouter une nouvelle boucle sur les étudiants de B et quand l'étudiant n'est pas présent dans A l'ajouter dans un tableau, disons $students_d comme le fichier va s'appeler D.csv.
$students_d = array();
foreach($students_b as $student_id => $student_b)
{
  /* si l'élève n'existe pas dans A on l'ajoute dans D */
  if(!isset($students_a[$student_id]))
    $students_d[] = $student_b;// inutile de mettre l'id en index car l'index ne sera jamais utilisé
}
Pour ce qui est de l'enregistrement c'est ok. Tu pourrais éventuellement faire une fonction pour ça.

A noter : la reconversion des , en . sur les notes n'est pas faite dans certains cas. Dans le cas des étudiants présents dans A mais pas dans B étant donné qu'on saute la ligne sans plus de traitement. Et maintenant dans le cas des étudiants présents dans B mais pas dans A.
Donc tu peux soit ajouter les traitements nécessaires pour faire ces conversions quand elles ne sont pas faites. Soit tu fais la conversion , vers . uniquement pour les comparaisons. Et je pense que personnellement je choisirai cette deuxième alternative.

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 24 juin 2015, 16:25

J'ai décidé de créer un tableau students_c qui regroupera les etudiants présents dans B et absents dans A
J'ai ecris ce code mais je crois mettre quelques peu emmelés les pinceaux dans les variables a/b/c

Code : Tout sélectionner

/* charge les fichiers */ $students_a = prepare_datas(file_get_contents('ApogeeSaisieFull.csv'), 'apogee'); $students_b = prepare_datas(file_get_contents('synthetiques_13_520.csv'), 'other'); /* compare les données et met à jour $a en fonction des comparaisons faites avec $b */ foreach($students_a as $student_id => $student_a) { // TODO : gerer présence étudiants dans B uniquement // si etudiant present dans B if(isset($students_b[$student_id])) { $student_c = $students_b[$student_id]; if($student_c['login'] != $student_a['login']) $student_a['note_'.$i] = $student_c['login']; for($i =1; $i <6; $i++){ if($student_c['note_'.$i] > $student_a['note_'.$i]) $student_a['note_'.$i] = $student_c['note_'.$i]; $student_a['note_'.$i] = str_replace('.', ',', $student_a['note_'.$i]); } $students_c[$student_id] = $student_a; /* si l'élève n'existe pas dans B on saute la ligne */ if(!isset($students_b[$student_id])) continue ;
Qu'en penses tu ?

Et au final

Code : Tout sélectionner

/* enregistre les données à jour */ // Fichier C avec absence des étudiants du B $fp = fopen('C.csv', 'w'); fputcsv($fp, array('Login','Nom','Prenom','Note','Note','Note','Note','Note'),';','"'); foreach ($students_a as $student) { fputcsv($fp, $student, ';', '"'); } fclose($fp); // Fichier D avec présence des étudiants du B $handle = fopen('D.csv', 'w'); fputcsv($handle, array('Login','Nom','Prenom','Note','Note','Note','Note','Note'),';','"'); foreach ($students_c as $student) { fputcsv($handle, $student, ';', '"'); } fclose($handle);

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 24 juin 2015, 10:47

Le cas de figure est déjà géré par le code :
/* si l'élève n'existe pas dans B on saute la ligne */
if(!isset($students_b[$student_id]))
  continue ;
J'ai pris la décision arbitraire d'ignorer la ligne. Rien ne t’empêches de faire autre chose qu'un continue.

Tu pourrais ajouter la ligne dans $students_a ou bien créer au préalable un tableau $students_c et ajouter la ligne à ce tableau pour à la fin l'enregistrer dans un autre fichier.

A toi de voir ce que tu veux en faire. ;)

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 24 juin 2015, 10:39

Ca marche déja beaucoup mieux merci :D
Le fichier C est rempli, c'était bien le délimiteur qui posait problème

Le fait que le print_R m'affichait des array vides m'inquiétait, j'avais l'impression que les données n'était pas chargées ou prises en compte.

Aussi je me demandais : je viens de constater qu'il y a aussi des étudiants présents dans le fichier B et absents du A
C'est "l'inverse" du cas précédent.

Dois je donc reprendre ton code pour gérer ce cas de figure, ou existe-t-il des fonctions ou méthodes pour gérer cette "exception" ? Je vais créer un fichier D.csv
D'une certaine manière c'est simplement une ligne X présent dans un fichier B et absent dans un fichier A

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 24 juin 2015, 10:17

Salut Ghirahim, si les tableaux sont vides juste après les 2 appels à prepare_datas c'est probablement que les retours à la ligne des fichiers ne sont pas des \n et le foreach ne se ferait donc qu'une fois avec tout le contenu du fichier :
foreach(explode("\n", $datas) as $student)
Remplace le \n par un \r et ça devrait aller mieux.

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 23 juin 2015, 22:55

Bonsoir (oui c'est encore moi .-.)
j'ai effectué un fputcsv cependant cela retourne dans le fichier C.csv seulement" l'entête" crée :

Code : Tout sélectionner

/* enregistre les données à jour */ $students = array('Login;Nom;Pr_nom;Note;Note;Note;Note;Note');
Il n'y a pas de tableau ni de valeur;

Aussi j'ai effectué des print_R et il semblerait que les différents tableaux students / students_a / students_b soient vides
Je ne comprend pas :?

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 22 juin 2015, 12:20

Salut, pas vraiment. Selon la doc file_put_contents "Revient à appeler les fonctions fopen(), fwrite() et fclose() successivement."

fputcsv sert à ajouter UNE ligne dans le fichier (que tu auras préalablement ouvert avec fopen), or dans $students tu as tous les étudiants qui représentent donc plusieurs lignes.

Et tu ne peux pas écrire fputcsv(C.csv,... qui de toute façon fera une erreur sur C.csv.

L'utilisation du fputcsv ressemblerait plutôt à ceci :
$fp = fopen('C.csv', 'w');
foreach ($students as $student) {
    fputcsv($fp, $student, ';', '"');
}
fclose($fp);
Sauf que ça, ça serait à condition que chaque ligne de $students soit un tableau or dans mon code j'ai fait une boucle avec :
$students[] = implode(';', $student);
Ou chaque ligne de $students est donc une chaine de caractères où les colonnes de $student sont concaténées par un ;

Il faudrait donc à la place de ce code :
$students = array('Login;Nom;Pr_nom;Note;Note;Note;Note;Note');
foreach($students_a as $student)
  $students[] = implode(';', $student);

file_put_contents('C.csv', implode("\n", $students));
Mettre celui ci :
$fp = fopen('C.csv', 'w');
fputcsv($fp, array('Login', 'Nom', 'Pr_nom', 'Note', 'Note', 'Note', 'Note', 'Note'), ';', '"');
foreach ($students_a as $student) {
    fputcsv($fp, $student, ';', '"');
}
fclose($fp);
A noter que dans ce cas le formatage du fichier de sortie n'est donc plus le même que celui du fichier d'entrée ou il n'y a pas de délimiteur ".

PS : je dirai que le premier code est un peu plus sauvage, tandis que le deuxième est un peu plus académique. Et le deuxième sera plus adapté s'il y a beaucoup de lignes à traiter (quand je dis beaucoup, je pense à des milliers voir même plutôt des dizaines de milliers de lignes).

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 22 juin 2015, 10:10

Rebonjour Saiain !
Merci pour tes explications j'ai bien compris la structure et les enchainements de ton script

Il ne me reste plus désormais qu'à effectuer un simple

Code : Tout sélectionner

fputcsv(C.csv, $students, ";", '"');
puisque le "file_put_contents" effectue les fonctions "fopen" et "fgetcsv" ?

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 19 juin 2015, 14:40

Rebonjour Ghirahim, ça fait une bonne quinzaine d'années que je fais du php ce qui explique que j'ai une certaine facilité dans l'écriture du code. Ceci dit, même après toutes ces années, je ne maîtrise pas toutes les finesses du langage.

Pour le premier point c'est une question de portée des variables. Pour résumer la portée d'une variable dépend du contexte dans lequel elle est déclarée. Et en effet, une variable déclarée dans une fonction à une portée limitée à cette fonction. Elle n'est pas accessible à l'extérieur de la fonction et elle n'écrasera pas la valeur d'une variable de même nom dans un contexte extérieur à la fonction. De même dans le contexte d'une fonction on n'a pas accès aux variables déclarées en dehors de cette fonction.

J'ai déclaré $login_converter en dehors de la fonction afin quelle ne soit pas systématiquement ré-déclarée à chaque appel de la fonction. Mais du coup comme elle est déclarée dans le contexte principal (ou global), pour pouvoir y accéder dans la fonction, il faut faire appel au mot clé global afin d'indiquer que l'on souhaite utiliser la variable déclarée dans le contexte global.
La variable aurait pu être passée à la fonction en paramètre mais dans le cas présent j'ai préféré utiliser le mot clé global dans la fonction plutôt que devoir ajouter le paramètre à chaque appel de la fonction.

Sinon $login_converter n'est jamais modifié dans la fonction mais effectivement si on la modifiait elle serait modifiée dans le contexte global car il s'agit bien de la variable du contexte global.

http://php.net/manual/fr/language.variables.scope.php

Le strtolower/upper ça reste un grand classique pour trouver une correspondance de chaîne dans le cas où les casses peuvent être différentes. T'y avais pas pensé mais ça deviendra automatique à force.

Pour ce qui est de la variable $type, tu remarqueras qu'il s'agit du deuxième paramètre de la fonction prepare_datas. Il permet dans la fonction de faire la différence entre le CSV provenant d'apogée et l'autre CSV. Si tu regardes bien les 2 appels à prepare_datas, dans le premier cas $type prend la valeur 'apogee' et dans le deuxième cas la valeur 'other'.
/* charge les fichiers */
$students_a = prepare_datas(file_get_contents('A.csv'), 'apogee');
$students_b = prepare_datas(file_get_contents('B.csv'), 'other');
Cela permet dans la fonction d'appliquer les traitements adéquats aux valeurs selon qu'elles proviennent d'un fichier ou de l'autre. Par exemple dans le cas du fichier qui ne vient pas d'apogée ($type == 'other') il faut retraiter le login pour remplacer les lettres par la valeur numérique correspondante. Dans l'autre cas il n'y a pas de transformation à appliquer.

Et pour ce code :
for($i = 1; $i < 6; $i++) {
      $varname = 'note_'.$i;
      $note = $$varname;
Il s'agit en effet de faire appel au variables $note_1, $note_2, etc de façon dynamique plutôt que d'écrire 5 fois la même ligne de code avec juste la variable de note qui change.
Au fil de la boucle $varname prend les valeurs note_1, note_2, etc et ainsi $$varname revient à faire appel aux variables $note_1, $note_2, etc.

http://php.net/manual/fr/language.varia ... riable.php

Re: Fichier CSV : Colonnes qui disparaissent

par Ghirahim » 19 juin 2015, 10:28

Rebonjour Saian, encore un grand merci de prendre de ton temps pour m'aider, j'ai l'impression que tu fais ça avec tellement d'aisance :lol:
Mais j'ai quelques questions à propos de ton code :oops:

Code : Tout sélectionner

/* fonction de préparation des données pour comparaisons */ function prepare_datas($datas, $type) { global $login_converter; $students = array();
Une variable locale est une variable stockée dans une fonction puis détruite une fois la fonction terminée
A l'inverse, une variable "globale" est réutilisable et donc modifiable ?
Cela correspond il à une forme d'héritage en language objet où une classe est réutilisable et modifiable ?


Par la suite :

Code : Tout sélectionner

/* stocke les données sous une forme exploitable pour les comparaisons */ /* indexe les données sur nom-prenom pour un accès simple lors des comparaisons */ $student_id = strtoupper($nom).'-'.strtoupper($prenom); $students[$student_id] = array( 'login' => $type == 'other' ? $login_converter[substr($login, 0, 2)].substr($login, 2) : $login, 'nom' => $nom, 'prenom' => $prenom );
Tu utilises strtolower/upper pour la notion de casse entre les deux fichiers, c'est ingénieux de ta part j'y avais à peine pensé :mrgreen:
Mais je ne comprend pas ce que tu considères comme "type = autre" au niveau du login


Aussi,

Code : Tout sélectionner

/* stocke les notes en remplaçant les , par des . dans le cas d'apogée (pour comparaison numérique) et en les mettant /20 dans l'autre cas */ for($i = 1; $i < 6; $i++) { $varname = 'note_'.$i; $note = $$varname; $students[$student_id][$varname] = $type == 'other' ? substr($note, 0, -2) / 5 : str_replace(',', '.', $note);
Tu utilises le double dollar pour produire une variable dynamique. Le nom de la variable $varname est lui même une variable, c'est bien cela ?


Encore un grand merci pour ce que tu as écris

Re: Fichier CSV : Colonnes qui disparaissent

par Saian » 18 juin 2015, 23:28

Merci Ghirahim, ton enthousiasme fait plaisir. :)

PS : j'ai réécris un peu le code pour enlever l'inutile et le rendre plus lisible.
/* tableau de convertion des logins */
$login_converter = array();
$chars = 'abcdefghijklmnopqrstuvwxyz';
for($i = 0; $i < strlen($chars); $i++)
	$login_converter['i'.$chars[$i]] = 208 + $i;

/* fonction de préparation des données pour comparaisons */
function prepare_datas($datas, $type)
{
	global $login_converter;
	$students = array();
	
	foreach(explode("\n", $datas) as $student)
	{
		/* saute la première ligne du fichier */
		if(strtolower(substr($student, 0, 5)) == 'login')
			continue ;
	  
	  /* extrais les colonnes de la ligne */
		list($login, $nom, $prenom, $note_1, $note_2, $note_3, $note_4, $note_5) = explode(';', $student);
		
		/* stocke les données sous une forme exploitable pour les comparaisons */
		/* indexe les données sur nom-prenom pour un accès simple lors des comparaisons */
		$student_id = strtoupper($nom).'-'.strtoupper($prenom);
		$students[$student_id] = array(
			'login'  => $type == 'other' ? $login_converter[substr($login, 0, 2)].substr($login, 2) : $login,
			'nom'    => $nom,
			'prenom' => $prenom
		);
		
		/* stocke les notes en remplaçant les , par des . dans le cas d'apogée (pour comparaison numérique) et en les mettant /20 dans l'autre cas */
		for($i = 1; $i < 6; $i++) {
			$varname = 'note_'.$i;
			$note = $$varname;
			$students[$student_id][$varname] = $type == 'other' ? substr($note, 0, -2) / 5 : str_replace(',', '.', $note);
		}
	}
	
	return $students;
}

/* charge les fichiers */
$students_a = prepare_datas(file_get_contents('A.csv'), 'apogee');
$students_b = prepare_datas(file_get_contents('B.csv'), 'other');

/* compare les données et met à jour $a en fonction des comparaisons faites avec $b */
foreach($students_a as $student_id => $student_a)
{
	/* si l'élève n'existe pas dans B on saute la ligne */
	if(!isset($students_b[$student_id]))
		continue ;
	
	$student_b = $students_b[$student_id];
	
	/* mets à jour le login le cas échéant */
	if($student_b['login'] != $student_a['login'])
		$student_a['login'] = $student_b['login'];
		
  /* mets à jour les notes le cas échéant */
	for($i = 1; $i < 6; $i++) {
		if($student_b['note_'.$i] > $student_a['note_'.$i])
			$student_a['note_'.$i] = $student_b['note_'.$i];
			
		/* remet une , à la place du . */
		$student_a['note_'.$i] = str_replace('.', ',', $student_a['note_'.$i]);
	}
	
	/* met à jour l'étudiant dans le tableau d'origine */
	$students_a[$student_id] = $student_a;
}

/* enregistre les données à jour */
$students = array('Login;Nom;Pr_nom;Note;Note;Note;Note;Note');
foreach($students_a as $student)
	$students[] = implode(';', $student);

file_put_contents('C.csv', implode("\n", $students));