كيف يمكنني إخراج CSV UTF-8 في PHP أن Excel سوف يقرأ بشكل صحيح؟

StackOverflow https://stackoverflow.com/questions/4348802

سؤال

لقد حصلت على هذا الشيء البسيط للغاية الذي يخرج بعض الأشياء بتنسيق CSV ، ولكن يجب أن يكون UTF-8. أفتح هذا الملف في TextedIt أو Textmate أو Dreamweaver ويعرض أحرف UTF-8 بشكل صحيح ، ولكن إذا فتحته في Excel ، فإنه يقوم بهذا النوع من الأشياء السخيفة بدلاً من ذلك. هذا ما لدي على رأس وثيقي:

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

يبدو أن كل هذا له التأثير المطلوب باستثناء Excel (Mac ، 2008) لا يريد استيراده بشكل صحيح. لا توجد خيارات في Excel بالنسبة لي إلى "فتح UTF-8" أو أي شيء ، لذلك ... أنا أشعر بالضيق قليلاً.

لا يمكنني العثور على أي حلول واضحة لهذا في أي مكان ، على الرغم من أن الكثير من الأشخاص يعانون من نفس المشكلة. الشيء الأكثر رؤيته هو تضمين BOM ، لكن لا يمكنني معرفة كيفية القيام بذلك بالضبط. كما ترون أعلاه أنا فقط echoجي هذه البيانات ، أنا لا أكتب أي ملف. يمكنني القيام بذلك إذا كنت بحاجة إلى ذلك ، فأنا ليس فقط لأن هناك حاجة إليها في هذه المرحلة. أي مساعدة؟

تحديث: حاولت صدى BOM كما echo pack("CCC", 0xef, 0xbb, 0xbf); الذي سحبته للتو من موقع كان يحاول اكتشاف BOM. لكن Excel فقط يلحق تلك الأحرف الثلاثة بالخلية الأولى عندما تستورد ، ولا يزال يفسد الشخصيات الخاصة.

هل كانت مفيدة؟

المحلول

يقتبس مهندس دعم Microsoft,

Excel لنظام التشغيل Mac لا يدعم حاليًا UTF-8

تحديث ، 2017: هذا صحيح في جميع إصدارات Microsoft Excel لنظام التشغيل Mac من قبل مكتب 2016. إصدارات أحدث (من Office 365) تدعم الآن UTF-8.

من أجل إخراج محتوى UTF-8 الذي يتفوق على كل من Windows و OS X سيتمكن من القراءة بنجاح ، ستحتاج إلى القيام بأمرين:

  1. تأكد من تحويل نص UTF-8 الخاص بك إلى UTF-16LE

    mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
    
  2. تأكد من إضافة علامة ترتيب بايت UTF-16LE

    chr(255) . chr(254)
    

المشكلة التالية التي تظهر فقط مع Excel على OS X (ولكن ليس سيكون Windows) عند عرض ملف CSV مع قيم مفصولة بفاصلة ، لن يقوم Excel بتقديم الصفوف فقط باستخدام صف واحد وجميع النص مع الفواصل في الصف الأول.

طريقة تجنب ذلك هي استخدام علامات التبويب كقيمة منفصلة.

إستعملت هذه الوظيفة من تعليقات PHP (باستخدام علامات التبويب " t" بدلاً من الفواصل) وعملت بشكل مثالي على OS X و Windows Excel.

لاحظ أنه لإصلاح مشكلة مع عمود فارغ كنهاية صف ، كان عليّ تغيير سطر الكود الذي يقول:

    $field_cnt = count($fields);

إلى

    $field_cnt = count($fields)-1;

كما تقول بعض التعليقات الأخرى على هذه الصفحة ، فإن تطبيقات جداول البيانات الأخرى مثل OpenOffice Calc و Apple الخاصة وجداول بيانات DOC من Google ليس لديها أي مشاكل مع ملفات UTF-8 مع فواصل.

