PHP encoding Umlauts in .csv for Excel - php

I'm working on a PHP script that creates a .csv file from some data.
Unfortunately, in Excel Umlauts are not displayed properly: Löl becomes L√∂l (this is just in Excel, in Apple's Numbers, Atom and Textedit everything looks fine).
I have tried hundreds of functions to try and get the encoding right (see the commented functions below). Could someone please tell me what I'm doing wrong?
$rows = json_decode('[["Löl"]]');
foreach($rows as $key_row => $row) {
foreach($row as $key_cell => $cell) {
// $rows[$key_row][$key_cell] = utf8_decode($cell);
// $rows[$key_row][$key_cell] = iconv('UTF-8', 'Windows-1252', $cell);
// $rows[$key_row][$key_cell] = mb_convert_encoding($cell, 'UTF-16LE', 'UTF-8');
// iconv('UTF-8', 'Windows-1252', $rows[$key_row][$key_cell]);
// mb_convert_encoding($rows[$key_row][$key_cell], 'UTF-16LE', 'UTF-8');
}
}
$temp = fopen('php://memory', 'w');
foreach($rows as $row) {
fputcsv($temp, $row, ';');
}
fseek($temp, 0);
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="test.csv";');
fpassthru($temp);

The following conversion to UTF-8 BOM worked:
foreach($rows as $key_row => $row) {
foreach($row as $key_cell => $cell) {
$rows[$key_row][$key_cell] = chr(239) . chr(187) . chr(191) . $cell;
}
}
Thanks for everybody who chimed in :)

Related

PHP encoding Umlauts and Spaces in .csv for Excel

I have some json data that I need to email to my users as a .csv file.
The following code works as expected for Hällowörld, however, once I put a space in there, Hällo wörld, the .csv file reads ÔªøH√§llo w√∂rld when opened in Excel (for Mac).
$temp = fopen('php://temp/maxmemory:10485760', 'w');
$rows = json_decode('[["Hällowörld"]]'); // -> Hällowörld
//$rows = json_decode('[["Hällo wörld"]]'); // -> ÔªøH√§llo w√∂rld
foreach($rows as $row) {
$row = array_map(function($cell) {
return chr(239).chr(187).chr(191).$cell;
}, $row);
fputcsv($temp, $row, ';');
}
rewind($temp);
$csv = stream_get_contents($temp);
fclose($temp);
$csv = base64_encode($csv);
// -> post $csv to my email provider's API
A few notes:
My code is in UTF-8
If I open the file with Apple's numbers or textedit, the content is displayed as expected.
If I don't do the mapping with chr(239).chr(187).chr(191).$cell, I get Hällowörld.
If instead, I use mb_convert_encoding($cell, 'UTF-16LE', 'UTF-8') or mb_convert_encoding($cell, 'Windows-1252', 'UTF-8'), as is often suggested, I get H‰llowˆrld.
The final base64_encode() is necessary, because my email provider needs the attachment to be base_64-encoded.
I found the solution! :) Replace the above foreach loop with the following:
array_unshift($rows, [chr(239).chr(187).chr(191)]);
foreach($rows as $row) {
fputcsv($f, $row, ',');
}

Automating CSV conversion from iso-8859-2 to utf-8

I have quite a few CSV files that are unfortunately encoded with iso-8859-2 (according to Brackets). I would like to iterate over these files with PHP and convert them.
I found https://csv.thephpleague.com/9.0/converter/charset/ but the way I can use the conversion function is uncertain to me.
Their example code
use League\Csv\CharsetConverter;
$csv = new SplFileObject('/path/to/french.csv', 'r');
$csv->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
$encoder = (new CharsetConverter())->inputEncoding('iso-8859-15');
$records = $encoder->convert($csv);
This is my code so far that is part of a form to upload one file and save the contents to the database for testing. It of course saves the text in the incorrect format.
$db = ConnectDB::getConnection('address_dtb');
$sql = " ... ";
$stmt = $db->prepare($sql);
$rowCount = 0;
$temp_name = $_FILES['adresscsv']['tmp_name'];
$file_handle = fopen($temp_name, 'r');
while (($items = fgetcsv($file_handle, 1000, ';')) !== FALSE) {
if($flag) { $flag = false; continue; }
$stmt->execute($items);
$rowCount++;
}
fclose($file_handle);
ConnectDB::closeConnection($db);
What is the correct way to use the PHP CSV library above to iterate over locally saved files in a for loop to automate the process?
I ended up using iconv as hinted.
$files = glob('address/*.csv');
foreach ($files as $csv) {
$file_data = file_get_contents($csv);
$utf8_file_data = iconv('Windows-1250', 'UTF-8', $file_data);
file_put_contents($csv, $utf8_file_data);
}
You do not have to use a library. There is a function in PHP that can do that iconv

