Excel が正しく読み取れる UTF-8 CSV を PHP で出力するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4348802

質問

いくつかのものを CSV 形式で出力するだけの非常に単純なものがありますが、UTF-8 である必要があります。このファイルを TextEdit または TextMate または Dreamweaver で開くと、UTF-8 文字が正しく表示されますが、Excel で開くと、代わりにこの愚かな動作が行われます。私の文書の冒頭にあるものは次のとおりです。

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

Excel (Mac、2008) がそれを適切にインポートしようとしないことを除いて、これはすべて望ましい効果があるように見えます。Excel には「UTF-8 として開く」などのオプションがないので、少しイライラしています。

多くの人が同じ問題を抱えているにもかかわらず、これに対する明確な解決策はどこにも見つからないようです。私が最もよく目にするのは BOM を含めることですが、その方法が正確にわかりません。上でわかるように、私はただ echoこのデータを作成するときは、ファイルには書き込みません。必要に応じてそうすることもできますが、現時点ではその必要がないと思われるため、そうしません。何か助けはありますか?

アップデート:BOMを次のようにエコーしてみました echo pack("CCC", 0xef, 0xbb, 0xbf); これは、BOM を検出しようとしていたサイトから取得したものです。しかし、Excel はインポート時にこれらの 3 文字を最初のセルに追加するだけで、依然として特殊文字が混乱します。

役に立ちましたか?

解決

引用するには Microsoft サポート エンジニア,

Excel for Mac は現在 UTF-8 をサポートしていません

更新情報、2017 年:これは、以前の Microsoft Excel for Mac のすべてのバージョンに当てはまります。 オフィス2016. 。新しいバージョン (Office 365 以降) は UTF-8 をサポートするようになりました。

Windows と OS X の両方で Excel が正常に読み取ることができる UTF-8 コンテンツを出力するには、次の 2 つのことを行う必要があります。

  1. UTF-8 テキストを必ず UTF-16LE に変換してください。

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    
  2. UTF-16LE バイト オーダー マークを必ず追加してください。

    chr(255) . chr(254)
    

次の問題は、OS X 上の Excel でのみ発生します (ただし、 ない Windows) では、カンマ区切りの値を含む CSV ファイルを表示すると、Excel では 1 行のみの行と、最初の行のカンマを含むすべてのテキストがレンダリングされます。

これを回避する方法は、区切られた値としてタブを使用することです。

私が使用した PHP コメントからのこの関数 (カンマの代わりにタブ「 」を使用)、OS X と Windows Excel で完全に動作しました。

行の末尾が空の列の問題を修正するには、次のコード行を変更する必要があることに注意してください。

    $field_cnt = count($fields);

    $field_cnt = count($fields)-1;

このページの他のコメントにもあるように、OpenOffice Calc、Apple 独自の Numbers、Google Doc の Spreadsheet などの他のスプレッドシート アプリでは、カンマを含む UTF-8 ファイルに問題はありません。

見る この質問の表 Excel の Unicode CSV ファイルで機能するものと機能しないものについて


余談ですが、使用している場合は、 作曲, 、追加を見てみる必要があります League\Csv あなたのニーズに合わせて。 League\Csv もっている CSV ファイルを構築するための非常に優れた API.

使用するには League\Csv CSV ファイルを作成するこの方法を使用して、チェックしてください。 この例

他のヒント

私も同じ(または同様の)問題を抱えています。

私の場合、出力に BOM を追加すると、機能します。

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

これはかなり醜いハックだと思いますが、少なくとも Excel 2007 Windows ではうまくいきました。Mac で動作するかどうかはわかりません。

