Pergunta

Estou exportando dados programaticamente (usando PHP 5.2) para um arquivo de teste .csv.
Dados de exemplo: Numéro 1 (observe o e acentuado).Os dados são utf-8 (sem BOM prefixado).

Quando abro este arquivo no MS Excel é exibido como Numéro 1.

Consigo abrir isso em um editor de texto (UltraEdit) que o exibe corretamente.UE relata que o personagem é decimal 233.

Como posso exportar texto dados em um arquivo .csv para que o MS Excel irá renderizar corretamente de preferência sem forçar o uso do assistente de importação ou configurações não padrão do assistente?

Foi útil?

Solução

Um arquivo UTF8 formatado corretamente pode ter um Marca de pedidos de byte Como seus três primeiros octetos. Estes são os valores hexadecimais 0xef, 0xbb, 0xbf. Esses octetos servem para marcar o arquivo como UTF8 (uma vez que não são relevantes como informações de "ordem de bytes").1 Se esse nascimento não existir, o consumidor/leitor será deixado para inferir o tipo de codificação do texto. Os leitores que não são UTF8 capazes de ler os bytes como alguma outra codificação, como o Windows-1252, e exibirão os caracteres  No início do arquivo.

Há um bug conhecido em que o Excel, ao abrir os arquivos UTF8 CSV via Associação de Arquivos, assume que eles estão em uma codificação de bytes, desconsiderando A presença do UTF8 Bom. Isso pode não ser corrigido por qualquer sistema de codificação padrão ou configuração de idioma. O BOM não vai pisar no Excel - simplesmente não funcionará. (Um relatório minoritário afirma que o nascimento às vezes desencadeia o assistente de "texto de importação".) Esse bug parece existir no Excel 2003 e anteriormente. A maioria dos relatórios (em meio às respostas aqui) diz que isso é fixado no Excel 2007 e mais recente.

Observe que você posso Sempre* Abra corretamente os arquivos UTF8 CSV no Excel usando o assistente "Importar texto", que permite especificar a codificação do arquivo que você está abrindo. Claro que isso é muito menos conveniente.

Os leitores desta resposta provavelmente provavelmente em uma situação em que não apoiam particularmente o Excel <2007, mas estão enviando texto UTF8 bruto para o Excel, que está interpretando mal e aspergir com seu texto com à e outros caracteres Windows-1252 semelhantes. Adicionar o UTF8 BOM é provavelmente a sua melhor e mais rápida correção.

Se você está preso aos usuários nos excelentes mais antigos, e o Excel é o único consumidor do seu CSVS, você pode contornar isso exportando UTF16 em vez do UTF8. O Excel 2000 e 2003 clicará duas vezes em aberto corretamente. (Alguns outros editores de texto podem ter problemas com o UTF16, portanto, você pode ter que pesar suas opções com cuidado.)


* Exceto quando você não pode, (pelo menos) Excel 2011 para o Assistente de Importação do Mac, na verdade nem sempre funciona com todas as codificações, independentemente do que você diz.u003C/anecdotal-evidence> :)

Outras dicas

Preparando um nascido ( ufeff) funcionou para mim (Excel 2007), naquele Excel reconheceu o arquivo como UTF-8. Caso contrário, salvá -lo e usar o assistente de importação funciona, mas é menos ideal.

Abaixo está o código PHP que eu uso no meu projeto ao enviar o Microsoft Excel para o usuário:

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

UPDATED: Filename improvement and BUG fix correct length calculation. Graças a Trig e @Ivanhoe011

A resposta para todas as combinações de versões do Excel (2003 + 2007) e tipos de arquivo

A maioria das outras respostas aqui referem-se apenas à versão do Excel e não necessariamente o ajudarão, porque a resposta pode não ser verdadeira para a sua versão do Excel.

Por exemplo, adicionar o caractere BOM apresenta problemas com o reconhecimento automático do separador de colunas, mas não com todas as versões do Excel.

Existem 3 variáveis ​​que determinam se funciona na maioria das versões do Excel:

  • Codificação
  • Presença de personagem BOM
  • Separador de células

Alguém estóico na SAP tentou todas as combinações e relatou o resultado.Resultado final?Use UTF16le com BOM e caractere de tabulação como separador para que funcione na maioria das versões do Excel.

Você não acredita em mim?Eu também não, mas leia aqui e chore: http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator

Selecione UTF-8 Encontro ao importar. Se você usa o Office 2007, é aqui que você o escolhe: logo após abrir o arquivo.

Eco UTF-8 BOM antes de emitir dados de CSV. Isso corrige todos os problemas de caracteres no Windows, mas não funciona para o Mac.

echo "\xEF\xBB\xBF";

Funciona para mim porque preciso gerar um arquivo que será usado apenas no Windows PCs.