php write hebrew / UTF-8 in csv

Hi I am trying to write a CSV with HEBREW text in it. It writes some symbol not an Hebrew text. Below is my PHP CODE.
<?php
$list = array (
array('שלטל', 'שלטל', 'שלטל', 'שלטל'),
array('123', '456', '789'),
array('"שלטל"', '"שלטל"')
);
$fp = fopen('file.csv', 'w');
//fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
?>
I checked in internet and added "fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ))" but it didnt work out. Can some one help me.
Below is the out put i am getting.
Just ran your code. The text is correctly encoded and generated csv is valid. Opening the CSV in a text editor that supports Hebrew text will show correctly. To open CSV containing Hebrew you need to follow instructions as suggested here
Update:
So turns out MS uses UTF-16 and not only that it uses UTF-16LE (little endian). For MS CSV to open correctly, you need UTF-16LE encoded text, tab delimited file.
$list = array (
array('שלטל', 'שלטל', 'שלטל', 'שלטל'),
array('123', '456', '789'),
array('"שלטל"', '"שלטל"')
);
$fp = fopen('file.csv', 'w');
//UTF-16LE BOM
fputs($fp, chr(0xFF) . chr(0xFE));
foreach ($list as $fields) {
$out = '';
foreach ($fields as $k => $v){
$fields[$k] = mb_convert_encoding($v, 'UTF-16LE', 'UTF-8');
}
// UTF-16LE tab
$out = implode(chr(0x09).chr(0x00), $fields);
// UTF-16LE new line
fputs($fp, $out.chr(0x0A).chr(0x00));
}
fclose($fp);
Above code works, not sure about its efficiency though.
I think I've encountered this before and sometimes some versions of excel just isn't showing proper utf8 characters/fonts. but the file itself have utf8 already.
Try opening your csv into Notepad++ and see if it is a utf8-bom and if its showing utf8 characters

Special charcter issue at Mysql to CSV in PHP script

I am trying to create a .csv file from a php script (that get the data from a database). My problem is that special characters are not displayed correctly.
$content[] = All field content at here.
echo "<pre>";
print_r($content);
$title = array("Category", "ProductName", "ProductSKU", "Price", "ProductURL", "ManufacturerSKU", "ManufacturerName","EAN","Description"
,"imageURL","StockStatus","DeliveryTime","Shippingcost");
$output = fopen('csv.csv', 'w+');
fputcsv($output, $title);
foreach ($content as $con) {
fputcsv($output, $con);
}
fclose($output);
echo "CSV created."
When i print $content, it is displaying properly special characters, But when i open csc.csv, It is not displaying properly.

How to make fputcsv "echo" the data

I need a way to make the fputscv function write data to the browser on-the-fly instead of creating a temporary file, saving data into that file and doing a echo file_get_contents().
Found this on the PHP docs website, first comment under the function reference:
function outputCSV($data) {
$outstream = fopen("php://output", 'w');
function __outputCSV(&$vals, $key, $filehandler) {
fputcsv($filehandler, $vals, ';', '"');
}
array_walk($data, '__outputCSV', $outstream);
fclose($outstream);
}
And a second option:
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($csv, array('blah','blah'));
rewind($csv);
// put it all in a variable
$output = stream_get_contents($csv);
Hope this helps!
BTW the PHP docs should always be your first stop when trying to figure things out. :-)
By a comment on the PHP site
<?php
$out = fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>
As the original asker wanted to "write to the browser on the fly", maybe is worth noting (as was my case and noone mentioned it) that if you want to force a file name and a dialog asking to download a file in the browser, you must set the proper headers before outputting anything with fputcsv:
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=myFile.csv');
Producing a CSV is actually not all that difficult (parsing a CSV is a little bit more involved).
Sample code for writing a 2D Array as CSV:
$array = [
[1,2,3],
[4,5,6],
[7,8,9]
];
// If this CSV is a HTTP response you will need to set the right content type
header("Content-Type: text/csv");
// If you need to force download or set a filename (you can also do this with
// the download attribute in HTML5 instead)
header('Content-Disposition: attachment; filename="example.csv"')
// Column heading row, if required.
echo "Column heading 1,Column heading 2,Column heading 3\n";
foreach ($array as $row) {
$row = array_map(function($cell) {
// Cells containing a quote, a comma or a new line will need to be
// contained in double quotes.
if (preg_match('/["\n,]/', $cell)) {
// double quotes within cells need to be escaped.
return '"' . preg_replace('/"/', '""', $cell) . '"';
}
return $cell;
}, $row);
echo implode(',', $row) . "\n";
}

Categories