Jak mogę wyprowadzić UVF-8 CSV w PHP, który Excel będzie poprawnie czytał?

191

Mam tę bardzo prostą rzecz, która po prostu wyświetla niektóre pliki w formacie CSV, ale musi to być UTF-8. Otwieram ten plik w TextEdit lub TextMate lub Dreamweaver i wyświetla on poprawnie znaki UTF-8, ale jeśli otworzę go w Excelu, robi to głupio. Oto, co mam na początku mojego dokumentu:

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

Wszystko to wydaje się mieć pożądany efekt, z wyjątkiem tego, że Excel (Mac, 2008) nie chce go poprawnie importować. W Excelu nie ma opcji „otwarcia jako UTF-8” ani czegoś takiego, więc… Trochę się denerwuję.

Nie mogę znaleźć nigdzie jasnych rozwiązań tego problemu, mimo że wiele osób ma ten sam problem. Najbardziej widzę dołączenie BOM, ale nie mogę dokładnie wymyślić, jak to zrobić. Jak widać powyżej, właśnie wprowadzam echote dane, nie piszę żadnych plików. Mogę to zrobić, jeśli zajdzie taka potrzeba, po prostu nie jestem, ponieważ w tym momencie nie wydaje się to potrzebne. Jakaś pomoc?

Aktualizacja: Próbowałem odtworzyć BOM, echo pack("CCC", 0xef, 0xbb, 0xbf);który właśnie ściągnąłem ze strony, która próbowała wykryć BOM. Ale program Excel po prostu dodaje te trzy znaki do pierwszej komórki podczas importowania i nadal miesza znaki specjalne.

Ben Saufley
źródło
2
Excel nie oferuje opcji dostosowania zestawu znaków pliku przychodzącego? Czy jesteś tego w 100% pewien? Nie mam pod ręką kopii, więc nie mogę wypróbować, ale wyobrażam sobie, że gdzieś musi być rozwijane pudełko.
Pekka,
To jest Excel na Macu - wydaje się bardziej ograniczony niż Excel na PC. W oknie dialogowym Otwórz nie ma żadnych list rozwijanych, poza którymi typami plików można otworzyć. Wszędzie szukałem. Jeśli tam jest, jest niejasny. Powiedziałbym 98% pewności.
Ben Saufley,
Biuro Microsoft czy openoffice?
ajreal
Microsoft jest lepszy pod tym względem, nie ma (jak znalazłem) sposobu, aby OpenOffice wykrył zestaw znaków, nawet BOM. Cholera.
Ciantic
BOM nie ma również wpływu na Microsoft Excel 2008 dla komputerów Mac.
Ben Saufley,

Odpowiedzi:

134

Aby zacytować inżyniera wsparcia Microsoft ,

Program Excel dla komputerów Mac nie obsługuje obecnie UTF-8

Aktualizacja, 2017 : Dotyczy to wszystkich wersji programu Microsoft Excel dla komputerów Mac przed pakietem Office 2016 . Nowsze wersje (z Office 365) obsługują teraz UTF-8.

Aby wyświetlić zawartość UTF-8, którą Excel zarówno w systemie Windows, jak i OS X będzie w stanie z powodzeniem odczytać, musisz wykonać dwie czynności:

  1. Upewnij się, że konwertujesz tekst UTF-8 CSV na UTF-16LE

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
  2. Upewnij się, że dodałeś znak kolejności bajtów UTF-16LE na początku pliku

    chr(255) . chr(254)

Kolejny problem, który pojawia się tylko w programie Excel w systemie OS X (ale nie w systemie Windows), pojawi się podczas przeglądania pliku CSV z wartościami oddzielonymi przecinkami, program Excel wyświetli wiersze tylko z jednym wierszem i całym tekstem wraz z przecinkami w pierwszym wierszu.

Aby tego uniknąć, należy użyć tabulatorów jako oddzielnej wartości.

Użyłem tej funkcji z komentarzy PHP (używając tabulatorów „\ t” zamiast przecinków) i działała idealnie na OS X i Windows Excel.

Zauważ, że aby rozwiązać problem z pustą kolumną na końcu wiersza, musiałem zmienić wiersz kodu, który mówi:

    $field_cnt = count($fields);

do

    $field_cnt = count($fields)-1;

Jak mówią niektóre inne komentarze na tej stronie, inne aplikacje arkuszy kalkulacyjnych, takie jak OpenOffice Calc, własne numery Apple i arkusze kalkulacyjne Google Doc, nie mają problemów z plikami UTF-8 z przecinkami.

Zobacz tabelę w tym pytaniu, aby dowiedzieć się, co działa i nie działa w przypadku plików CSV Unicode w programie Excel


Na marginesie, mogę dodać, że jeśli używasz Composer , powinieneś spojrzeć na dodawanie League\Csvdo swoich wymagań. League\Csvma naprawdę niezły interfejs API do tworzenia plików CSV .

Aby skorzystać League\Csvz tej metody tworzenia plików CSV, sprawdź ten przykład

Tim Groeneveld
źródło
1
Nazywaj mnie głupcem, ale nie mogę sprawić, żeby to zadziałało. Przekształciłem moje dane za pomocą funkcji mb_convert_encoding i wypisałem BOM poprzedzający zawartość pliku, ale po otwarciu pliku w Excelu dostaję tylko jeden wiersz chińskich znaków. Nadal używam przecinków zamiast kart, ale prawdopodobnie nie powinno to powodować tego, co widzę.
John Rix,
@JohnRix to dziwne. Ten kod dosłownie rozwiązał każdy problem, jaki kiedykolwiek miałem z eksportowanymi plikami CSV - z wyjątkiem importerów, którzy akceptują tylko przecinki. Czy możesz przesłać mi pastebin używanego kodu wraz z tablicą, którą zamieniasz w CSV i kopią wyeksportowanego pliku?
Tim Groeneveld,
2
To rozwiązanie rozwiązało również problem UTF8 dla mnie na komputerach Mac i Windows. Odkryłem również, że dodanie wiersza z plikiem CSV sep=;lub sep=,do niego mówi Excelowi, w jaki sposób CSV jest rozdzielany i kolumny zostaną ponownie utworzone poprawnie.
Luc Wollants
5
Przekonałem się, że wszystko zaczęło się zniekształcać, gdy zacząłem ciąg jako BOM, a następnie w innym wierszu dodał "sep=,\n", a następnie w innym wierszu dodał dane. Wszystko szło dobrze, gdybym to wszystko zrobił w jednym wierszu ( $csv = chr(255) . chr(254) /* BOM */ . "sep=,\n" . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');). Teraz wszystko wygląda świetnie na komputerze Mac. Nie mam systemu Windows do testowania.
tremby
2
Jedyne, co w pełni działało dla mnie. Niespójność Microsoftu nigdy nie przestaje mnie zadziwiać. Zapisywanie normalnego pliku csv używa „,” jako separatora, ale jeśli istnieje BOM, to z jakiegoś powodu zapisuje się za pomocą „\ t”. C w .csv oznacza „COMMA” do cholery. To naprawdę nie jest trudne.
Phil,
288

Mam ten sam (lub podobny) problem.

W moim przypadku, jeśli dodam BOM do wyniku, działa:

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

Uważam, że jest to dość brzydki hack, ale zadziałało to dla mnie, przynajmniej dla Windows 2007 Excel. Nie jestem pewien, czy to zadziała na komputerze Mac.

Daniel Magliola
źródło
10
Brzydki, ale bardzo pomocny. Dziękuję Ci.
abelito
7
Niestety jestem pewien, że nie działa to dobrze w systemie OS X. Myślę, że może faktycznie wyświetlać BOM podczas importowania (ostrzeżenie: mgliste wspomnienia.)
davidtbernal
2
To jest poprawne. Przynajmniej próbowałem przygotowania z BOM, tak jak w powyższym przykładzie, ale tak naprawdę na początku pokazywało kilka funky znaków i ciągle wyświetlało nieprawidłowe znaki specjalne (testowane w programie Excel 2011). Wydawało mi się, że działa najlepiej dla mnie we wszystkich ustawieniach: stackoverflow.com/a/1648671/1005334 (przy użyciu PHP).
kasimir
4
Wciąż otrzymuję powiadomienia o tym pytaniu, ponieważ podobno natknęło się na niego wiele innych osób. Chciałbym móc oznaczyć to jako poprawne, ponieważ zostało to bardzo wysoko ocenione. Niestety w końcu wypróbowałem to rozwiązanie (dawno temu porzuciłem ten projekt) i nie działa ono dla mnie w programie Excel 2008 dla komputerów Mac. Cieszę się, że to działa dla ciebie. Poparłem rozwiązanie. Ale to nie rozwiązuje problemu z programem Excel dla komputerów Mac 2008. Jeśli ktoś ma szczęście na Macu, zdecydowanie daj mi znać (i najwyraźniej wszystkim ).
Ben Saufley
Działa pięknie, wysyłając plik CSV do MS Excel Starter 2010. Dziękujemy bardzo!
Jamie Dexter,
32

Oto jak to zrobiłem (aby zachęcić przeglądarkę do pobrania pliku 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();

Jedyne, co rozwiązało problem z kodowaniem UTF8 w podglądzie CSV po naciśnięciu spacji na komputerze Mac .. ale nie w programie Excel Mac 2008 ... nie wiem dlaczego

Jazzer
źródło
1
Kod BOM linii UTF-8 oszczędza mój dzień dzięki eksportowaniu do formatu xls
Mladen Janjetovic
6
Szukałem sposobu na wyjście bezpośrednio do przeglądarki jako utf8, kiedy natknąłem się na ten post, oto moje rozwiązanie z kredytami na ten post dla BOM i nagłówka transferu binarnego. $outstream = fopen( "php://output", 'w' ); fputs( $outstream, "\xEF\xBB\xBF" ); foreach ( $export as $fields ) { fputcsv( $outstream, $fields ); } fclose( $outstream );
fyrye
Literówka - usuń podwójne )).
sitilge,
22

