Które kodowanie poprawnie otwiera pliki CSV w programie Excel na komputerach Mac i Windows?

137

Mamy aplikację internetową, która eksportuje pliki CSV zawierające obce znaki z UTF-8, bez BOM. Użytkownicy systemów Windows i Mac otrzymują śmieciowe znaki w programie Excel. Próbowałem przekonwertować na UTF-8 z BOM; Excel / Win jest w porządku, Excel / Mac pokazuje bełkot. Używam programu Excel 2003 / Win, Excel 2011 / Mac. Oto wszystkie kodowania, które wypróbowałem:

Encoding  BOM      Win                            Mac
--------  ---      ----------------------------   ------------
utf-8     --       scrambled                      scrambled
utf-8     BOM      WORKS                          scrambled
utf-16    --       file not recognized            file not recognized
utf-16    BOM      file not recognized            Chinese gibberish
utf-16LE  --       file not recognized            file not recognized
utf-16LE  BOM      characters OK,                 same as Win
                   row data all in first field

Najlepszy to UTF-16LE z BOM, ale CSV nie jest rozpoznawany jako taki. Separatorem pól jest przecinek, ale średnik niczego nie zmienia.

Czy jest jakieś kodowanie, które działa w obu światach?

Timm
źródło
1
Co się stanie, jeśli użyjesz UTF-16LE dla wszystkich danych pola, ale użyjesz znaku 8-bitowego / ASCII jako przecinka? Na podstawie tego artykułu ( creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndEncodings ) program Excel może interpretować przecinek Unicode jako część danych pola zamiast separatora.
jveazey
1
Ciekawa wskazówka @jveazey. Spróbuję tego: mb_convert_encoding($str, "UTF-16LE");w moim kodzie eksportu i opublikuj wyniki tutaj.
Timm,
Nie żeby ci to pomogło, ale przetestowałem Excel 2007 SP2 na Windows (używając Notepad2 do tworzenia plików testowych). Wszystko działało z wyjątkiem BOM UTF-16LE (taki sam wynik jak twój w systemie Windows) i BOM UTF-16BE (który przeanalizował pola poprawnie, ale BOM został uwzględniony jako pierwsze 2 znaki w A1).
jveazey
Znalazłem również ten stackoverflow.com/questions/155097/ ...
jveazey
@hveazey, na cytowane pytanie odpowiada creechy polecająca stronę kodową Windows-1252. To nie zadziałało w moim przypadku (niemieckie umlauty i ostre s).
Timm

Odpowiedzi:

61

Kodowanie Excela

Zauważyłem, że WINDOWS-1252kodowanie jest najmniej frustrujące w przypadku programu Excel. Ponieważ jest to w zasadzie własny, zastrzeżony zestaw znaków Microsoftu, można założyć, że będzie działał zarówno na Mac, jak i na Windows w wersji MS-Excel. Obie wersje zawierają przynajmniej odpowiedni selektor „Pochodzenie pliku” lub „Kodowanie pliku”, który prawidłowo odczytuje dane.

W zależności od systemu i narzędzi użyć, to kodowanie może być również nazwany CP1252, ANSI, Windows (ANSI), MS-ANSIlub po prostu Windows, między innymi odmianami.

To kodowanie jest nadzbiorem ISO-8859-1(aka LATIN1i innych), więc możesz wrócić do niego, ISO-8859-1jeśli WINDOWS-1252z jakiegoś powodu nie możesz go użyć . Pamiętaj, że ISO-8859-1brakuje niektórych znaków z, WINDOWS-1252jak pokazano tutaj:

| Char | ANSI | Unicode | ANSI Hex | Unicode Hex | HTML entity | Unicode Name                               | Unicode Range            |
| €    | 128  | 8364    | 0x80     | U+20AC      | €      | euro sign                                  | Currency Symbols         |
| ‚    | 130  | 8218    | 0x82     | U+201A      | ‚     | single low-9 quotation mark                | General Punctuation      |
| ƒ    | 131  | 402     | 0x83     | U+0192      | ƒ      | Latin small letter f with hook             | Latin Extended-B         |
| „    | 132  | 8222    | 0x84     | U+201E      | „     | double low-9 quotation mark                | General Punctuation      |
| …    | 133  | 8230    | 0x85     | U+2026      | …    | horizontal ellipsis                        | General Punctuation      |
| †    | 134  | 8224    | 0x86     | U+2020      | †    | dagger                                     | General Punctuation      |
| ‡    | 135  | 8225    | 0x87     | U+2021      | ‡    | double dagger                              | General Punctuation      |
| ˆ    | 136  | 710     | 0x88     | U+02C6      | ˆ      | modifier letter circumflex accent          | Spacing Modifier Letters |
| ‰    | 137  | 8240    | 0x89     | U+2030      | ‰    | per mille sign                             | General Punctuation      |
| Š    | 138  | 352     | 0x8A     | U+0160      | Š    | Latin capital letter S with caron          | Latin Extended-A         |
| ‹    | 139  | 8249    | 0x8B     | U+2039      | ‹    | single left-pointing angle quotation mark  | General Punctuation      |
| Œ    | 140  | 338     | 0x8C     | U+0152      | Œ     | Latin capital ligature OE                  | Latin Extended-A         |
| Ž    | 142  | 381     | 0x8E     | U+017D      |             | Latin capital letter Z with caron          | Latin Extended-A         |
| ‘    | 145  | 8216    | 0x91     | U+2018      | ‘     | left single quotation mark                 | General Punctuation      |
| ’    | 146  | 8217    | 0x92     | U+2019      | ’     | right single quotation mark                | General Punctuation      |
| “    | 147  | 8220    | 0x93     | U+201C      | “     | left double quotation mark                 | General Punctuation      |
| ”    | 148  | 8221    | 0x94     | U+201D      | ”     | right double quotation mark                | General Punctuation      |
| •    | 149  | 8226    | 0x95     | U+2022      | •      | bullet                                     | General Punctuation      |
| –    | 150  | 8211    | 0x96     | U+2013      | –     | en dash                                    | General Punctuation      |
| —    | 151  | 8212    | 0x97     | U+2014      | —     | em dash                                    | General Punctuation      |
| ˜    | 152  | 732     | 0x98     | U+02DC      | ˜     | small tilde                                | Spacing Modifier Letters |
| ™    | 153  | 8482    | 0x99     | U+2122      | ™     | trade mark sign                            | Letterlike Symbols       |
| š    | 154  | 353     | 0x9A     | U+0161      | š    | Latin small letter s with caron            | Latin Extended-A         |
| ›    | 155  | 8250    | 0x9B     | U+203A      | ›    | single right-pointing angle quotation mark | General Punctuation      |
| œ    | 156  | 339     | 0x9C     | U+0153      | œ     | Latin small ligature oe                    | Latin Extended-A         |
| ž    | 158  | 382     | 0x9E     | U+017E      |             | Latin small letter z with caron            | Latin Extended-A         |
| Ÿ    | 159  | 376     | 0x9F     | U+0178      | Ÿ      | Latin capital letter Y with diaeresis      | Latin Extended-A         |

Zwróć uwagę, że brakuje znaku euro . Ten stół można znaleźć u Alana Wooda .

Konwersja

Konwersja przebiega inaczej w każdym narzędziu i języku. Załóżmy jednak, że masz plik, o query_result.csvktórym wiesz, że jest UTF-8zakodowany. Przekształcić go WINDOWS-1252za pomocą iconv:

iconv -f UTF-8 -t WINDOWS-1252 query_result.csv > query_result-win.csv
mikezter
źródło
6
Trochę kłopotów, ale wydaje się, że jest to odpowiedź na importowanie plików .csv ze znakami europejskimi do programu Excel w systemie Mac OSX
Fergie
1
Prawdziwe. Zamiast tego odpowiada na pytanie OP. W twoim przypadku musisz najpierw poznać (lub odgadnąć) kodowanie użyte w twoim "pliku .csv ze znakami europejskimi". Następnie możesz go przekonwertować na WINDOS-1252, który najprawdopodobniej zostanie poprawnie zinterpretowany zarówno przez Maca, jak i Windows Excel.
mikezter
1
To nie jest prawdziwe rozwiązanie, prędzej czy później natkniesz się na postać, której nie da się zamienić na WINDOWS-1252.
Walter Tross
2
WINDOWS-1252 zawiedzie, jeśli występuje chiński znak. Wydaje się więc, że jedyną opcją jest UTF-16LE z BOM.
XWang
Działa to dobrze w przypadku eksportów danych SQL ze znakami diakrytycznymi.
motorbaby
26

W przypadku UTF-16LE z BOM, jeśli jako separatory użyjesz znaków tabulacji zamiast przecinków, program Excel rozpozna pola. Powodem, dla którego to działa, jest fakt, że Excel w rzeczywistości używa parsera Unicode * .txt.