これが私がそれを行った方法です(ブラウザに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();

Mac でスペースバーを押したときの CSV プレビューでの UTF8 エンコードの問題が修正された唯一のこと。Excel Mac 2008 ではそうではありません...なぜだかわかりません

同じ問題に対処し、2 つの解決策を思いつきました。

  1. 使用 PHPエクセル クラス bpeterson76 が提案したように.

    • このクラスを使用すると、最も広く互換性のあるファイルが生成され、Excel 2008 Mac、Excel 2007 Windows、および Google ドキュメントで問題なく開く UTF-8 エンコード データからファイルを生成できました。
    • PHPExcel を使用する場合の最大の問題は、速度が遅く、大量のメモリを使用することです。これは、適度なサイズのファイルの場合は問題ではありませんが、 Excel/CSV ファイルに数百行または数千行がある場合、このライブラリは使用できなくなります。.
    • これは、TSV データを取得して Excel ファイルをブラウザに出力する PHP メソッドです。Excel5 Writer を使用していることに注意してください。つまり、ファイルは古いバージョンの Excel と互換性がある必要がありますが、現在はどのバージョンにもアクセスできません。したがってテストすることはできません。

      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. PHPExcel には効率の問題があるため、UTF-8 および Excel と互換性のある CSV または TSV ファイルを生成する方法を理解する必要もありました。

    • 私が思いついた最善のファイルは、Excel 2008 Mac および Excel 2007 PC と互換性があるが、Google ドキュメントとは互換性がないファイルであり、私のアプリケーションには十分でした。
    • 解決策を見つけました ここ, 、 具体的には、 この答え, 、ただし、こちらも読んでください。 受け入れられた回答 問題を説明しているからです。
    • これが私が使用した PHP コードです。tsv データ (カンマではなくタブを区切り文字として使用) を使用していることに注意してください。

      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;
      

私も同じ問題を抱えていましたが、次のように解決されました。

    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();

Excel は UTF-8 をサポートしていません。UTF-8 テキストを UCS-2LE にエンコードする必要があります。

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');

これをフォローアップするには:

問題は単に Mac 上の Excel にあるようです。CSV を生成する場合でも、それはファイルを生成する方法ではありません。 エクセルから それらを壊しているのです。CSVで保存して再インポートすると文字が全部崩れてしまいます。

つまり…これに対する正しい答えはないようです。すべてのご提案に感謝します。

私が読んだすべてのことから、BOM に関する @Daniel Magliola の提案が、おそらく他のコンピューターにとって最良の答えになるでしょう。しかし、それでも私の問題は解決しません。

私の場合、次の方法は、Excel で正しく表示される UTF-8 文字を含む CSV ファイルを作成するのに非常にうまく機能します。

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

0xEF 0xBB 0xBF BOM ヘッダーにより、Excel は正しいエンコーディングを認識します。

これは、Windows と Mac OS の両方の Excel で正常に機能します。

発音記号、キリル文字、ギリシャ文字、通貨記号を含む文字が表示されない Excel の問題を修正します。

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;
}

CSV ファイルにはバイト オーダー マークが含まれている必要があります。

または、提案および回避策として、HTTP 本文でそれをエコーするだけです

UTF8 エンコーディングは Excel ではうまく機能しないためです。次を使用してデータを別のエンコードタイプに変換できます。 iconv().

例えば

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),

追加:

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

または:

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

CSV ファイルにコンテンツを書き込む前。

例:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);

を使用して既に utf-8 エンコードされたテキストを変換する mb_convert_encoding は必要ありません。元のコンテンツの前に 3 文字を追加するだけです。

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

私の場合、これで CSV ファイル内の特殊文字の問題が解決されました。

調査したところ、UTF-8 は MAC と Windows ではうまく機能しないことがわかったので、 Windows-1252 で試してみました。両方でうまくサポートされていますが、ubuntu ではエンコードの種類を選択する必要があります。これが私のコードです$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
**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;
}

Excel自体に出力するだけではどうでしょうか? これは素晴らしいクラスです これにより、サーバー側で XLS ファイルを生成できるようになります。私は CSV を「理解」できないクライアントに対して頻繁にこのツールを使用していますが、これまでに苦情があったことはありません。また、CSV では実行できない追加の書式設定 (シェーディング、行の高さ、計算など) も可能になります。

