Comment puis-je produire un CSV UTF-8 en PHP que Excel Lira correctement?

j'ai ce truc très simple qui ne sort que des trucs au format CSV, mais ça doit être UTF-8. J'ouvre ce fichier dans TextEdit ou TextMate ou Dreamweaver et il affiche les caractères UTF-8 correctement, mais si je l'ouvre dans Excel il fait ce genre de chose stupide íÄ à la place. Voici ce que j'ai en tête de mon document:

header("content-type:application/csv;charset=UTF-8");
header("Content-Disposition:attachment;filename="CHS.csv"");

tout cela semble avoir L'effet désiré Excel sauf (Mac, 2008) qui ne veut pas l'importer correctement. Il n'y a pas options dans Excel pour moi de "s'ouvrir comme UTF-8" ou autre, donc ... je suis un peu agacé.

il semble que je ne puisse trouver de solutions claires à ce problème nulle part, malgré le fait que beaucoup de gens aient le même problème. La chose que je vois le plus est d'inclure le BOM, mais je ne peux pas exactement comprendre comment faire. Comme vous pouvez le voir ci-dessus je suis juste echo ing ces données, je n'écris pas de fichier. Je peux le faire si j'en ai besoin, mais je ne le suis pas parce qu'il n'y a pas besoin de ça à de ce point. Toute aide?

mise à jour: j'ai essayé de faire écho au BOM comme echo pack("CCC", 0xef, 0xbb, 0xbf); que je viens de tirer d'un site qui essayait de détecter le BOM. Mais Excel ajoute ces trois personnages à la première cellule lors de l'importation, et encore bousille les caractères spéciaux.

159
demandé sur pnuts 2010-12-03 21:49:11

30 réponses

pour citer un Microsoft support engineer ,

Excel for Mac ne supporte pas actuellement UTF-8

mise à jour, 2017 : ceci est vrai de toutes les versions de Microsoft Excel pour Mac avant Office 2016 . Les versions plus récentes (de Office 365) prennent maintenant en charge UTF-8.

afin de produire un contenu UTF-8 qui excelle à la fois sur Windows et OS X seront capables de lire avec succès, vous aurez besoin de faire deux choses:

  1. assurez-vous que vous convertissez votre texte UTF-8 en UTF-16LE

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    
  2. assurez-vous d'ajouter la marque D'ordre UTF-16LE byte

    chr(255) . chr(254)
    

le problème suivant qui apparaît seulement avec Excel sur OS X (mais pas Windows) sera lorsque vous visualisez un fichier CSV avec des valeurs séparées par des virgules, Excel affichera des lignes avec une seule ligne et tout le texte avec les virgules dans la première ligne.

la façon d'éviter cela est d'utiliser les onglets comme valeur séparée.

j'ai utilisé cette fonction des commentaires PHP (en utilisant des onglets" \t " au lieu de virgules) et il a fonctionné parfaitement sur OS X et Windows Excel.

noter que pour régler un problème avec un vide colonne comme la fin d'une ligne, que j'ai eu à changer la ligne de code qui dit:

    $field_cnt = count($fields);

à

    $field_cnt = count($fields)-1;

comme certains des autres commentaires sur cette page le disent, D'autres applications de tableurs comme OpenOffice Calc, les propres numéros D'Apple et le tableur de Google Doc n'ont aucun problème avec les fichiers UTF-8 avec des virgules.

Voir le tableau de cette question de ce qui fonctionne et ne fonctionne pas pour l'Unicode des fichiers CSV en Excel


comme note, je pourrais ajouter que si vous utilisez compositeur , vous devriez avoir un regard à ajouter League\Csv à vos requires. League\Csv a une API vraiment agréable pour la construction de fichiers CSV .

pour utiliser League\Csv avec cette méthode de création de fichiers CSV, cochez cet exemple

108
répondu Tim Groeneveld 2017-10-22 23:23:54

j'ai le même problème (ou similaire).

dans mon cas, si j'ajoute un BOM à la sortie, ça marche:

header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=Customers_Export.csv');
echo "\xEF\xBB\xBF"; // UTF-8 BOM

je crois que c'est un hack assez laid, mais il a fonctionné pour moi, au moins pour Excel 2007 Windows. Pas sûr que ça marchera sur Mac.

251
répondu Daniel Magliola 2015-11-01 20:58:18

