web-dev-qa-db-ja.com

Microsoft Excelは.csvファイルの発音区別符号を破壊しますか?

プログラムでデータを(PHP 5.2を使用して).csvテストファイルにエクスポートしています。
サンプルデータ:Numéro 1(アクセント記号付きeに注意してください)。データはutf-8(前置BOMなし)です。

このファイルをMS Excelで開くと、Numéro 1と表示されます。

これを正しく表示するテキストエディター(UltraEdit)で開くことができます。 UEは、文字がdecimal 233であることを報告します。

どうすればテキストのエクスポート .csvファイルのデータMS Excelが正しくレンダリングするできれば、インポートウィザードまたはデフォルト以外のウィザード設定を使用せずに?

184
Freddo411

正しくフォーマットされたUTF8ファイルは、最初の3オクテットとして Byte Order Mark を持つことができます。これらは16進値0xEF、0xBB、0xBFです。これらのオクテットは、ファイルをUTF8としてマークするのに役立ちます(「バイトオーダー」情報としては関係ないため)。 1 このBOMが存在しない場合、コンシューマ/リーダーはエンコードタイプを推測しますテキスト。 UTF8に対応していないリーダーは、Windows-1252などの他のエンコーディングとしてバイトを読み取り、ファイルの先頭に文字を表示します。

ファイルの関連付けを介してUTF8 CSVファイルを開くと、Excelがシングルバイトエンコーディングであると想定する既知のバグがあります。存在を無視 UTF8 BOM。これは、notシステムのデフォルトのコードページまたは言語設定によって修正できます。 BOMはExcelで手掛かりになりません-動作しません。 (少数レポートでは、BOMが「テキストのインポート」ウィザードをトリガーすることがあると主張しています。)このバグは、Excel 2003以前に存在するようです。ほとんどのレポート(ここでの回答の中で)は、Excel 2007以降では修正されていると述べています。

canは常に「テキストのインポート」ウィザードを使用してUTF8 CSVファイルをExcelで正しく開くことができます。これにより、ファイルのエンコーディングを指定できます開いています。もちろん、これはあまり便利ではありません。

この回答の読者は、Excel <2007を特にサポートしていないが、生のUTF8テキストをExcelに送信している状況で、ほとんどの場合、それを誤って解釈し、テキストにÃなどのWindows-1252文字を振りかけています。 UTF8 BOMを追加するのがおそらく最良かつ迅速な修正です。

古いExcelのユーザーにこだわっており、ExcelがCSVの唯一のコンシューマである場合、UTF8ではなくUTF16をエクスポートすることでこの問題を回避できます。 Excel 2000および2003は、これらを正しくダブルクリックして開きます。 (他の一部のテキストエディターではUTF16に問題がある可能性があるため、オプションを慎重に検討する必要があります。)


*できない場合を除いて、(少なくとも)Excel 2011 for MacのインポートWizardは、実際にすべてのエンコーディングで動作するとは限りません。 </ anecdotal-evidence> :)

232
James Baker

BOM(\ uFEFF)を先頭に追加すると、ExcelでファイルがUTF-8として認識されるという点で(Excel 2007)うまくいきました。それ以外の場合は、保存してインポートウィザードを使用しても機能しますが、理想的ではありません。

38
Fergal

以下は、Microsoft Excelをユーザーに送信するときにプロジェクトで使用するPHPコードです。

  /**
   * Export an array as downladable Excel CSV
   * @param array   $header
   * @param array   $data
   * @param string  $filename
   */
  function toCSV($header, $data, $filename) {
    $sep  = "\t";
    $eol  = "\n";
    $csv  =  count($header) ? '"'. implode('"'.$sep.'"', $header).'"'.$eol : '';
    foreach($data as $line) {
      $csv .= '"'. implode('"'.$sep.'"', $line).'"'.$eol;
    }
    $encoded_csv = mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    header('Content-Description: File Transfer');
    header('Content-Type: application/vnd.ms-Excel');
    header('Content-Disposition: attachment; filename="'.$filename.'.csv"');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: '. strlen($encoded_csv));
    echo chr(255) . chr(254) . $encoded_csv;
    exit;
  }

更新:ファイル名の改善とバグにより、正しい長さの計算が修正されました。 TRiG および @ ivanhoe011 に感謝

30
Marc Carlucci

Excelバージョン(2003 + 2007)およびファイルタイプのすべての組み合わせに対する回答

