Export CSV d'une table MySQL pas si triviale que ça.

Export CSV d'une table MySQL pas si triviale que ça. - PHP - Programmation

Marsh Posté le 17-02-2006 à 11:22:42    

Bonjour,
 
Je me casse la tête sur un problème PHP/MySQL qui semble simple au premier abord. Voici la formulation simple du problème :
"Comment dumper une table MySQL dont certains champs textes contiennent plusieurs types de retours à la ligne dans un fichier CSV (lisible sous excel) ?"
 
Ce problème semble évident, mais après avoir testé de nombreuses méthodes, aucune ne semble donner de résultats satisfaisants.  
 
MÊME phpMyAdmin N'ARRIVE PAS A RESOUDRE CE PROBLEME.
 
 
Il me semble que le souci est que Excel donne la priorité à certains types de retours chariots... Normalement sur un fichier CSV, il suffit de mettre des guillemets pour "protéger" les éléments qui doivent être contenus dans une cellule. Donc l'exemple suivant :
"toto";"foo \n bar";
Devrait nous donner 2 cellules avec toto dans l'une et "foo <retour à la ligne> bar" dans l'autre...
 
L'exemple ci-dessous confirme ce fonctionnement :
(LISEZ APRES C'EST LA QUE SURVIENT LE PROBLEME)
 
 
<?PHP
//****************
// variables
//****************
 
$host='localhost';
$user='root';
$passwd='';
 
$delimiter=';';
 
//**********************************************************
 
 
// Create a temporary database to be filled with only few lines
//-----------------------------
$conn=mysql_connect($host,$user,$passwd) or die (mysql_error($conn));
mysql_query('CREATE DATABASE test_return',$conn) or die (mysql_error($conn));
mysql_select_db('test_return',$conn) or die (mysql_error($conn));
mysql_query('CREATE TABLE texts  
    (
     ID int(8) NOT NULL auto_increment,
      primary key (ID),
     text_field text
    )',$conn) or die (mysql_error($conn));
 
 
// insertion of content to our table with print_r results
//-----------------------------
mysql_query('INSERT INTO texts (text_field) VALUES ("first test" )',$conn) or die (mysql_error($conn));
mysql_query('INSERT INTO texts (text_field) VALUES ("second test" )',$conn) or die (mysql_error($conn));
$with_classical_end_of_lines=print_r(array(array(1,2),array(3,4)),true);
mysql_query('INSERT INTO texts (text_field) VALUES ("'.$with_classical_end_of_lines.'" )',$conn) or die (mysql_error($conn));
mysql_query('INSERT INTO texts (text_field) VALUES ("last test" )',$conn) or die (mysql_error($conn));
 
 
 
// Sending headers
//-----------------------------
//header("Content-Type: application/csv-tab-delimited-table" );
header("Content-disposition: attachment; filename=test_csv.csv" );  
header("Content-Type: application/force-download" );  
header("Content-Transfer-Encoding: application/octet-stream\n" );
header("Content-Length: ".taille_table('texts',$conn));  
header("Pragma: no-cache" );  
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public" );
 
 
 
 
//****************************
// creating a CSV file
//****************************
 
 
 
table_to_csv('texts',$delimiter,$conn);
 
mysql_query('drop database test_return',$conn);
 
mysql_close($conn);
 
 
//*******************************
//         functions
//*******************************
function table_to_csv($table,$delimiter,$conn)
{
 $query_result=mysql_query('select * from '.$table,$conn);
 while($result=mysql_fetch_array($query_result,MYSQL_NUM))
 {
  $table=array();
  foreach($result as $key=>$value)
  {
   // we escape " to have them embeded in the csv fields
   $to_export=str_replace('"','\"',$value);
   
   /* trying to protect against undesired carriage returns
   $to_export=str_replace('
','',$to_export);
   $to_export=str_replace('\n','',$value);
   */
   
   $table[]=$to_export;
  }
  echo '"'.implode('"'.$delimiter.'"',$table).'"
';
 }
}
 
// size in octets of the table... This helps the browser to be given this numer in the header
function taille_table($nom_table,$conn)
{
 $res=mysql_query('show table status',$conn);
 while(($tabl=mysql_fetch_array($res,MYSQL_ASSOC)))
 {
  if($tabl['Name']==$nom_table)
  {
   return $tabl['Data_length'];
  }
 }
 return false;
}
?>
 
 
 
 
Jusque là tout va bien, en ouvrant le fichier sous Excel, on trouve bien dans la case B3 le contenu de notre cellule avec des retours à la ligne à l'intérieur...  
 
 
===================================
CE QUI NE MARCHE PAS PAR CONTRE
===================================
 
Si, au lieu de remplir du contenu par un script qui envoie du texte "formaté", la table de texte est remplie à partir de textarea dans un formulaire, l'utilisateur peut aussi entrer des retours chariot... (je ne peux pas mettre les mêmes dans un exemple de code car leur code ANSI sera changé...).  
Ce sont ces retours chariot là qui sont problématiques... ils forcent le changement de ligne et "cassent" la cellule qui normalement aurait due être unique...
 
 
J'espère que quelqu'un pourra voir une solution à ce problème, pour l'instant je ne trouve aucune solution concrète...
 
D'avance merci à vous.

Reply

Marsh Posté le 17-02-2006 à 11:22:42   

Reply

Marsh Posté le 17-02-2006 à 11:29:39    

Si l'utilisateur rajoute des retours chariots au milieu d'une ligne de fichier cvs sans avoir mis de guillemets autour, alors il n'y a aucun moyen d'éviter l'erreur.
Vu de php, un retour chariot "normal" et un retour chariot de l'utilisateur seront parfaitement identique.
 
Une solution serait d'envoyer directement le fichier csv dans le forumlaire tout comme le fait hotmail (par exemple) pour les fichiers qui sont attaché à un mail.

Reply

Marsh Posté le 17-02-2006 à 11:45:13    

omega2 a écrit :

Si l'utilisateur rajoute des retours chariots au milieu d'une ligne de fichier cvs sans avoir mis de guillemets autour, alors il n'y a aucun moyen d'éviter l'erreur.
Vu de php, un retour chariot "normal" et un retour chariot de l'utilisateur seront parfaitement identique.
 
Une solution serait d'envoyer directement le fichier csv dans le forumlaire tout comme le fait hotmail (par exemple) pour les fichiers qui sont attaché à un mail.


 
Je crois qu'il faut que je reprécise ce que je cherche...
Mon besoin est d'éditer pour un admin toutes les modifications qui sont faites sur des formulaires... Donc j'ai :
- d'un côté des utilisateurs utilisant des formulaires
- de l'autre un accès admin donnant un fichier excel...
 
L'utilisateur ne modifie pas le CSV... Le problème vient du type de retour chariot utilisé... Comme on peut le voir avec le code php que j'ai posté au début, il est tout à fait possible d'avoir "certains" retours chariot qui ne posent pas de souci... Ce que je cherche c'est un moyen de passer TOUS les types de retours chariots que MySQL a pu recevoir dans le fichier CSV... Ou bien un moyen de comprendre comment différencier les retours chariots qui passent de ceux qui ne passent pas...

Reply

Marsh Posté le 17-02-2006 à 12:08:19    

Sous windows, le retour chario classique, c'est "\n\r".
Sous unix, c'est jsute "\n". (si je ne me trompe pas de caractére)
 
DOnc a toi de voir où t'as des orphelins parmis les retour chariot et tu pouras vérifier si c'est ça qui passe pas.

Reply

Marsh Posté le 17-02-2006 à 12:19:56    

omega2 a écrit :

Sous windows, le retour chario classique, c'est "\n\r".
Sous unix, c'est jsute "\n". (si je ne me trompe pas de caractére)
 
DOnc a toi de voir où t'as des orphelins parmis les retour chariot et tu pouras vérifier si c'est ça qui passe pas.


 
J'ai déjà testé tous les types "connus" de retours chariot que je connaissait... (\n\r) inclus, même ceux de unix et MacOS, mais mon str_replace n'a rien changé

Reply

Marsh Posté le 17-02-2006 à 12:33:10    

Si tu veux que strreplace bosse sur les retours chariots, alors utilise un " et pas un ' .
Avec un ' il cherchera dle caractére "\" suivit du caractére "n"

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed