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.