نرى الجدول في هذا السؤال لما ينجح ولا يعمل مع ملفات Unicode CSV في Excel


كملاحظة جانبية ، قد أضيف ذلك إذا كنت تستخدم ملحن, ، يجب أن تلقي نظرة على الإضافة League\Csv لطلبك. League\Csv لديها واجهة برمجة تطبيقات لطيفة حقًا لبناء ملفات CSV.

ليستخدم League\Csv باستخدام هذه الطريقة لإنشاء ملفات CSV ، تحقق من هذا المثال

نصائح أخرى

لدي نفس المشكلة (أو ما شابه).

في حالتي ، إذا قمت بإضافة BOM إلى الإخراج ، فهي تعمل:

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

أعتقد أن هذا اختراق قبيح للغاية ، لكنه نجح بالنسبة لي ، على الأقل لنوافذ Excel 2007. لست متأكدًا من أنه سيعمل على Mac.

إليكم كيف فعلت ذلك (وهذا يطلب من المتصفح تنزيل ملف 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();

الشيء الوحيد الذي تم إصلاحه في UTF8 تشفير مشكلة في معاينة CSV عندما تضغط على شريط الفضاء على Mac .. ولكن ليس في Excel Mac 2008 ... لا تعرف لماذا

لقد تعاملت مع نفس المشكلة ، وتوصلت إلى حلين.

  1. استخدم ال phpexcel صف دراسي كما اقترح bpeterson76.

    • باستخدام هذه الفئة ، يولد الملف الأكثر توافقًا على نطاق واسع ، تمكنت من إنشاء ملف من بيانات UTF-8 المشفرة التي فتحت بشكل جيد في Windows Excel 2008 و Excel 2007 و Google Docs.
    • أكبر مشكلة في استخدام phpexcel هي أنها بطيئة وتستخدم الكثير من الذاكرة ، وهي ليست مشكلة للملفات ذات الحجم المعقول ، ولكن إذا كان ملف Excel/CSV الخاص بك يحتوي على مئات أو آلاف الصفوف ، تصبح هذه المكتبة غير صالحة للاستعمال.
    • فيما يلي طريقة PHP التي ستأخذ بعض بيانات TSV وإخراج ملف excel إلى المتصفح ، لاحظ أنه يستخدم كاتب Excel5 ، مما يعني أن الملف يجب أن يكون متوافقًا مع الإصدارات القديمة من Excel ، لكن لم يعد لدي الوصول إلى أي ، لذلك لا يمكنني اختبارهم.

      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. نظرًا لقضايا الكفاءة مع Phpexcel ، اضطررت أيضًا إلى معرفة كيفية إنشاء ملف CSV أو TSV متوافق مع UTF-8 & Excel.

    • كان أفضل ما يمكن أن أتوصل إليه هو ملف متوافق مع Excel 2008 Mac ، و Excel 2007 PC ، ولكن ليس مستندات Google ، وهو أمر جيد بما يكفي لتطبيقي.
    • لقد وجدت الحل هنا, ، خاصة، هذا الجواب, ، ولكن يجب عليك أيضا قراءة إجابة مقبولة كما يفسر المشكلة.
    • فيما يلي رمز PHP الذي استخدمته ، لاحظ أنني أستخدم بيانات TSV (علامات التبويب كحمد بدلاً من الفواصل):

      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;
      

كنت أواجه نفس المشكلة وتم حلها على النحو التالي:

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

Excel لا يدعم UTF-8. يجب عليك تشفير نص UTF-8 الخاص بك إلى UCS-2LE.

mb_convert_encoding($output, 'UCS-2LE', 'UTF-8');

لمتابعة هذا:

يبدو أن المشكلة هي ببساطة مع Excel على Mac. ليس كيف أقوم بإنشاء الملفات ، لأنه حتى إنشاء CSVs من Excel يكسرهم. أنا حفظ كـ CSV ، وأعيد الاستيلاء ، ويتم إفساد جميع الشخصيات.

لذلك ... لا يبدو أن هناك إجابة صحيحة على هذا. شكرا لجميع الاقتراحات.

أود أن أقول أنه من كل ما قرأته ، من المحتمل أن يكون اقتراح Daniel Magliola حول BOM أفضل إجابة لبعض الكمبيوتر الآخر. لكنه لا يزال لا يحل مشكلتي.

في حالتي التالية ، تعمل بشكل جيد جدًا لجعل ملف CSV باستخدام chars UTF-8 معروض بشكل صحيح في Excel.

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

ال 0xEF 0xBB 0xBF سيخبر رأس BOM Excel بمعرفة الترميز الصحيح.

هذا يعمل بشكل جيد في Excel لكل من Windows وكذلك Mac OS.

إصلاح المشكلات في Excel التي لا تعرض الأحرف التي تحتوي على علم الحمل والرسائل السيريلية والرسالة اليونانية ورموز العملة.

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

يتضمن MUSST ملف CSV علامة ترتيب بايت.

أو كما هو مقترح وحلول فقط صدىه مع جسم HTTP

نظرًا لأن ترميز UTF8 لا يلعب بشكل جيد مع Excel. يمكنك تحويل البيانات إلى نوع ترميز آخر باستخدام iconv().

على سبيل المثال

iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value),