Uwaga : jeśli plik jest edytowany w programie Excel i zapisany, zostanie zapisany jako rozdzielany tabulatorami ASCII. Problem polega teraz na tym, że po ponownym otwarciu pliku program Excel zakłada, że ​​jest to prawdziwy CSV (z przecinkami), widzi, że nie jest to Unicode, więc analizuje go jako rozdzielany przecinkami - i dlatego tworzy z niego skrót!

Aktualizacja : Wydaje się, że powyższe zastrzeżenie nie dotyczy mnie dzisiaj przynajmniej w programie Excel 2010 (Windows), chociaż wydaje się, że istnieje różnica w zachowaniu oszczędzania, jeśli:

  • edytujesz i zamykasz program Excel (próbuje zapisać jako „Unicode * .txt”)

w porównaniu do:

  • edycja i zamknięcie samego pliku (działa zgodnie z oczekiwaniami).
Duncan Smart
źródło
1
Fajnie, ale zastrzeżenie łamie mi rozwiązanie; użytkownicy końcowi nie będą zadowoleni z zepsutych arkuszy Excela.
Timm
Być może, jeśli zmienisz początkowe rozszerzenie pliku na * .txt, zadziała, ale wtedy utracisz powiązanie między typem pliku a programem Excel: tj. Nie mogą dwukrotnie kliknąć pliku i automatycznie otworzyć go w programie Excel.
Duncan Smart
To nie zadziała dla mnie. Nie znając się na komputerze, użytkownik końcowy musi bez przeszkód otworzyć go w programie Excel.
Timm
Moje arkusze programu Excel „.csv” wyglądają dobrze ze znakami specjalnymi i oddzielnymi polami. Rozpoczynam ciąg wyjściowy od „\ ufeff” jako znacznika kolejności bajtów (BOM), a następnie używam tabulatorów „\ t” zamiast przecinków do separacji pól i koduję plik za pomocą „utf-16LE”. Działa jak marzenie, dzięki tej stronie!
Geek Stocks,
sep=,Kodowanie pierwszej linii i UTF16LE działało u mnie i nie wymagało innego znaku separatora (pozostał przecinek). Otwarcie pliku przez dwukrotne kliknięcie wczytało plik poprawnie, z zachowaniem znaków specjalnych i podziałów wierszy w komórkach. Wada: sep=,nagłówek nie jest rozpoznawany przez żaden program poza Excelem, o ile widziałem. Ale OpenOffice / LibreOffice i tak nie wymagają tego hacka (podziały wierszy w zawartości komórki działają dobrze, podczas gdy ładowanie z pliku tekstowego / użycie tekstu do asystenta kolumn w Excelu nie obsługuje poprawnie podziałów wierszy w komórkach).
CodeManX
24

Najważniejsze jest to: nie ma rozwiązania. Excel 2011 / Mac nie może poprawnie zinterpretować pliku CSV zawierającego umlauty i znaki diakrytyczne bez względu na to, jakie kodowanie lub przeskakujesz. Byłbym szczęśliwy, gdyby ktoś powiedział mi coś innego!

Timm
źródło
4
Zauważyłem, że kodowanie WIN-1252 lub ISO-8859-1 działa. Zobacz moją odpowiedź.
mikezter
3
Rozwiązaniem jest użycie UTF-16LE i upewnienie się, że używasz tabulatorów do oddzielania kolumn zamiast przecinków.
Tim Groeneveld,
Czy naprawdę próbowałeś tego na Win i Mac Tim? Jak wspomniałem, w moim przypadku TSV nie wchodzi w grę.
Timm
1
Dla mnie eksport działa dobrze, jeśli używam kodowania WIN-1252, zarówno w wersji Mac, jak i Windows w programie Excel. @Timm, powinieneś rozważyć zmianę zaakceptowanej odpowiedzi.
Pierre Arnaud
2
W przypadku tych, dla których to działa, czy faktycznie rozszerzyliście (jak chińskie) znaki w swoich zbiorach danych? Kodowanie WIN-1252 przerywa te, ponieważ są poza zakresem.
Bill Leeper
11

Próbowałeś tylko pliku CSV rozdzielanego przecinkami i średnikami. Gdybyś wypróbował CSV rozdzielany znakami tabulacji (zwany także TSV), znalazłbyś odpowiedź:

UTF-16LE z BOM (znak kolejności bajtów), oddzielone tabulatorami


Ale : W komentarzu wspominasz, że TSV nie jest dla ciebie opcją (chociaż nie udało mi się znaleźć tego wymagania w twoim pytaniu). Szkoda. Często oznacza to, że pozwalasz na ręczną edycję plików TSV, co prawdopodobnie nie jest dobrym pomysłem. Wizualne sprawdzanie plików TSV nie stanowi problemu. Ponadto edytory można ustawić tak, aby wyświetlały specjalny znak do oznaczania zakładek.