ここでの他のほとんどの回答は、Excelのバージョンのみに関するものであり、必ずしも役立つとは限りません。これらの回答は、ご使用のExcelのバージョンには当てはまらない可能性があるためです。

たとえば、BOM文字を追加すると、列区切り文字の自動認識で問題が発生しますが、すべてのExcelバージョンで問題は発生しません。

ほとんどのExcelバージョンで動作するかどうかを決定する3つの変数があります。

  • エンコーディング
  • BOMキャラクターの存在
  • セルセパレーター

SAPのストイックな人がすべての組み合わせを試し、結果を報告しました。最終結果?ほとんどのExcelバージョンで機能させるには、BOMおよびタブ文字を区切り文字としてUTF16leを使用します。

信じられない?どちらもしませんが、ここを読んで泣いてください: http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator

13

CSVデータを出力する前にUTF-8 BOMをエコーし​​ます。これにより、Windowsのすべてのキャラクターの問題が修正されますが、Macでは機能しません。

echo "\xEF\xBB\xBF";

Windows PCでのみ使用されるファイルを生成する必要があるため、私にとってはうまくいきます。

8
Johal

サービスパックなし、BOM(U + ffefまたは0xEF、0xBB、0xBF、どちらも機能しない)なしでOffice 2007でUTF-8が機能しないを追加しました。

UTF-16は、0xff 0xef BOMを先頭に追加した「utf-16-le」を使用し、タブをセパレータとして使用してpythonでエンコードする場合に機能します。私は手動でBOMを書き出す必要があり、それから「utf-16」ではなく「utf-16-le」を使用しました。そうでない場合、各encode()は書き出されたすべての行にBOMを追加し、 2行目以降。

spはインストールされていなくてもUTF-16が機能するかどうかはわかりません。今は戻れません。 ため息

これは窓にあり、MACのオフィスについては知らない。

どちらの作業ケースでも、ブラウザから直接ダウンロードを起動するとインポートが機能し、テキストインポートウィザードが機能しないため、期待どおりに機能します。

7
gerald dol

Fregalが言ったように、\ uFEFFは進むべき道です。

<%@LANGUAGE="JAVASCRIPT" CODEPAGE="65001"%>
<%
Response.Clear();
Response.ContentType = "text/csv";
Response.Charset = "utf-8";
Response.AddHeader("Content-Disposition", "attachment; filename=excelTest.csv");
Response.Write("\uFEFF");
// csv text here
%>
4

拡張子が「xls」のHTMLファイルを保存でき、アクセントが機能します(少なくとも2007より前)。

例:これをメモ帳でSave utf8を使用してtest.xlsとして保存します。

<html>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
<table>
<tr>
  <th>id</th>
  <th>name</th>
</tr>
<tr>
 <td>4</td>
 <td>Hélène</td>
</tr>
</table>
</html>
2
Benjol

また、しばらく前に質問に「答えられた」ことにも気づきましたが、テキストウィザードを使用せずにExcelでutf8エンコードされたcsvファイルを正常に開くことができないという話は理解できません。

私の再現可能な経験:Old MacDonald had a farm,ÈÌÉÍØをメモ帳に入力し、Enterキーを押して、名前を付けて保存(UTF-8オプションを使用)します。

Pythonを使用して、実際にそこにあるものを表示します。

>>> open('oldmac.csv', 'rb').read()
'\xef\xbb\xbfOld MacDonald had a farm,\xc3\x88\xc3\x8c\xc3\x89\xc3\x8d\xc3\x98\r\n'
>>> ^Z

良い。メモ帳は、BOMを前面に配置しています。

次に、Windowsエクスプローラーに移動し、ファイル名をダブルクリックするか、右クリックして[...で開く]を使用すると、期待どおりにExcel(2003)が表示されます。

2
John Machin

CSV形式は、ExcelではUnicodeではなくASCIIとして実装されているため、発音区別符号がマングリングされます。公式のCSV標準がExcelでASCIIベースであると定義されていることを追跡した方法と同じ問題が発生しました。

1
Jeff Yates

Excel 2007は、BOM(EF BB BF)でエンコードされたcsvでUTF-8を適切に読み取ります。

Excel 2003(およびそれ以前)は、BOM(FF FE)でUTF-16LEを読み取りますが、カンマまたはセミコロンの代わりにTABを使用します。

1
user203319