Właśnie poradziłem sobie z tym samym problemem i wpadłem na dwa rozwiązania.

  1. Użyj klasy PHPExcel, zgodnie z sugestią bpeterson76 .

    • Korzystając z tej klasy generuje najbardziej kompatybilny plik, byłem w stanie wygenerować plik z danych zakodowanych w UTF-8, które otworzyły się dobrze w Excel 2008 Mac, Excel 2007 Windows i Dokumentach Google.
    • Największy problem z korzystaniem z PHPExcel polega na tym, że jest powolny i zużywa dużo pamięci, co nie stanowi problemu w przypadku plików o rozsądnych rozmiarach, ale jeśli plik Excel / CSV ma setki lub tysiące wierszy, biblioteka ta stanie się bezużyteczna .
    • Oto metoda PHP, która pobierze niektóre dane TSV i wyśle ​​plik Excela do przeglądarki, pamiętaj, że używa programu Excel5 Writer, co oznacza, że ​​plik powinien być zgodny ze starszymi wersjami programu Excel, ale nie mam już dostępu do żadnego, więc nie mogę ich przetestować.

      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. Z powodu problemów z wydajnością w PHPExcel musiałem również wymyślić, jak wygenerować plik CSV lub TSV zgodny z UTF-8 i Excel.

    • Najlepsze, co mogłem wymyślić, to plik zgodny z programem Excel 2008 Mac i Excel 2007 PC, ale nie z Dokumentami Google, co jest wystarczająco dobre dla mojej aplikacji.
    • Znalazłem tutaj rozwiązanie , a konkretnie tę odpowiedź , ale powinieneś również przeczytać zaakceptowaną odpowiedź, ponieważ wyjaśnia ona problem.
    • Oto kod PHP, którego użyłem, zauważ, że używam danych tsv (tabele jako separatory zamiast przecinków):

      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;
