Pregunta

Estoy exportando datos mediante programación (usando PHP 5.2) a un archivo de prueba .csv.
Datos de ejemplo: Numéro 1 (nótese la e acentuada).Los datos son utf-8 (sin lista de materiales antepuesta).

Cuando abro este archivo en MS Excel se muestra como Numéro 1.

Puedo abrir esto en un editor de texto (UltraEdit) que lo muestra correctamente.UE informa que el personaje es decimal 233.

Cómo puedo exportar texto datos en un archivo .csv para que que MS Excel renderizará correctamente ¿Preferiblemente sin forzar el uso del asistente de importación o una configuración del asistente no predeterminada?

¿Fue útil?

Solución

Un archivo UTF8 formateado correctamente puede tener un Marca de orden de bytes como sus primeros tres octetos.Estos son los valores hexadecimales 0xEF, 0xBB, 0xBF.Estos octetos sirven para marcar el archivo como UTF8 (ya que no son relevantes como información de "orden de bytes").1 Si esta lista de materiales no existe, el consumidor/lector debe inferir el tipo de codificación del texto.Los lectores que no son compatibles con UTF8 leerán los bytes como alguna otra codificación, como Windows-1252, y mostrarán los caracteres.  al inicio del archivo.

Existe un error conocido por el cual Excel, al abrir archivos CSV UTF8 mediante asociación de archivos, asume que están en una codificación de un solo byte. sin tener en cuenta la presencia de la lista de materiales UTF8.Esto puede no ser solucionado por cualquier página de códigos predeterminada del sistema o configuración de idioma.La lista de materiales no dará pistas en Excel, simplemente no funcionará.(Un informe minoritario afirma que la lista de materiales a veces activa el asistente "Importar texto"). Este error parece existir en Excel 2003 y versiones anteriores.La mayoría de los informes (entre las respuestas aquí) dicen que esto está solucionado en Excel 2007 y versiones posteriores.

Tenga en cuenta que usted poder Siempre* abra correctamente archivos CSV UTF8 en Excel usando el asistente "Importar texto", que le permite especificar la codificación del archivo que está abriendo.Por supuesto, esto es mucho menos conveniente.

Lo más probable es que los lectores de esta respuesta se encuentren en una situación en la que no son particularmente compatibles con Excel <2007, pero envían texto UTF8 sin formato a Excel, lo que lo malinterpreta y salpica su texto con à y otros caracteres similares de Windows-1252. Agregar la lista de materiales UTF8 es probablemente la mejor y más rápida solución.

Si está atrapado con usuarios de Excel más antiguos y Excel es el único consumidor de sus archivos CSV, puede solucionar este problema exportando UTF16 en lugar de UTF8.Excel 2000 y 2003 harán doble clic para abrirlos correctamente.(Algunos otros editores de texto pueden tener problemas con UTF16, por lo que es posible que tengas que sopesar tus opciones cuidadosamente).


* Excepto cuando no puedas, (al menos) el Asistente de importación de Excel 2011 para Mac no siempre funciona con todas las codificaciones, independientemente de lo que le digas.</evidencia-anecdótica> :)

Otros consejos

Anteponer una BOM (\ uFEFF) funcionó para mí (Excel 2007), en ese Excel reconoció el archivo como UTF-8. De lo contrario, guardarlo y usar el asistente de importación funciona, pero es menos ideal.

A continuación se muestra el código PHP que uso en mi proyecto cuando envío Microsoft Excel al usuario:

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

ACTUALIZADO: La mejora del nombre de archivo y el ERROR corrigen el cálculo correcto de la longitud. Gracias a TRiG y @ ivanhoe011

La respuesta para todas las combinaciones de versiones de Excel (2003 + 2007) y tipos de archivo

La mayoría de las otras respuestas aquí se refieren solo a su versión de Excel y no necesariamente lo ayudarán, porque su respuesta podría no ser cierta para su versión de Excel.

Por ejemplo, agregar el carácter BOM presenta problemas con el reconocimiento automático del separador de columnas, pero no con todas las versiones de Excel.

Hay 3 variables que determinan si funciona en la mayoría de las versiones de Excel:

  • Codificación
  • Presencia de personaje BOM
  • Separador de celdas

Alguien estoico en SAP probó todas las combinaciones e informó el resultado. ¿Resultado final? Use UTF16le con BOM y caracteres de tabulación como separador para que funcione en la mayoría de las versiones de Excel.

¿No me crees? Yo tampoco, pero lea aquí y llore: http://wiki.sdn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator

seleccione UTF-8 enconding al importar. si usa Office 2007, aquí es donde lo eligió: justo después de abrir el archivo.

Echo UTF-8 BOM antes de enviar datos CSV. Esto soluciona todos los problemas de caracteres en Windows, pero no funciona para Mac.

echo "\xEF\xBB\xBF";

Funciona para mí porque necesito generar un archivo que se usará solo en PC con Windows.

