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");
Related
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, ',');
}
I use a mySQL database and have to create some lists in Excel format (xlsx). The Excel sheets must be formated. For csv export I use phpExcel (I know, it is obsolete but still working).
Which add on do I need to create formated Excel sheets from my mySQL database. I use php to create the frontend.
Thanks,
Markus
This is just a copy of the function i use. It just launches the function when a specific $_GET isset. The function creates a xlsx file. If you want to export the file as .csv you can just change the file extension and edit text/xlsm to text/csv
$gg = $db->prepare("SELECT * FROM beta_mails ORDER BY created DESC");
$gg->execute();
$ggg = $gg->get_result();
$gg->store_result();
while ($row = $ggg->fetch_assoc()) {
$data[] = $row;
}
function getprelaunchCSV(){
global $data;
header('Content-Type: text/xlsx; charset=utf-8');
header('Content-Disposition: attachment; filename=data.xlsx');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('ID', 'EMAIL', 'OPRETTET'));
foreach ($data as $rowCSV){
fputcsv($output, [$rowCSV["id"], decrypt($rowCSV["email"]), $rowCSV["created"]]);
}
fclose($output);
die();
}
if (isset($_GET["getlist"]) && $_GET["getlist"] == "1") {
echo getprelaunchcsv();
header("Location:admin?success=1");
}
I'm using str_get_html http://simplehtmldom.sourceforge.net/ to export an HTML table to CSV. The user completes a form and the same table displays on screen. If they check a form box, I would like it to also generate a CSV file for download (in addition to displaying the table on screen).
Using ajax, I have the table being displayed in an empty div element.
<script type="text/javascript">
$(document).ready(function() {
var options = {target: '#output1'};
$('#completed').ajaxForm(options);});
</script>
It's almost working. The only problem is that it displays the CSV content in the div update, rather than generating a file for download. If I remove the on-screen display of the table and remove the ajax functionality, it generates the CSV file perfectly. Can someone help me with the code below so that it will generate a file for download?
include 'simple_html_dom.php';
$html = str_get_html($table);
header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename=sample.csv');
$fp = fopen("php://output", "w");
foreach($html->find('tr') as $element)
{
$td = array();
foreach( $element->find('th') as $row)
{
$td [] = $row->plaintext;
}
fputcsv($fp, $td);
$td = array();
foreach( $element->find('td') as $row)
{
$td [] = $row->plaintext;
}
fputcsv($fp, $td);
}
fclose($fp);
Instead of using "php://output", you need to use a path/filename. Right now, you are telling php to write to the output buffer mechanism.
For example:
$fp = fopen("path/to/filename.csv", "w");
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, ',', '"');
}
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";
}