Jasdeep Gosal
źródło
Mam do czynienia z tym samym problemem w Windows 7 Excel 2007 i wypróbowałem wszystkie sugestie, ale nie udało mi się :(
PHP Ferrari
Rozwiązanie UTF-16LE działało. Pamiętaj, że musisz poprawnie sformatować plik tsv i musi to być tsc, więc tabulator należy rozdzielić, a nie przecinkiem. Zobacz także post Marc tutaj: stackoverflow.com/a/1648671/1697370
Ellert van Koperen
17

Miałem ten sam problem i został on rozwiązany jak poniżej:

    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();
Reza Mamun
źródło
13

Excel nie obsługuje UTF-8. Musisz zakodować swój tekst UTF-8 w UCS-2LE.

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');
Leopold Gault
źródło
3
Lepiej użyj UTF-16LE, jak sugerowano powyżej, który obejmuje każdą istniejącą postać.
Ellert van Koperen,
Zauważyłem, że mb_convert_encoding działa dobrze i poprawnie wyświetla znaki diakrytyczne w eksportowanym pliku XLS. Mam domyślne konfiguracje mysql i apache + php ustawione do pracy z utf-8
Junior Mayhé
10

W moim przypadku bardzo fajnie jest zrobić plik CSV z znakami UTF-8 wyświetlanymi poprawnie w Excelu.

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

0xEF 0xBB 0xBFNagłówka BOM pozwoli Excel znać poprawne kodowanie.

Codemole
źródło
1
big up for you bro <3
Adrien G
fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));<- właśnie tego potrzebowałem. To działa jak urok.
Alex
8

Aby kontynuować:

Wygląda na to, że problem dotyczy po prostu Excela na Macu. Nie tak generuję pliki, ponieważ nawet generowanie CSV z Excela je psuje . Zapisuję jako CSV i ponownie importuję, a wszystkie postacie są popsute.

Więc… wydaje się, że nie ma na to poprawnej odpowiedzi. Dziękuję za wszystkie sugestie.

Powiedziałbym, że z tego, co przeczytałem, sugestia @Daniel Magliola dotycząca BOM byłaby prawdopodobnie najlepszą odpowiedzią na jakiś inny komputer. Ale nadal nie rozwiązuje mojego problemu.

Ben Saufley
źródło
Ponieważ obsługa UTF8 jest niespójna między komputerami Mac i Windows, najlepszym rozwiązaniem jest użycie zupełnie innego kodowania. Odkryłem, że CP1252 ogólnie dobrze gra z rzeczami Microsoft. en.wikipedia.org/wiki/Windows-1252
s29
1
Ben, poprawna odpowiedź na to pytanie :) Zobacz moje!
Tim Groeneveld
7

Działa to doskonale w programie Excel zarówno w systemie Windows, jak i Mac OS.

Napraw problemy w programie Excel, które nie wyświetlają znaków zawierających znaki diakrytyczne, litery cyrylicy, litery greckie i symbole walut.

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;
}
Murali Krishna
źródło
to rozwiązanie pozwoliło mi sprawić, by eksport działał także w Arkuszach Google (niektóre inne zawiodły)
Cafn
6

Musst pliku CSV zawiera znak kolejności bajtów.

Lub zgodnie z sugestią i obejściem wystarczy powtórzyć to w treści HTTP

Cybot
źródło
5

Dodaj:

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

Lub:

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

Przed zapisaniem treści w pliku CSV.

Przykład:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);
Rejaul
źródło
4

Ponieważ kodowanie UTF8 nie działa dobrze w programie Excel. Możesz przekonwertować dane na inny typ kodowania za pomocą iconv().

na przykład

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),
Abrar A. Shareef
źródło
To było jedyne rozwiązanie, które działało dla mnie w programie Excel Mac 2011
Christer Fernstrom,
3

Konwersja już zakodowanego tekstu utf-8 za pomocą mb_convert_encodingnie jest potrzebna. Po prostu dodaj trzy znaki przed oryginalną treścią:

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

Dla mnie rozwiązało to problem znaków specjalnych w plikach csv.

Rvanlaak
źródło
Nie do wiary; Wypróbowałem co najmniej 10 innych rozwiązań i jedynym rozwiązaniem dla mnie wydaje się być to, w połączeniu z BOM UTF-8 przez fputs.
kaarto
2

Jak zbadałem i stwierdziłem, że UTF-8 nie działa dobrze na MAC i Windows, więc próbowałem z Windows-1252, obsługuje dobrze na obu z nich, ale musisz wybrać rodzaj kodowania na Ubuntu. Oto mój kod$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
Ho Ha
źródło
2
**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;
}
Sagar72427
źródło
2
Zasadniczo odpowiedzi są o wiele bardziej pomocne, jeśli zawierają wyjaśnienie, do czego służy kod i dlaczego rozwiązuje problem bez przedstawiania innych.
Tim Diekmann
1