Voici comment je l'ai fait (qui est d'inciter le navigateur pour télécharger le fichier csv):

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=file.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
echo $csv_file_content;
exit();

la seule chose qu'il a corrigé problème D'encodage UTF8 dans l'aperçu CSV lorsque vous frappez la barre d'espace sur Mac.. mais pas dans Excel Mac 2008... Je ne sais pas pourquoi

30
répondu Jazzer 2017-04-12 02:55:46

je viens de traiter le même problème, et j'ai trouvé deux solutions.

  1. utilisez la PHPExcel classe comme suggéré par bpeterson76 .

    • en utilisant cette classe génère le fichier le plus largement compatible, j'ai été en mesure de générer un fichier à partir de données encodées UTF-8 qui a ouvert fine dans Excel 2008 Mac, Excel 2007 Windows, et Google Docs.
    • Le plus gros problème avec L'utilisation de PHPExcel est qu'il est lent et utilise beaucoup de mémoire, ce qui n'est pas un problème pour les fichiers de taille raisonnable, mais si votre fichier Excel/CSV a des centaines ou des milliers de lignes, cette bibliothèque devient inutilisable .
    • Voici une méthode PHP qui va prendre quelques données TSV et produire un fichier Excel au navigateur, notez qu'il utilise le rédacteur Excel5, ce qui signifie que le fichier doit être compatible avec les versions plus anciennes D'Excel, mais Je n'ai plus accès à tout, donc je ne peux pas les tester.

      function excel_export($tsv_data, $filename) {
          $export_data = preg_split("/\n/", $tsv_data);
          foreach($export_data as &$row) {
              $row = preg_split("/\t/", $row);
          }
      
          include("includes/PHPExcel.php");
          include('includes/PHPExcel/Writer/Excel5.php');
      
          $objPHPExcel = new PHPExcel();          
      
          $objPHPExcel->setActiveSheetIndex(0);
          $sheet = $objPHPExcel->getActiveSheet();
          $row = '1';
          $col = "A";
          foreach($export_data as $row_cells) {
              if(!is_array($row_cells)) { continue; }
                  foreach($row_cells as $cell) {
                      $sheet->setCellValue($col.$row, $cell);
                      $col++;
                  }
              $row += 1;
              $col = "A";
          }
      
          $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);
          header('Content-Type: application/vnd.ms-excel');
          header('Content-Disposition: attachment;filename="'.$filename.'.xls"');
          header('Cache-Control: max-age=0');
          $objWriter->save('php://output');   
          exit;   
      }
      
  2. en raison des problèmes d'efficacité avec PHPExcel, j'ai également dû comprendre comment générer un fichier CSV ou TSV compatible UTF-8 & Excel.

    • le mieux que j'ai pu trouver était un fichier qui était compatible avec Excel 2008 Mac, et Excel 2007 PC, mais pas Google Docs, ce qui est assez bon pour mon application.
    • j'ai trouvé la solution ici , spécifiquement, cette réponse , mais vous devriez également lire la réponse acceptée comme il explique le problème.
    • voici le code PHP que j'ai utilisé, notez que j'utilise les données tsv (tabs comme délimiteurs au lieu des virgules):

      header ( 'HTTP/1.1 200 OK' );
      header ( 'Date: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Last-Modified: ' . date ( 'D M j G:i:s T Y' ) );
      header ( 'Content-Type: application/vnd.ms-excel') ;
      header ( 'Content-Disposition: attachment;filename=export.csv' );
      print chr(255) . chr(254) . mb_convert_encoding($tsv_data, 'UTF-16LE', 'UTF-8');
      exit;
      
21
répondu Jasdeep Gosal 2018-08-22 15:15:02

Excel ne supporte pas UTF-8. Vous devez encoder votre texte UTF-8 dans UCS-2le.

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
12
répondu Leopold Gault 2012-11-08 14:09:04

j'avais le même problème et il a été résolu comme ci-dessous:

    header('Content-Encoding: UTF-8');
    header('Content-Type: text/csv; charset=utf-8' );
    header(sprintf( 'Content-Disposition: attachment; filename=my-csv-%s.csv', date( 'dmY-His' ) ) );
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');

    $df = fopen( 'php://output', 'w' );

    //This line is important:
    fputs( $df, "\xEF\xBB\xBF" ); // UTF-8 BOM !!!!!

    foreach ( $rows as $row ) {
        fputcsv( $df, $row );
    }
    fclose($df);
    exit();
