1

UPDATE: I have changed the code in order to insert a BOM, with no possitive result. Here's the updated piece of code:

$output = fopen($file, 'w');

        $utf8_output_with_bom = chr(239) . chr(187) . chr(191) . $output;

        fputcsv($output, array('NOMBRE','APELLIDO','TELEFONO', 'RESPUESTA', 'DIA', 'HORA'), "\t");


        if ($key1!="No definida"){            

            // fetch the data
            $rows1 = mysqli_query($con, "SELECT cm_name, cm_surname, cr_phone, cr_message, DATE_FORMAT(cr_time,'%d/%m/%Y'), DATE_FORMAT(cr_time,'%H:%i') FROM ws_campreplies JOIN ws_campmsg WHERE cr_phone=cm_phone AND cr_fk_us_id='$id' AND cr_message='$key1' AND cm_fk_ca_id='$ca_id'");
            // loop over the rows, outputting them
            while ($row1 = mysqli_fetch_assoc($rows1)) {     
                fputcsv($output, $row1, "\t");        
            }
        }

I have a utf8_general_ci database, with this example of records on the two involved tables (all utf8_general_ci):

Table ws_campmsg:

ws_campmsg

Table ws_campreplies:

ws_campreplies

The only thing I need is to export this on Excel, and this is almost done. This PHP file creates a SQL and exports a correct XLS file:

$con = mysqli_connect(DB_SERVER,DB_USER,DB_PASS,DB_NAME);    
mysqli_set_charset($con, 'utf8');

[....]
        $ca_id = $_POST['ca_id'];            
        $key1 = $_POST['key1'];

        $file='../uploads/TemporalCsv_'.time().'.xls';

        header("Content-Type: application/xls");    
        header("Content-Disposition: attachment; filename=$file");  
        header("Pragma: no-cache"); 
        header("Expires: 0");


        $output = fopen($file, 'w');        


        fputcsv($output, array('NOMBRE','APELLIDO','TELEFONO', 'RESPUESTA', 'DIA', 'HORA'), "\t");


        if ($key1!="No definida"){            

            // fetch the data
            $rows1 = mysqli_query($con, "SELECT cm_name, cm_surname, cr_phone, cr_message, DATE_FORMAT(cr_time,'%d/%m/%Y'), DATE_FORMAT(cr_time,'%H:%i') FROM ws_campreplies JOIN ws_campmsg WHERE cr_phone=cm_phone AND cr_fk_us_id='$id' AND cr_message='$key1' AND cm_fk_ca_id='$ca_id'");
            // loop over the rows, outputting them
            while ($row1 = mysqli_fetch_assoc($rows1)) {                
                fputcsv($output, $row1, "\t");        
            }
        }

        fclose($output);
        echo $file;

If I pass ca_id="438", and key1="CLAVE7", the exported file is right this one:

xls


As you see the only problem now is that it does not show properly accents like á or Á. As I have searched quite a bit about solving this, there are some tries I have made with no possitive result, like trying to export on text format dfirectly on browser (exports the same coding mistakes):

$file='../uploads/TemporalCsv_'.time().'.txt';
header("Content-Type: text/tab-separated-values");

Also tried changing headers (exports the same coding mistakes)

header("Content-Type:   application/vnd.ms-excel; charset=utf-8");
header("Content-type:   application/x-msexcel; charset=utf-8");
header("Content-Disposition: attachment; filename=ventas.xls");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);

On the last tries I found that maybe converting with iconv() would be effective, but with this modification an error emerges, as html_entity_decode() accepts strings, not arrays:

if ($key1!="No definida"){            

            // fetch the data
            $rows1 = mysqli_query($con, "SELECT cm_name, cm_surname, cr_phone, cr_message, DATE_FORMAT(cr_time,'%d/%m/%Y'), DATE_FORMAT(cr_time,'%H:%i') FROM ws_campreplies JOIN ws_campmsg WHERE cr_phone=cm_phone AND cr_fk_us_id='$id' AND cr_message='$key1' AND cm_fk_ca_id='$ca_id'");
            // loop over the rows, outputting them
            while ($row1 = mysqli_fetch_assoc($rows1)) {     
                iconv("UTF-8","WINDOWS-1255",html_entity_decode( $row1 ,ENT_COMPAT,'utf-8'));
                fputcsv($output, $row1, "\t");        
            }
        }

I hope I explained myself crearly. The use of PHPExcel is my last chance, if there is any posibility of correcting this issue without using PHPExcel, I would prefer it. Very grateful.

6
  • 1
    Don't open it directly in Excel ... instead create a new spreadsheet and then do data > import from file ... when you do that you can specify the character encoding of the data import to use utf-8 rather than Windows-1252 Commented Jun 25, 2015 at 10:18
  • Thank you. But is it not an spreadsheet what I am creating? I am confused about differences on opening in Excel and creating an sporeadsheet, is it not the same? The spreadsheet itself gets created under the $file directory, you mean taking that and doing a data > import from file...? Commented Jun 25, 2015 at 10:22
  • 1
    Basically once you've exported the .xls file don't double-click on it to open it in Excel. Instead open Excel and use the data > import from file tool to import the data into your spreadsheet. That import tool allows you to specify the character set that the data is in. If you double-click to open the .xls file, Excel assumes the character encoding will be Windows-1252 and scrambles your data. Commented Jun 25, 2015 at 10:27
  • I understand now. The problem is that this is an AJAX aplication, and whats is being echoed (the $file value, that means the final directory and file) gets automatically opened on a new tab, so it is not manually opened by the final user. Optimal solution would be to pass a final directory and file with that file itself previously encoded. Is there any way of making this trough PHP instead of trough Excel? Commented Jun 25, 2015 at 10:31
  • 1
    It's more an Excel problem than a PHP problem... I run into it every time I do a data dump from PHPMyAdmin. Your best bet is probably to throw it at Google Spreadsheet instead according to this answer : stackoverflow.com/questions/4221176/… Commented Jun 25, 2015 at 10:33

1 Answer 1

3

You have to add a BOM at the beginning of your output.

$utf8_output_with_bom = chr(239) . chr(187) . chr(191) . $utf8_output;

The BOM is not required in UTF8.

Example:

$output = fopen($file, 'w');
fwrite($output, chr(239) . chr(187) . chr(191)); // Write the BOM to the beginning of the file
fputcsv($output, <...>);
fclose($output);

Code to write the CSV:

$output = fopen($file, 'w');

fwrite($output, chr(239) . chr(187) . chr(191));

fputcsv($output, array('NOMBRE', 'APELLIDO', 'TELEFONO', 'RESPUESTA', 'DIA', 'HORA'), "\t");

if ($key1 != "No definida") {

    // fetch the data
    $rows1 = mysqli_query($con, "SELECT cm_name, cm_surname, cr_phone, cr_message, DATE_FORMAT(cr_time,'%d/%m/%Y'), DATE_FORMAT(cr_time,'%H:%i') FROM ws_campreplies JOIN ws_campmsg WHERE cr_phone=cm_phone AND cr_fk_us_id='$id' AND cr_message='$key1' AND cm_fk_ca_id='$ca_id'");
    // loop over the rows, outputting them
    while ($row1 = mysqli_fetch_assoc($rows1)) {
        fputcsv($output, $row1, "\t");
    }

}

fclose($output);
Sign up to request clarification or add additional context in comments.

3 Comments

So after creating the file with $output = fopen($file, 'w'); I must set the next line as $utf8_output_with_bom = chr(239) . chr(187) . chr(191) . $output; ?
I have updated the top of the cuestion with the edition I made on the code to add the BOM. Please check. I guess I do not know how to structurate this addition on the EXCEL file...
Could not continue with this untill today. Your help has make this work, thank you,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.