CSV文字列を次のように変換できます アイコンv。例えば:

$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) );

エンコーディング「Windows-1252」を使用する必要があります。

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

文字列を変換する必要があるかもしれません。

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

  return iconv($encoding, "Windows-1252", $string);
}

エクスポートする前にファイルに 3 バイトを追加することもできます。私にとってはうまくいきます。そのシステムを実行する前は、Windows と HP -UX でのみ動作しましたが、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 );

ファイルの先頭に UTF-8 BOM (3 バイト、16 進数 EF BB BF) を含めます。それ以外の場合、Excel はロケールのデフォルトのエンコーディングに従ってデータを解釈します (例:cp1252) utf-8 の代わりに

ExcelのCSVファイルの生成、値の中に改行を入れる方法

私は Mac を使用していますが、私の場合は区切り文字を次のように指定する必要がありました。 "sep=;\n" 次のようにファイルを UTF-16LE でエンコードします。

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');

私にとって、上記の解決策はどれも機能しませんでした。問題を解決するために私がやったことは次のとおりです。PHP コードでこの関数を使用して値を変更します。

$value = utf8_encode($value);

これにより、値が Excel シートに適切に出力されます。

Excel VBA ルーチンでデータをインポートしたときにも、同じ問題が発生しました。CSV はプレーン テキスト形式であるため、プログラムでワードパッドなどの単純なファイル エディターでデータを開き、Unicode テキストとして再保存するか、そこからクリップボードにコピーして Excel に貼り付けることで、この問題を回避していました。Excel が CSV をセルに自動的に解析しない場合は、組み込みの「テキストを列に変換」機能を使用して簡単に解決できます。

.txt ファイルとして保存し、カンマを区切り文字として Excel で開いた場合でも問題は発生しますか?

問題はエンコーディングではなく、単にファイルが Excel の標準に従って完全な CSV ではないだけである可能性があります。

この投稿はかなり古いものですが、何時間も試した結果、私の解決策を共有したいと思います…Excel、Mac、CSV を扱う人やこの脅威につまずいている人に役立つかもしれません。Excel ユーザーを念頭に置いて、データベースからの出力として CSV を動的に生成しています。(BOM 付き UTF-8)

多くの iconv を試しましたが、Mac Excel 2004 ではドイツ語のウムラウトを機能させることができませんでした。1 つの解決策:PHPエクセル。それは素晴らしいことですが、私のプロジェクトには少し多すぎます。私にとってうまくいくのは、csv ファイルを作成し、この PHPsnippet を使用してこの csv ファイルを xls に変換することです。 csv2xls. 。結果の xls は Excel のドイツ語のウムラウト (ä、ö、Ü、...) で機能します。

これらのヘッダーを試してみたところ、Windows 7 PC 上の Excel 2013 で特殊文字を含む CSV ファイルを正しくインポートできるようになりました。バイト オーダー マーク (BOM) は、それを機能させるための最後のキーでした。

    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

それ以外の場合は、次のことを行うことができます。

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);

Mac Excel 2008 の簡単な解決策:私はこれに何度も苦労しましたが、簡単な修正は次のとおりです。Textwrangler で .csv ファイルを開くと、UTF-8 文字が正しく開くはずです。次に、下部のステータス バーでファイル形式を「Unicode (UTF-8)」から「Western (ISO Latin 1)」に変更し、ファイルを保存します。次に、Mac Excel 2008 に移動し、[ファイル] > [インポート] > [csv の選択] > [ファイルを検索] の順に選択し、[ファイルの原点] で [Windows (ANSI)] を選択すると、UTF-8 文字が正しく表示されます。少なくとも私にとってはそうです...

私はこれを使っています、そしてそれはうまくいきます

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;

#Excel が正しく読み取れる UTF-8 CSV を PHP で出力します。

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
//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"));
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top