12
répondu Reza Mamun 2015-12-18 16:31:30

pour faire suite à cela:

il semble que le problème est simplement avec Excel sur le Mac. Ce n'est pas comme ça que je génère les fichiers, parce que même la génération de CSVs à partir D'Excel les casse. Je sauve en CSV, et je réimporte, et tous les personnages sont fichus.

donc ... il ne semble pas y avoir de réponse correcte à cela. Merci pour toutes les suggestions.

je dirais que de tout ce que j'ai lu, La suggestion de @Daniel Magliola sur le BOM serait probablement la meilleure réponse pour un autre ordinateur. Mais il n'est toujours pas à résoudre mon problème.

8
répondu Ben Saufley 2011-01-11 16:56:44

le fichier CSV doit inclure une marque D'ordre D'octet.

Ou comme l'a suggéré et d'une solution juste écho avec le corps HTTP

6
répondu Cybot 2011-10-20 08:56:43

cela fonctionne très bien dans excel pour Windows et aussi Mac OS.

corriger les numéros dans excel qui ne contiennent pas de caractères contenant des signes diacritiques, des lettres cyrilliques, des lettres grecques et des symboles monétaires.

function writeCSV($filename, $headings, $data) {   

    //Use tab as field separator
    $newTab  = "\t";
    $newLine  = "\n";

    $fputcsv  =  count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';

    // Loop over the * to export
    if (! empty($data)) {
      foreach($data as $item) {
        $fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
      }
    }

    //Convert CSV to UTF-16
    $encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');

    // Output CSV-specific headers
    header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel

    exit;
}
5
répondu Murali Krishna 2018-03-27 16:13:00

depuis UTF8 encoding ne fonctionne pas bien avec Excel. Vous pouvez convertir les données à un autre type d'encodage en utilisant iconv() .

p.ex.

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
4
répondu Abrar A. Shareef 2015-11-01 21:09:06

ajouter:

fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));

ou:

fprintf($file, "\xEF\xBB\xBF");

avant d'écrire tout contenu dans le fichier CSV.

exemple:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);
4
répondu Rejaul 2016-03-15 06:25:59

comme j'ai enquêté et j'ai constaté que UTF-8 ne fonctionne pas bien sur MAC et Windows donc j'ai essayé avec Windows-1252 , il supporte bien sur les deux mais vous devez sélectionner le type d'encodage sur ubuntu. Voici mon code $valueToWrite = mb_convert_encoding($value, 'Windows-1252');

$response->headers->set('Content-Type', $mime . '; charset=Windows-1252');
    $response->headers->set('Pragma', 'public');
    $response->headers->set('Content-Endcoding','Windows-1252');
    $response->headers->set('Cache-Control', 'maxage=1');
    $response->headers->set('Content-Disposition', $dispositionHeader);
    echo "\xEF\xBB\xBF"; // UTF-8 BOM
2
répondu Ho Ha 2017-04-17 02:52:05

dans mon cas suivant fonctionne très agréable de faire fichier CSV avec des caractères UTF-8 affiché correctement dans Excel.

$out = fopen('php://output', 'w');
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($out, $some_csv_strings);

l'en-tête bom 0xEF 0xBB 0xBF permettra à Excel de connaître le bon encodage.

2
répondu Codemole 2017-12-26 18:28:53

Que Diriez-vous de simplement produire pour exceller lui-même? c'est une excellente classe qui vous permet de générer des fichiers XLS côté serveur. Je l'utilise fréquemment pour les clients qui ne peuvent pas "comprendre" csv et jusqu'à présent n'ont jamais eu une plainte. Il permet également certains formatage supplémentaire (ombrage, rowheights, calculs, etc) que csv ne fera jamais.

1
répondu bpeterson76 2010-12-03 22:42:36

vous pouvez convertir votre chaîne CSV avec iconv . par exemple:

$csvString = "Möckmühl;in Möckmühl ist die Hölle los\n";
file_put_contents('path/newTest.csv',iconv("UTF-8", "ISO-8859-1//TRANSLIT",$csvString) );
1
répondu foued611 2012-05-14 13:53:39