Co powiesz na wyjście w samym Excelu? Jest to doskonała klasa, która pozwala generować pliki XLS po stronie serwera. Używam go często dla klientów, którzy nie mogą „rozgryźć” plików CSV i do tej pory nigdy nie mieli skargi. Pozwala także na dodatkowe formatowanie (cieniowanie, wysokości wierszy, obliczenia itp.), Którego csv nigdy nie zrobi.

bpeterson76
źródło
Pamiętaj, że phpexcel ma problemy z dużą ilością danych.
Ellert van Koperen,
1

możesz przekonwertować ciąg CSV za pomocą iconv . na przykład:

$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) );
foued611
źródło
Świetne przykładowe teksty;)
ngeek
1

Musisz użyć kodowania „Windows-1252”.

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

Może musisz przekonwertować swoje ciągi:

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

  return iconv($encoding, "Windows-1252", $string);
}
roNn23
źródło
1

Możesz dodać 3 bajty do pliku przed eksportem, to działa dla mnie. Przed wykonaniem tego systemu działa tylko w systemie Windows i HP -UX, ale nie działa w systemie 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 );

Posiadaj BOM UTF-8 (3 bajty, hex EF BB BF) na początku pliku. W przeciwnym razie program Excel zinterpretuje dane zgodnie z domyślnym kodowaniem ustawień regionalnych (np. CP1252) zamiast utf-8

Generowanie pliku CSV dla programu Excel, jak umieścić nowy wiersz w wartości

Cherry Yap
źródło
1

Jestem na komputerze Mac, w moim przypadku po prostu musiałem określić separator "sep=;\n"i zakodować plik w UTF-16LE w następujący sposób:

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
Sebastien Horin
źródło
1

Dla mnie żadne z powyższych rozwiązań nie zadziałało. Poniżej jest to, co zrobiłem, aby rozwiązać problem: zmodyfikuj wartość za pomocą tej funkcji w kodzie PHP:

$value = utf8_encode($value);

Te wartości wyjściowe są prawidłowe w arkuszu programu Excel.

Barani r
źródło
0

Miałem ten sam problem, gdy miałem procedurę Excel VBA, która importowała dane. Ponieważ CSV jest zwykłym formatem tekstowym, pracowałem nad tym, programowo otwierając dane w prostym edytorze plików, takim jak Wordpad, i ponownie zapisując je jako tekst Unicode lub kopiując je do schowka i wklejając je do programu Excel. Jeśli program Excel nie analizuje automatycznie pliku CSV w komórkach, można to łatwo naprawić za pomocą wbudowanej funkcji „Tekst do kolumn”.

Alain
źródło
Próbowałem tego! Ale jest już zakodowany jako tekst Unicode… zapisanie go jako tekstu Unicode niczego nie zmienia. Jak zapisać go jako zwykły tekst bez niewłaściwej interpretacji wszystkich znaków specjalnych?
Ben Saufley,
Myślę, że „zapisując go jako tekst Unicode”, Alain może oznaczać „UTF-16LE”. Windows często (niestety) używa „Unicode” do niepoprawnego odniesienia do UTF-16LE lub UTF-16LE z wiodącym zestawieniem komponentów. Plik Notatnika -> Zapisz okno używa w ten sposób „Unicode”.
Thanatos,
0

Czy problem nadal występuje, gdy zapiszesz go jako plik .txt i otworzą go w programie Excel z przecinkiem jako separatorem?

Problemem może nie być w ogóle kodowanie, może to być po prostu to, że plik nie jest doskonałym CSV zgodnie ze standardami programu Excel.

