Export CSV for Excel

前端 未结 5 1222
耶瑟儿~
耶瑟儿~ 2020-12-29 16:58

I\'m writing a CSV file in PHP using fputcsv($file, $data). It all works, however I can\'t just open it in Excel but have to import it and specify the encoding

相关标签:
5条回答
  • 2020-12-29 17:33

    This is how I make Excel readable CSV files from PHP :

    • Add BOM to fix UTF-8 in Excel
    • Set semi-colon (;) as delimeter
    • Set correct header ("Content-Type: text/csv; charset=utf-8")

    For exemple :

    $headers = array('Lastname :', 'Firstname :');
    $rows = array(
        array('Doe', 'John'),
        array('Schlüter', 'Rudy'),
        array('Alvarez', 'Niño')
    );
    
    // Create file and make it writable
    
    $file = fopen('file.csv', 'w');
    
    // Add BOM to fix UTF-8 in Excel
    
    fputs($file, $bom = (chr(0xEF) . chr(0xBB) . chr(0xBF)));
    
    // Headers
    // Set ";" as delimiter
    
    fputcsv($file, $headers, ";");
    
    // Rows
    // Set ";" as delimiter
    
    foreach ($rows as $row) {
    
        fputcsv($file, $row, ";");
    }
    
    // Close file
    
    fclose($file);
    
    // Send file to browser for download
    
    $dest_file = 'file.csv';
    $file_size = filesize($dest_file);
    
    header("Content-Type: text/csv; charset=utf-8");
    header("Content-disposition: attachment; filename=\"file.csv\"");
    header("Content-Length: " . $file_size);
    readfile($dest_file);
    

    Works with Excel 2013.

    0 讨论(0)
  • 2020-12-29 17:40

    I notice that you need to consider: Content-Type header BOM (Byte Order Mark) Actual character encoding in the file

    With BOM (works):

    $bom = pack("CCC", 0xEF, 0xBB, 0xBF);
    header('Content-Type: text/csv');
    header('Content-Length: '.(strlen($csv)+strlen($bom)));
    header('Content-Disposition: attachment;filename=my.csv');
    echo $bom;
    echo $csv;
    

    Without BOM (works but you need to replace “smart quotes” then run utf8_decode on each value or cell, and it converts some characters, for example FRĒ is converted to FRE')

    header('Content-Type: application/csv;charset=utf-8');
    header('Content-Length: '.strlen($csv));
    header('Content-Disposition: attachment;filename=my.csv');
    echo $csv;
    

    If the wrong combination of charset and BOM are used, it just comes out wrong when opening in MS Excel.

    Bonus fact: mb_strlen tells you the number of characters, strlen tells you the number of bytes. You do NOT want to use mb_strlen for calculating the Content-Length header.

    Bonus 2: replace microsoft "smart" characters (em dash, curly quotes, etc):

    $map = array(chr(145) => "'"
                ,chr(146) => "'"
                ,chr(147) => '"'
                ,chr(148) => '"'
                ,chr(149) => '-'
                ,chr(150) => '-'
                ,chr(151) => '-'
                ,chr(152) => '-'
                ,chr(152) => '-'
                ,chr(171) => '-'
                ,chr(187) => '-'
    );
    // faster that strtr
    return str_replace( array_keys($map), $map, $str );
    
    0 讨论(0)
  • 2020-12-29 17:42

    this is really a mess. You surely can use the sep=; or sep=, or sep=\t or whatever to make Excel aware of a separator used in your CSV. Just put this string at the beginning of your CSV contents. E.g.:

    fwrite($handle, "sep=,\n");
    
    fputcsv($handle,$yourcsvcontent);
    

    This works smoothly. BUT, it doesn't work in combination with a BOM which is required to make Excel aware of UTF-8 in case you need to support special characters or MB respectively.

    In the end to make it bullet-proof you need to read out users locale and set the Separator accordingly, as mentioned above. Put a BOM ("\xEF\xBB\xBF") at the begining of your CSV content, then write the CSV like e.g.: fputcsv($handle, $fields, $user_locale_seperator); where $user_locale_seperator is the separtator you retrieved by checking the user's locale. Not comfortable but it works...

    0 讨论(0)
  • 2020-12-29 17:48

    Despite the "C=comma" in CVS, Excel uses your locale native separator. So supposing fputcsv always uses a comma, it won't work, if your locale separator is for example a semicolon.

    What Google AdSense does, when you click "Export to Excel CSV", is that it uses Tab as a separator. And that works.

    To replicate that, set the third parameter (delimiter) of fputcsv to override the default comma. E.g. for Tab use: fputcsv($handle, $fields, "\t");

    Compare the format of the CSV that works for you against the one generated by fputcsv.

    Consider including example of both in your question. You might get better answers.

    0 讨论(0)
  • 2020-12-29 17:57

    You may have an encoding issue.

    Try this post:

    http://onwebdev.blogspot.com.es/2010/10/php-encoding-of-csv-file-for-excel.html

    0 讨论(0)
提交回复
热议问题