Vous devez utiliser le codage "Windows-1252".

header('Content-Encoding: Windows-1252');
header('Content-type: text/csv; charset=Windows-1252');
header("Content-Disposition: attachment; filename={$filename}");

peut-être que vous devez convertir vos cordes:

private function convertToWindowsCharset($string) {
  $encoding = mb_detect_encoding($string);

  return iconv($encoding, "Windows-1252", $string);
}
1
répondu roNn23 2013-04-10 09:20:34

je suis sur Mac, dans mon cas j'ai juste eu à spécifier le séparateur avec "sep=;\n" et encoder le fichier en UTF-16LE comme ceci:

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
1
répondu Sebastien Horin 2016-07-18 22:45:29

pour moi, aucune des solutions ci-dessus n'a fonctionné. Voici ce que j'ai fait pour résoudre le problème: modifier la valeur en utilisant cette fonction dans le code PHP:

$value = utf8_encode($value);

cette valeur de sortie correctement dans une feuille excel.

1
répondu Barani r 2016-12-07 08:55:13
**This is 100% works fine in excel for both Windows7,8,10 and also All Mac OS.**
//Fix issues in excel that are not displaying characters containing diacritics, cyrillic letters, Greek letter and currency symbols.

function generateCSVFile($filename, $headings, $data) {

    //Use tab as field separator
    $newTab  = "\t";
    $newLine  = "\n";

    $fputcsv  =  count($headings) ? '"'. implode('"'.$newTab.'"', $headings).'"'.$newLine : '';

    // Loop over the * to export
    if (! empty($data)) {
      foreach($data as $item) {
        $fputcsv .= '"'. implode('"'.$newTab.'"', $item).'"'.$newLine;
      }
    }

    //Convert CSV to UTF-16
    $encoded_csv = mb_convert_encoding($fputcsv, 'UTF-16LE', 'UTF-8');

    // Output CSV-specific headers
    header('Set-Cookie: fileDownload=true; path=/'); //This cookie is needed in order to trigger the success window.
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv; //php array convert to csv/excel
    exit;
}
1
répondu Sagar72427 2018-03-27 13:49:25

j'ai eu ce même problème quand J'ai eu une routine Excel VBA qui a importé des données. Puisque CSV est un format de texte simple, j'ai travaillé autour de cela en ouvrant programmatically les données dans un éditeur de fichier simple comme wordpad, et le re-enregistrant comme texte unicode, ou le copiant au presse-papiers à partir de là et le collant pour exceller. Si excel ne décompose pas automatiquement le CSV en cellules, il est facile d'y remédier en utilisant la fonction "Texte vers Colonnes".

0
répondu Alain 2010-12-03 18:52:22

le problème est-il encore se produire lorsque vous l'enregistrez en tant que .txt ouvrir que dans excel avec virgule comme délimiteur?

le problème pourrait ne pas être l'encodage du tout, il pourrait juste être que le fichier n'est pas un CSV parfait selon les normes excel.

0
répondu Alain 2010-12-03 18:58:51

ce Post est assez vieux, mais après des heures d'essai je veux partager ma solution ... peut-être qu'il aide quelqu'un qui traite avec Excel et Mac et CSV et trébuche sur cette menace. Je génère un csv dynamiquement comme sortie à partir d'une base de données avec les utilisateurs Excel à l'esprit. (UTF-8 avec BOM)

j'ai essayé beaucoup d'iconvs mais je n'ai pas pu obtenir des umlautes allemands travaillant dans Mac Excel 2004. Une solution: PHPExcel. Il est génial mais pour mon projet un peu trop. Ce qui fonctionne pour moi est la création d' le fichier csv et convertir ce fichier csv en xls avec ce PHPsnippet: csv2xls . le résultat xls travaille avec excel Allemand umlauts (ä, ö, Ü,...).

0
répondu t Book 2013-04-29 20:01:34

je viens d'essayer ces en-têtes et ai obtenu Excel 2013 sur un PC Windows 7 pour importer le fichier CSV avec des caractères spéciaux correctement. Le Byte Order Mark (BOM) était la clé finale qui a fait fonctionner.


    header('Content-Encoding: UTF-8');
    header('Content-type: text/csv; charset=UTF-8');
    header("Content-disposition: attachment; filename=filename.csv");
    header("Pragma: public");
    header("Expires: 0");
    echo "\xEF\xBB\xBF"; // UTF-8 BOM

