PHP encoding Umlauts and Spaces in .csv for Excel - php

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, ',');
}

Related

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

Export HTML table to CSV file

I am making a script which gets a table from your mail and puts it into a CSV file.
This is the code I use to transfer my html table to CSV
$html = str_get_html($outputstr);
// For Excel
header('Content-type: application/ms-excel');
// Download File
header('Content-Disposition: attachment; filename=sample.csv');
$fp = fopen("php://output", "w");
// Take out empty lines
foreach($html->find('tr') as $element) {
$td = array();
foreach( $element->find('th') as $row) {
$td [] = $row->plaintext;
}
foreach( $element->find('td') as $row) {
$td [] = $row->plaintext;
}
fputcsv($fp, $td);
}
fclose($fp);
The only problem that I'm getting is that when I am opening the CSV file, some of the empty columns have a strange character:
I cannot read through with my PHP script to export it to a database
fgetcsv($handle, 1000, "\t");
How can I fix this problem?
Do I fix this by modifying the code on the part where I create the CSV file or where I read the CSV file when I'm transferring it to a MySQL database?
When I use an online html to CSV converter it works fine and I am not facing this issue then.
If there is any code needed then I'd love to share it.
Any help would be appreciated.
Have you tried setting your charset to UTF-8? Additionally, you're not setting this up as a CSV with your header, instead it is an Excel file.
header("content-type:application/csv;charset=UTF-8");

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.

SimpleXML to CSV with missing tags

So I have an XML file that looks similar to this:
<container>
<example1>some text</example1>
<example2>some text</example2>
<example3>some text</example3>
<example4>some text</example4>
</container>
<container>
<example1>some text</example1>
<example2>some text</example2>
<example4>some text</example4>
</container>
Basically, if example3 doesn't contain any information, the XML author decided to leave it out completely. The trouble is, when I am using my script to convert to CSV, this particular XML file doesn't convert to CSV properly due to the text in the second example4 being displayed under the header of example3 in the CSV file.
This is the PHP script I have to normally works with other XML files.
$file='input.xml';
if (file_exists($file)) {
$xml = simplexml_load_file($file);
$f = fopen('output.csv', 'w');
// array to hold the field names
$headers = array();
// loop through the first set of fields to get names
foreach ($xml->container->children() as $field) {
// put the field name into array
$headers[] = $field->getName();
}
// print headers to CSV
fputcsv($f, $headers, ',', '"');
foreach ($xml->container as $information) {
fputcsv($f, get_object_vars($information), ',', '"');
}
fclose($f);
}
I can't figure out how to predefine the headers that I need and insert the correct information in the correct columns in the CSV.
Any pointers much appreciated.
thanks
mike
If your first entry always present all fields, then its enougth to iterate over the header fields for each line and look if the current line has all entrys.
foreach ($xml->container as $information) {
$vars = get_object_vars($information);
$line = array();
foreach($headers as $field) {
$line[] = isset($vars[$field]) ? $vars[$field] : '';
}
fputcsv($f, $line, ',', '"');
}

Generate pipe delimited file through php

My code generates a txt file using PHP's fputcsv function.
For the delimiter, I am trying to use '|'
$query = mysql_query("SELECT email, emailSource FROM session WHERE is_complete='1' ORDER by sessionid ASC")
$filename= 'here.txt';
$fp = fopen( $filename,'w');
fputcsv($fp, array('Email address', 'Email Source'));
if(mysql_numrows($query) > 0) {
while ($row = mysql_fetch_array($query, MYSQL_ASSOC)) {
fputcsv($fp, array_values($row));
}
}
fclose($fp);
$contents = file_get_contents($filename);
$contents = str_replace(",", "|", $contents);
file_put_contents($filename, $contents);
The result I get is all on one line instead of showing the values on a seperate line and I also have "" around the headers.
"Email address"|"Email Source"|blah#blah.com|hi|
instead of this:
Email address|Email Source|
blah#blah.com|hi|
Please can someone tell me what I am doing wrong. Is it because I am using fputcsv and saving to a txt file?
Get rid of the str_replace / file_get_contents/ file_put_contents block. Instead of fputcsv($fp, array('...')), use fputcsv($fp, array('...'), '|');

Categories