I tak, wypróbowałem to na Windows i Mac.

Walter Tross
źródło
4

Oto kwestia importowania pliku CSV zakodowanego w utf8 do programu Excel 2011 dla komputerów Mac: Microsoft mówi: „Program Excel dla komputerów Mac obecnie nie obsługuje UTF-8”. Excel 2011 dla komputerów Mac i UTF-8

Tak, droga do stwardnienia rozsianego!

Timm
źródło
4

Najlepszym obejściem do odczytywania plików CSV za pomocą UTF-8 na Macu jest przekonwertowanie ich na format XLSX. Znalazłem skrypt autorstwa Konrada Foerstnera, który poprawiłem trochę, dodając obsługę różnych znaków separatora.

Pobierz skrypt z Github https://github.com/brablc/clit/blob/master/csv2xlsx.py . Aby go uruchomić trzeba będzie zainstalować moduł Pythona openpyxl for Excel manipulacji pliku: sudo easy_install openpyxl.

brablc
źródło
3

W moim przypadku to zadziałało (Mac, Excel 2011, cyrylica i łacińskie znaki z czeskimi znakami diakrytycznymi):

  • Charset UTF-16LE (po prostu UTF-16 to za mało)
  • BOM "\ xFF \ xFE"
  • \ t (tabulator) jako separator
  • Nie zapomnij zakodować również separatora i CRLF :-)
  • Użyj iconv zamiast mb_convert_encoding
Marek Demčák
źródło
2

Wydaje mi się, że Excel 2011 dla Mac OS nie używa Encoding.GetEncoding ("10000"), jak myślałem i zmarnowałem 2 dni z tą samą iso, co w systemie Microsoft OS. Najlepszym dowodem na to jest utworzenie pliku w Excel 2011 dla MAC ze specjalnymi znakami, zapisanie go jako CSV, a następnie otwarcie w edytorze tekstu MAC, a znaki są zaszyfrowane.

Dla mnie to podejście zadziałało - co oznacza, że ​​eksport CSV w programie Excel 2011 w systemie MAC OS zawiera w sobie specjalne znaki zachodnioeuropejskie:

Encoding isoMacOS = Encoding.GetEncoding("iso-8859-1");
Encoding defaultEncoding = Encoding.Default; 

// Convert the string into a byte array.
byte[] defaultEncodingBytes = defaultEncoding.GetBytes(exportText);

// Perform the conversion from one encoding to the other.
byte[] ansiBytes = Encoding.Convert(defaultEncoding, isoMacOS, defaultEncodingBytes);

decodedString = isoMacOS.GetString(ansiBytes);
user525081
źródło
W jakim języku używasz @ user525081? Czy możesz przetłumaczyć to na PHP?
Timm
@Timm, który wygląda jak przykład w Javie, ale w PHP możesz użyć iconv do wykonania konwersji - de3.php.net/manual/en/function.iconv.php
Ashish Datta
OK @ user525081, taka sama oferta jak w przypadku innych odpowiedzi. To jest przeznaczone dla użytkowników komputerów Mac, pozostawiając ludzi Windows na lodzie; i nie odpowiada na pierwotne pytanie - kodowanie, które działa na obu platformach. Dzięki.
Timm,
2

UTF-8 bez BOM obecnie działa dla mnie w programie Excel Mac 2011 14.3.2.

UTF-8 + BOM działa, ale BOM renderowane jako bełkot.

UTF-16 działa, jeśli zaimportujesz plik i ukończysz kreatora, ale nie po dwukrotnym kliknięciu.

Craig Stuntz
źródło
2

Poniższe działały dla mnie w programie Excel 2011 dla komputerów Mac i Windows Excel 2002:

  1. Używając iconv na Macu, przekonwertuj plik do UTF-16 Little-Endian + nazwij go * .txt (rozszerzenie .txt zmusza Excela do uruchomienia Kreatora importu tekstu):

    iconv -f UTF-8 -t UTF-16LE filename.csv >filename_UTF-16LE.csv.txt

  2. Otwórz plik w programie Excel iw Kreatorze importu tekstu wybierz:

    • Krok 1: Pochodzenie pliku : zignoruj ​​go, nie ma znaczenia, co wybierzesz
    • Krok 2: wybierz odpowiednie wartości dla separatorów i kwalifikatora tekstu
    • Krok 3: w razie potrzeby wybierz formaty kolumn