0
répondu Brian 2013-07-17 17:45:11

vous pouvez ajouter les 3 octets au fichier avant l'exportation, ça marche pour moi . Avant de faire ce système ne fonctionne que sous Windows et HP-UX mais a échoué sous Linux.

FileOutputStream fStream = new FileOutputStream( f );
final byte[] bom = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };
OutputStreamWriter writer = new OutputStreamWriter( fStream, "UTF8" );
fStream.write( bom );

Ont UTF-8 BOM (3 octets, hex EF BB BF) au début du fichier. Sinon Excel interprétera les données selon le codage par défaut de votre locale (par exemple cp1252) au lieu de utf-8

générer un fichier CSV pour Excel, Comment avoir une nouvelle ligne à l'intérieur d'un valeur

0
répondu Cherry Yap 2017-05-23 11:54:59

sinon vous pouvez:

header("Content-type: application/x-download");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=".$fileName."");
header("Cache-control: private");

echo utf8_decode($output);
0
répondu user3519396 2014-04-10 12:13:23

la conversion de texte déjà encodé utf-8 en utilisant mb_convert_encoding n'est pas nécessaire. Juste ajouter trois caractères devant le contenu original:

$newContent = chr(239) . chr(187) . chr(191) . $originalContent

pour moi cela a résolu le problème des caractères spéciaux dans les fichiers csv.

0
répondu Rvanlaak 2014-09-16 12:13:56

solution facile pour Mac Excel 2008: J'ai lutté avec ce soo plusieurs fois, Mais voici ma solution facile: Ouvert le .csv fichier dans Textwrangler qui devrait ouvrir vos caractères UTF-8 correctement. Maintenant, dans la barre d'état du bas, changez le format de fichier "Unicode (UTF-8)" en "Western (ISO Latin 1)" et sauvegardez le fichier. Maintenant, allez sur votre Mac Excel 2008 et sélectionnez Fichier > Importer > sélectionner csv > trouver votre fichier > dans l'origine du fichier, sélectionnez " Windows (ANSI)" et voila les caractères UTF-8 apparaissent correctement. Moins il ne fait pour moi...

0
répondu Poul 2015-08-11 06:41:15

j'utilise et ça marche

header('Content-Description: File Transfer');
header('Content-Type: text/csv; charset=UTF-16LE');
header('Content-Disposition: attachment; filename=file.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
// output headers so that the file is downloaded rather than displayed
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
fputs( $output, "\xEF\xBB\xBF" );
// output the column headings
fputcsv($output, array('Thông tin khách hàng đăng ký'));
// fetch the data
$setutf8 = "SET NAMES utf8";
$q = $conn->query($setutf8);
$setutf8c = "SET character_set_results = 'utf8', character_set_client =
'utf8', character_set_connection = 'utf8', character_set_database = 'utf8',
character_set_server = 'utf8'";
$qc = $conn->query($setutf8c);
$setutf9 = "SET CHARACTER SET utf8";
$q1 = $conn->query($setutf9);
$setutf7 = "SET COLLATION_CONNECTION = 'utf8_general_ci'";
$q2 = $conn->query($setutf7);
$sql = "SELECT id, name, email FROM myguests";
$rows = $conn->query($sql);
$arr1= array();
if ($rows->num_rows > 0) {
// output data of each row
while($row = $rows->fetch_assoc()) {
    $rcontent = " Name: " . $row["name"]. " - Email: " . $row["email"];  
    $arr1[]["title"] =  $rcontent;
}
} else {
     echo "0 results";
}
$conn->close();
// loop over the rows, outputting them
foreach($arr1 as $result1):
   fputcsv($output, $result1);
endforeach;
0
répondu BoRnbeBaD 2016-03-27 16:47:50

#sortie UTF-8 CSV PHP qui Excel lire correctement.

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
0
répondu Murali Krishna 2017-10-05 11:10:31
//convert UTF-8 file without BOM to UTF-16LE for excel on mac
$fileUtf8String = file_get_contents("file.ext");
file_put_contents("file.ext", "\xFF\xFE" . mb_convert_encoding($fileUtf8String, "UTF-16LE", "UTF-8"));
-1
répondu b3wii 2015-01-08 15:56:50