يضيف:

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

أو:

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

قبل كتابة أي محتوى إلى ملف CSV.

مثال:

<?php
$file = fopen( "file.csv", "w");
fprintf( $file, "\xEF\xBB\xBF");
fputcsv( $file, ["english", 122, "বাংলা"]);
fclose($file);

تحويل النص المشفر UTF-8 بالفعل باستخدام mb_convert_encoding لسنا بحاجته. فقط أضف ثلاثة أحرف أمام المحتوى الأصلي:

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

بالنسبة لي هذا حل مشكلة الأحرف الخاصة في ملفات CSV.

عندما قمت بالتحقيق ووجدت أن UTF-8 لا يعمل بشكل جيد على نظام التشغيل Mac و Windows ، لذا حاولت مع Windows-1252 ، فهو يدعم جيدًا على كل منهما ولكن يجب عليك تحديد نوع الترميز على Ubuntu. ها هو الكود الخاص بي$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
**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;
}

ماذا عن فقط الإخراج ل Excel نفسه؟ هذا فئة ممتازة يتيح لك ذلك إنشاء خادم ملفات XLS. أستخدمه بشكل متكرر للعملاء الذين لا يستطيعون "معرفة" CSV وحتى الآن لم يتلقوا شكوى. كما يسمح أيضًا ببعض التنسيقات الإضافية (التظليل ، والرائحة ، والحسابات ، وما إلى ذلك) التي لن تفعلها CSV على الإطلاق.

يمكنك تحويل سلسلة CSV الخاصة بك مع Iconv. فمثلا:

$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) );

يجب عليك استخدام الترميز "Windows-1252".

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

ربما عليك تحويل سلاسلك:

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

  return iconv($encoding, "Windows-1252", $string);
}

يمكنك إلحاق 3 بايت بالملف قبل التصدير ، فهو يعمل بالنسبة لي. قبل القيام بهذا النظام يعمل فقط في Windows و HP -UX ولكنه فشل في 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 );

لديك utf-8 bom (3 بايت ، Hex EF BB BF) في بداية الملف. وإلا فإن Excel سوف يفسر البيانات وفقًا لترميز موقعك الافتراضي (مثل CP1252) بدلاً من UTF-8

توليد ملف CSV لـ Excel ، وكيفية الحصول على سطر جديد داخل القيمة

أنا على جهاز Mac ، في حالتي ، كان علي فقط تحديد الفاصل "sep=;\n" وترميز الملف في UTF-16LE مثل هذا:

$data = "sep=;\n" .mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');

بالنسبة لي لا شيء من الحل أعلاه يعمل. فيما يلي ما فعلته لحل المشكلة: تعديل القيمة باستخدام هذه الوظيفة في رمز PHP:

$value = utf8_encode($value);

قيم الإخراج هذا بشكل صحيح في ورقة Excel.

واجهت نفس المشكلة عندما كان لدي روتين Excel VBA الذي تم استيراده. نظرًا لأن CSV عبارة عن تنسيق نصي عادي ، فقد كنت أعمل حول هذا عن طريق فتح البيانات برمجيًا في محرر ملفات بسيط مثل WordPad ، وأعيد توفيره كنص أحادي الصفر ، أو نسخه إلى الحافظة من هناك ولصقه للتفوق. إذا لم يكن Excel تحليل CSV تلقائيًا في الخلايا ، فسيتم علاج ذلك بسهولة باستخدام ميزة "النص إلى الأعمدة" المضمنة.

هل ما زالت المشكلة تحدث عند حفظها كملف .txt وفتحها في Excel مع فاصلة كمحدد؟

قد لا تكون المشكلة هي الترميز على الإطلاق ، فقد تكون الملفات ليست CSV مثالية وفقًا لمعايير Excel.

هذا المنشور قديم جدًا ، لكن بعد ساعات من المحاولة ، أريد أن أشارك الحل ... ربما يساعد شخص ما في التعامل مع Excel و Mac و CSV وتهرب من هذا التهديد. أقوم بإنشاء CSV ديناميكيًا كإخراج من قاعدة بيانات مع مراعاة مستخدمي Excel. (UTF-8 مع BOM)

لقد جربت الكثير من Iconv ولكن لم أستطع الحصول على umlauts الألمانية في Mac Excel 2004. حل واحد: phpexcel. إنه لأمر رائع ولكن لمشروعي كثيرًا. ما يناسبني هو إنشاء ملف CSV وتحويل ملف CSV هذا إلى XLS باستخدام هذا phpsnippet: CSV2XLS. النتيجة XLS تعمل مع Excel German Umlauts (ä ، Ö ، ü ، ...).

لقد جربت هذه الرؤوس وحصلت على Excel 2013 على جهاز كمبيوتر يعمل بنظام Windows 7 لاستيراد ملف CSV بأحرف خاصة بشكل صحيح. كانت علامة ترتيب البايت (BOM) هي المفتاح النهائي الذي جعلها تعمل.

    header('Content-Encoding: UTF-8');
    header('Content-type: text/csv; charset=UTF-8');
    header("Content-disposition: attachment; filename=filename.csv");
    header("Pragma: public");
    header("Expires: 0");
    echo "\xEF\xBB\xBF"; // UTF-8 BOM

وإلا يمكنك:

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

حل سهل لـ Mac Excel 2008: لقد ناضلت مع هذا SOO عدة مرات ، ولكن هنا كان إصلاحي السهل: افتح ملف .csv في TextWrangler والذي يجب أن يفتح UTF-8 chars بشكل صحيح. الآن في شريط الحالة السفلي ، قم بتغيير تنسيق الملف من "Unicode (UTF-8)" إلى "Western (ISO Latin 1)" وحفظ الملف. انتقل الآن إلى Mac Excel 2008 وحدد ملف> استيراد> حدد CSV> ابحث عن ملفك> في الملف الأصل حدد "Windows (ANSI)" و Voila. على الأقل هو الحال بالنسبة لي...

أنا أستخدم هذا وهو يعمل

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;

#output a utf-8 csv في php أن Excel سوف يقرأ بشكل صحيح.

//Use tab as field separator   
$sep  = "\t";  
$eol  = "\n";    
$fputcsv  =  count($headings) ? '"'. implode('"'.$sep.'"', $headings).'"'.$eol : '';
//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"));
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top