Alain
źródło
O ile mi wiadomo, formatowanie CSV jest w porządku. Mogę stworzyć „idealny” CSV w TextEdit, bez problemu, a nawet zmienić nazwę txt na csv, więc nie brakuje niczego tajemnego - CSV to tylko pliki tekstowe. Ponadto formatowanie jest w Excelu idealne, tylko łamią się znaki specjalne. Ale na wszelki wypadek wypróbowałem twoją sugestię i to niestety powoduje te same problemy.
Ben Saufley,
Z działu „Myśleli WTF”: należy pamiętać, że według Microsoft poprawny separator pól zależy od ustawień regionalnych. Plik „oddzielony przecinkami” może więc wymagać oddzielenia pól średnikiem w niektórych lokalizacjach - i nic nie można zrobić oprócz sugerowania OpenOffice
djn
to dość szalone - niestety nie mam problemów z prawidłowym rozgraniczeniem pól. Mam problem z tymi postaciami specjalnymi.
Ben Saufley,
0

Ten post jest dość stary, ale po wielu godzinach próbuję udostępnić swoje rozwiązanie… może to pomaga komuś, kto ma do czynienia z Excelem, Maciem i CSV i potyka się o to zagrożenie. Generuję csv dynamicznie jako dane wyjściowe z bazy danych z myślą o użytkownikach programu Excel. (UTF-8 z BOM)

Próbowałem wielu ikonv, ale nie mogłem uzyskać niemieckich umlautów pracujących w Mac Excel 2004. Jedno rozwiązanie: PHPExcel. To świetnie, ale jak na mój projekt trochę za dużo. Dla mnie działa tworzenie pliku csv i konwersja tego pliku csv do formatu xls za pomocą tego PHPsnippet: csv2xls . wynik xls działa z najlepszymi niemieckimi umlautami (ä, ö, Ü, ...).

t Book
źródło
0

Właśnie wypróbowałem te nagłówki i dostałem Excel 2013 na komputer z systemem Windows 7, aby poprawnie zaimportować plik CSV ze znakami specjalnymi. Byte Order Mark (BOM) był ostatnim kluczem, który sprawił, że działał.

    nagłówek („Kodowanie treści: UTF-8”);
    nagłówek („Content-type: text / csv; charset = UTF-8”);
    nagłówek („Content-disposition: załącznik; nazwa_pliku = nazwa_pliku.csv”);
    nagłówek („Pragma: public”);
    nagłówek („Wygasa: 0”);
    echo "\ xEF \ xBB \ xBF"; // LM UTF-8

Brian
źródło
Tak, to prawda, będzie działać poprawnie w programie Excel dla systemu Windows, ale jak wyjaśniono w mojej odpowiedzi, nie będzie działać w programie Excel dla systemu OS X.
Tim Groeneveld
0

W przeciwnym razie możesz:

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);
użytkownik3519396
źródło
0

ŁATWE rozwiązanie dla komputerów Mac Excel 2008: wiele razy miałem z tym problem, ale oto moja łatwa poprawka: otwórz plik .csv w Textwrangler, który powinien poprawnie otwierać znaki UTF-8. Teraz na dolnym pasku stanu zmień format pliku z „Unicode (UTF-8)” na „Western (ISO Latin 1)” i zapisz plik. Teraz przejdź do komputera Mac Excel 2008 i wybierz Plik> Importuj> Wybierz csv> Znajdź swój plik> w pliku źródłowym wybierz „Windows (ANSI)” i voila, znaki UTF-8 są wyświetlane poprawnie. Przynajmniej robi to dla mnie ...

Poul
źródło
0

Używam tego i działa

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;
BoRnbeBaD
źródło
0

#output UTF-8 CSV w PHP, który Excel będzie czytał poprawnie.

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
Murali Krishna
źródło
Wystarczy jedna odpowiedź na osobę. W przyszłości pamiętaj, że możesz dodać informacje do swojej odpowiedzi w dowolnym momencie, nie musisz tworzyć 2
RiggsFolly
-1
//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"));
b3wii
źródło
To pytanie nie pyta, jak przekonwertować, ale pyta, jak wydrukować. Odpowiednia część tego wkładu, uzyskana w UTF-16, została już wniesiona w Wybranej odpowiedzi .
Ben Saufley,
@BenSaufley Cóż, ale rozwiązuje problem pytania za pomocą 2 prostych linii kodu
b3wii
Pytanie zostało już rozwiązane i dokładniej wyjaśnione.
Ben Saufley,