UTF-8 no funciona para mí en Office 2007 sin ningún paquete de servicio, con o sin BOM (U + ffef o 0xEF, 0xBB, 0xBF, ninguno funciona) la instalación de sp3 hace que UTF-8 funcione cuando 0xEF, 0xBB, 0xBF BOM está antepuesto.

UTF-16 funciona cuando se codifica en python usando " utf-16-le " con un 0xff 0xef Lista de materiales antepuesta, y usando la pestaña como separador. Tuve que escribir manualmente la lista de materiales y luego usar & Quot; utf-16-le & Quot; en lugar de " utf-16 " ;, de lo contrario, cada encode () antepuso la lista de materiales a cada fila escrita que apareció como basura en la primera columna de la segunda línea y después.

no puede decir si UTF-16 funcionaría sin ningún sp instalado, ya que No puedo volver ahora. sigh

Esto está en Windows, no sé sobre Office para MAC.

para ambos casos de trabajo, la importación funciona cuando se inicia una descarga directamente desde el navegador y el asistente de importación de texto no intervienen, funciona como es de esperar.

Como dijo Fregal, \ uFEFF es el camino a seguir.

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

También me di cuenta de que la pregunta era " respondió " Hace algún tiempo, pero no entiendo las historias que dicen que no puede abrir un archivo csv codificado con utf8 con éxito en Excel sin usar el asistente de texto.

Mi experiencia reproducible: Escriba Old MacDonald had a farm,ÈÌÉÍØ en el Bloc de notas, presione Entrar y luego Guardar como (con la opción UTF-8).

Uso de Python para mostrar lo que hay realmente allí:

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

Bien. El Bloc de notas ha puesto una lista de materiales en la parte delantera.

Ahora vaya al Explorador de Windows, haga doble clic en el nombre del archivo o haga clic con el botón derecho y use " Abrir con ... " ;, y aparece Excel (2003) con la visualización como se esperaba.

Puede guardar un archivo html con la extensión 'xls' y los acentos funcionarán (antes de 2007 al menos).

Ejemplo: guarde esto (usando Guardar como utf8 en el Bloc 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>

Esto es solo una cuestión de codificaciones de caracteres. Parece que está exportando sus datos como UTF-8: & # 233; en UTF-8 está la secuencia de dos bytes 0xC3 0xA9, que cuando se interpreta en Windows-1252 es & # 195; & # 169 ;. Cuando importe sus datos a Excel, asegúrese de decirle que la codificación de caracteres que está usando es UTF-8.

El formato CSV se implementa como ASCII, no unicode, en Excel, lo que destruye los diacríticos. Experimentamos el mismo problema que es cómo rastreé que el estándar CSV oficial se definiera como basado en ASCII en Excel.

Escribir una lista de materiales en el archivo CSV de salida realmente funcionó para mí en 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 obtener más información http: //crashcoursing.blogspot .com / 2011/05 / exporting-csv-with-special-characters.html ¡Gracias chicos!

Otra solución que encontré fue simplemente codificar el resultado como página de códigos de Windows 1252 (Windows-1252 o CP1252).Esto se haría, por ejemplo, configurando Content-Type apropiadamente a algo como text/csv; charset=Windows-1252 y establecer la codificación de caracteres del flujo de respuesta de manera similar.

Tenga en cuenta que incluir la lista de materiales UTF-8 no es necesariamente una buena idea: las versiones para Mac de Excel lo ignoran y en realidad mostrarán la lista de materiales como ASCII & # 8230; tres caracteres desagradables al comienzo del primer campo en su hoja de cálculo & # 8230;

Verifique la codificación en la que está generando el archivo, para que Excel muestre el archivo correctamente, debe usar la página de códigos predeterminada del sistema.

¿Qué idioma estás usando? si es .Net solo necesita usar Encoding.Default mientras genera el archivo.

Excel 2007 lee correctamente UTF-8 con csv codificado BOM (EF BB BF).

Excel 2003 (y tal vez antes) lee UTF-16LE con BOM (FF FE), pero con TAB en lugar de comas o punto y coma.

Solo puedo hacer que CSV se analice correctamente en Excel 2007 como little-endian UTF-16 separado por tabulaciones comenzando con la marca de orden de bytes adecuada.

Si tiene código heredado en vb.net como yo, el siguiente código funcionó para mí:

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

He encontrado una manera de resolver el problema. Este es un truco desagradable pero funciona: abra el documento con Open Office , luego guárdelo en cualquier formato de Excel; el .xls o .xlsx resultante mostrará los caracteres acentuados.

Con Ruby 1.8.7 codifico cada campo a UTF-16 y descarto BOM (tal vez).

El siguiente código se extrae 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 -%>

La línea importante es:

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

abre el archivo csv con notepad ++ haga clic en Codificar, seleccione convertir a UTF-8 (no convertir a UTF-8 (sin BOM)) Salvar abierto por doble clic con excel Espero que ayuda Christophe GRISON

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top