UTF-8 BOMを含めることは必ずしも良いアイデアではないことに注意してください-ExcelのMacバージョンはそれを無視し、実際にBOMをASCIIとして表示します。スプレッドシートの最初のフィールドの先頭に3つの厄介な文字…

1
Ned Martin

私が見つけた別の解決策は、結果をWindowsコードページ1252(Windows-1252またはCP1252)としてエンコードすることでした。これは、たとえばContent-Typetext/csv; charset=Windows-1252のようなものに適切に設定し、同様に応答ストリームの文字エンコードを設定することにより行われます。

1
creechy

適切なバイトオーダーマークで始まるタブ区切りのリトルエンディアンUTF-16として、Excel 2007でCSVを適切に解析することしかできません。

1

Djangoで出力CSVファイルにBOMを書き込むと実際に機能しました。

def handlePersoonListExport(request):
    # Retrieve a query_set
    ...

    template = loader.get_template("export.csv")
    context = Context({
        'data': query_set,
    })

    response = HttpResponse()
    response['Content-Disposition'] = 'attachment; filename=export.csv'
    response['Content-Type'] = 'text/csv; charset=utf-8'
    response.write("\xEF\xBB\xBF")
    response.write(template.render(context))

    return response

詳細については http://crashcoursing.blogspot.com/2011/05/exporting-csv-with-special-characters.html どうもありがとう!

1
Lukas Batteau

これは文字エンコーディングの問題です。データをUTF-8としてエクスポートしているように見えます。UTF-8のéは2バイトシーケンス0xC3 0xA9であり、Windows-1252で解釈するとéです。データをExcelにインポートするときは、使用している文字エンコードがUTF-8であることを必ず確認してください。

1
Adam Rosenfield

問題を解決する方法を見つけました。これは厄介なハックですが、動作します:Open Officeでドキュメントを開き、任意のExcel形式で保存します。結果の.xlsまたは.xlsxは、アクセント記号付きの文字を表示します。

0
Fred Reillier

私のようにvb.netにレガシーコードがある場合、次のコードが役に立ちました。

    Response.Clear()
    Response.ClearHeaders()
    Response.ContentType = "text/csv"
    Response.Expires = 0
    Response.AddHeader("Content-Disposition", "attachment; filename=export.csv;")
    Using sw As StreamWriter = New StreamWriter(Context.Response.OutputStream, System.Text.Encoding.Unicode)
        sw.Write(csv)
        sw.Close()
    End Using
    Response.End()
0
Johann

ファイルを生成しているエンコードを確認します。Excelでファイルを正しく表示するには、システムのデフォルトコードページを使用する必要があります。

使用している言語は? .Netの場合、ファイルの生成中にEncoding.Defaultを使用するだけです。

0
albertein

Ruby 1.8.7を使用して、すべてのフィールドをUTF-16にエンコードし、BOMを破棄します(おそらく)。

次のコードがactive_scaffold_exportから抽出されます。

<%                                                                                                                                                                                                                                                                                                                           
      require 'fastercsv'                                                                                                                                                                                                                                                                                                        
      fcsv_options = {                                                                                                                                                                                                                                                                                                           
        :row_sep => "\n",                                                                                                                                                                                                                                                                                                        
        :col_sep => params[:delimiter],                                                                                                                                                                                                                                                                                          
        :force_quotes => @export_config.force_quotes,                                                                                                                                                                                                                                                                            
        :headers => @export_columns.collect { |column| format_export_column_header_name(column) }                                                                                                                                                                                                                                
      }                                                                                                                                                                                                                                                                                                                          

      data = FasterCSV.generate(fcsv_options) do |csv|                                                                                                                                                                                                                                                                           
        csv << fcsv_options[:headers] unless params[:skip_header] == 'true'                                                                                                                                                                                                                                                      
        @records.each do |record|                                                                                                                                                                                                                                                                                                
          csv << @export_columns.collect { |column|                                                                                                                                                                                                                                                                              
            # Convert to UTF-16 discarding the BOM, required for Excel (> 2003 ?)                                                                                                                                                                                                                                     
            Iconv.conv('UTF-16', 'UTF-8', get_export_column_value(record, column))[2..-1]                                                                                                                                                                                                                                        
          }                                                                                                                                                                                                                                                                                                                      
        end                                                                                                                                                                                                                                                                                                                      
      end                                                                                                                                                                                                                                                                                                                        
    -%><%= data -%>

重要な行は次のとおりです。

Iconv.conv('UTF-16', 'UTF-8', get_export_column_value(record, column))[2..-1]
0