O UTF-8 não funciona para mim no Office 2007 sem nenhum pacote de serviço, com ou sem BOM (U+FFEF ou 0XEF, 0xbb, 0xbf, nenhum dos trabalhos) instalando o SP3 faz o UTF-8 funcionar quando 0Xef, 0xbb, 0xbf BOM é Antendido.

O UTF-16 funciona ao codificar em Python usando "UTF-16-LE" com um Bom 0xff 0XEF, com antecedido e usando a TAB como Seperator. Eu tive que escrever manualmente o nascido e depois usar "UTF-16-LE" em vez de "UTF-16"; caso contrário, cada codificador () prévia o nascido a cada linha escrita que apareceu como lixo na primeira coluna do segunda linha e depois.

Não sei dizer se o UTF-16 funcionaria sem nenhum SP instalado, pois não posso voltar agora. suspirar

Isso está no Windows, não sei sobre o Office for Mac.

Para ambos os casos de trabalho, a importação funciona ao lançar um download diretamente do navegador e o assistente de importação de texto não interveio, ele funciona como você esperaria.

Como Fegal disse que ufeff é o caminho a percorrer.

<%@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
%>

Também notei que a pergunta foi "respondida" há algum tempo, mas não entendo as histórias que dizem que você não pode abrir um arquivo CSV codificado por UTF8 no Excel sem usar o assistente de texto.

Minha experiência reproduzível: tipo Old MacDonald had a farm,ÈÌÉÍØ No bloco de notas, pressione Enter e salve como (usando a opção UTF-8).

Usando Python para mostrar o que realmente está lá:

>>> 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. O BLETEPAD colocou um nascido na frente.

Agora vá para o Windows Explorer, clique duas vezes no nome do arquivo ou clique com o botão direito do mouse e use "Abrir com ...", e o Pops Excel (2003) com a exibição conforme o esperado.

Você pode salvar um arquivo HTML com a extensão 'XLS' e os sotaques funcionarão (pelo menos antes de 2007).

Exemplo: salve isso (usando salvar como utf8 no bloco de notas) como 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>

Isso é apenas uma questão de codificações de personagens. Parece que você está exportando seus dados como UTF-8: É no UTF-8 é a sequência de dois bytes 0xc3 0XA9, que quando interpretada no Windows-1252 é. Ao importar seus dados para o Excel, certifique-se de dizer que o caractere que está usando é UTF-8.

O formato CSV é implementado como ASCII, não unicode, no Excel, consumindo assim os diacríticos. Tivemos o mesmo problema, que é assim que eu rastreei que o padrão oficial do CSV foi definido como sendo baseado no ASCII no Excel.

Escrever um nascido no arquivo CSV de saída realmente funcionou para mim em Django:

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

Para mais informações http://crashcoursing.blogspot.com/2011/05/exporting-csv-with-special-characters.html Obrigado rapazes!

Outra solução que encontrei foi apenas para codificar o resultado como código do Windows página 1252 (Windows-1252 ou CP1252). Isso seria feito, por exemplo, configurando Content-Type apropriadamente para algo como text/csv; charset=Windows-1252 e definir a codificação do caractere do fluxo de resposta da mesma forma.

Observe que incluir a lista técnica UTF-8 não é necessariamente uma boa ideia - as versões Mac do Excel ignoram isso e exibirão a lista técnica como ASCII… três caracteres desagradáveis ​​no início do primeiro campo da sua planilha…

Verifique a codificação na qual você está gerando o arquivo, para fazer com que o Excel exiba o arquivo corretamente, você deve usar o sistema de código padrão do sistema.

Qual linguagem você está usando? Se for .NET, você só precisará usar o coding.default enquanto gera o arquivo.

O Excel 2007 lê adequadamente o UTF-8 com CSV codificado de BOM (EF BB BF).

O Excel 2003 (e talvez anterior) lê o UTF-16LE com BOM (FF FE), mas com guias em vez de vírgulas ou semicolons.

Só posso fazer com que o CSV analise corretamente no Excel 2007 como Little-Endian UTF-16 separado por Tab-Separado, começando com a marca de ordem de bytes adequada.

Se você tem código legado no vb.net como eu, o código a seguir funcionou para mim:

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

Encontrei uma maneira de resolver o problema. Este é um hack desagradável, mas funciona: abra o documento com Escritório aberto, salve -o em qualquer formato do Excel; o resultado .xls ou .xlsx exibirá os caracteres acentuados.

Com o Ruby 1.8.7, codificado todos os campos para UTF-16 e descarto Bom (talvez).

O código a seguir é extraído de 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 -%>

A linha importante é:

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

Abra o arquivo CSV com o bloco de notas ++ codificador, selecione converter para UTF-8 (não convert em UTF-8 (sem BOM)) Salvar aberto pelo Double Clic com Excel Hope que ajuda Christophe Grison

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top