PS UTF-16LE stworzony przez iconv ma na początku bajty BOM FF FE.

PPS Mój oryginalny plik csv został utworzony na komputerze z systemem Windows 7 w formacie UTF-8 (z bajtami BOM EF BB BF na początku) i wykorzystywał podziały wierszy CRLF. Przecinek został użyty jako separator pól, a pojedynczy cudzysłów jako kwalifikator tekstu. Zawierał litery ASCII oraz różne litery łacińskie z tyldami, umlautami itp., A także cyrylicę. Wszystkie wyświetlane poprawnie w programie Excel dla Win i Mac.

PPPS Dokładne wersje oprogramowania:
* Mac OS X 10.6.8
* Excel dla Mac 2011 wer. 14.1.3
* Windows Server 2003 SP2
* Windows Excel 2002 wer. 10.2701.2625

Koit Saarevet
źródło
Jeśli masz plik UTF-8 bez BOM, iconv przekonwertuje go na UTF-16LE bez BOM (i niestety nie ma sposobu, aby powiedzieć iconv, aby go dodał)
Walter Tross
2

W moim systemie Mac OS Text Wrangler zidentyfikował plik CSV utworzony w programie Excel jako mający kodowanie „zachodnie”.

Po pewnym googlowaniu zrobiłem ten mały skrypt (nie jestem pewien co do dostępności Windowsa, może z Cygwin ?):

$ cat /usr/local/bin/utf8.sh

#!/bin/bash

INPUTFILE="$1"

iconv -f macroman -c -t UTF-8 $INPUTFILE |tr '\r' '\n' >/tmp/file.$$.csv

mv $INPUTFILE ms_trash
mv /tmp/file.$$.csv $INPUTFILE
Nuno
źródło
To jedyna rzecz, która działała dla mnie w systemie OS X 10.14.2 (i programie Excel 2011)
Donald,
1

W moim przypadku dodanie Preambuły do ​​pliku rozwiązało mój problem:

var data = Encoding.UTF8.GetBytes(csv);
var result = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
return File(new MemoryStream(result), "application/octet-stream", "data.csv");
razon
źródło
0

zamiast csv, próbując wyprowadzić html z rozszerzeniem XLS i typem MIME „application / excel”. Wiem, że to zadziała w systemie Windows, ale nie mogę mówić w systemie MacOS

royce3
źródło
Dzięki @ royce23, ale oferuję tylko plik CSV do pobrania. Nie mogę przedstawić go poprzez HTTP, ponieważ sama wielkość znaczników spowolni odpowiedź do indeksowania - eksportowany tabela może zawierać miliony wierszy ...
Timm
z css twój HTML byłby tylko niewielki ułamek większy niż csv, na przykład: <r><c>id</c><c>name</c><c>phone</c> </r>
royce3
Nie jestem pewien, czy rozumiem, ale zapisuję plik CSV na serwerze i oferuję link do pobrania. Generowanie odpowiedzi HTML pochłania zbyt dużo pamięci PHP ...
Timm,
To zadziała (znaki UTF-8), ale jeśli masz osadzone podziały wierszy w komórkach ( brtag), Excel dla komputerów Mac ignoruje (działa z systemem Windows) CSS mso-data-placement:same-cell;
cropredy
0

To działa dla mnie

  1. Otwórz plik w BBEdit lub TextWrangler *.
  2. Ustaw plik jako Unicode (UTF-16 Little-Endian) (zakończenia linii mogą być w systemie Unix lub Windows). Zapisać!
  3. W programie Excel: Dane> Pobierz dane zewnętrzne> Importuj plik tekstowy ...

Teraz kluczowa kwestia, wybierz MacIntosh jako pochodzenie pliku (powinien to być pierwszy wybór).

Używa programu Excel 2011 (wersja 14.4.2)

* W dolnej części okna znajduje się małe menu

Gazzer
źródło
0

Rozwiąż ten problem za pomocą java (UTF-16LE z BOM):

String csvReportStr = getCsvReport();
byte[] data = Charset.forName("UTF-16LE").encode(csvReportStr)
    .put(0, (byte) 0xFF)
    .put(1, (byte) 0xFE)
    .array();

Zauważ, że plik CSV powinien używać TAB jako separator. Możesz czytać plik CSV zarówno w systemie Windows, jak i MAC OS X.

Odnosić się do: Jak kodować / dekodować tablice bajtów UTF-16LE za pomocą BOM?

niebieska strzała
źródło