i'd like to make an export into CSV format, but the mutualised host i use has deactivate the FILE functions in mysql.
I did a simple SELECT and then a fopen and fwrite with PHP.
The problem is that in fields there is carriage returns or double quotes.
How to keep them and build a correct csv file?
Thanks a lot.
To build a best CSV. you can do following way.
$filename ='data.csv';
$csv_terminated = "\n";
$csv_separator = ",";
$csv_enclosed = '"';
$csv_escaped = "\\";
$results = array('1','2','3');// value
$schema_insert = '';
$header = array('a','b','c');// header
for ($i = 0; $i< count($header); $i++)
{
$l = $csv_enclosed . str_replace($csv_enclosed, $csv_escaped . $csv_enclosed,
stripslashes($header[$i])) . $csv_enclosed;
$schema_insert .= $l;
$schema_insert .= $csv_separator;
} // end for
$out = trim(substr($schema_insert, 0, -1));
$out .= $csv_terminated;
// Format the data
for($i=0;$i<count($results);$i++)
{
$row = $results[$i];
$schema_insert = '';
for ($j = 0; $j < count($header); $j++)
{
if ($row[$j] == '0' || $row[$j] != '')
{
if ($csv_enclosed == '')
{
$schema_insert .= $row[$j];
} else
{
$schema_insert .= $csv_enclosed .
str_replace($csv_enclosed, $csv_escaped . $csv_enclosed, $row[$j]) . $csv_enclosed;
}
} else
{
$schema_insert .= 'NULL';
}
if ($j < count($header) - 1)
{
$schema_insert .= $csv_separator;
}
} // end for
$out .= $schema_insert;
$out .= $csv_terminated;
} // end while
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: " . strlen($out));
// Output to browser with appropriate mime type, you choose <img src="http://thetechnofreak.com/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley">
header("Content-type: text/x-csv");
//header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=$filename");
echo $out;
Notice that,
+ when you make enclosed for description which has html code , you should use double quote.
+ Empty value --> Change to Null text or Zero value
They will make your CSV better.
You can download file.csv by use header()
Output everything you want (base on csv format) after header function, for example:
$filename = "output";
header('Content-Type: text/csv');
header('Content-disposition: attachment;'.$filename.'=.csv');
$separate = ","; //or ;
$endline = "\r\n";
foreach($data as $key => $item)
{
echo $key.$separate.$value.$endline;
}
protected function getCsv( $fileName, array $data )
{
// alot of headers here, make force download work on IE8 over SSL
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="'.$fileName.'"');
header("Content-Transfer-Encoding: binary");
// Joe Green says:
// based on http://www.php.net/manual/en/function.fputcsv.php#100033
$outStream = fopen("php://output", "r+");
function __getCsv( &$vals, $key, $filehandler ) {
fputcsv( $filehandler, $vals, ',', '"');
}
array_walk( $data, '__getCsv', $outStream );
fclose($outStream);
}
fputcsv is your friend. Also, I had to refine this function to get it to this point. Some of those headers are required by IE to force the csv to open as a csv, particularly over SSL. I seem to recall it had something to do with IE8 not recognising the 'text/csv' content type in the first instance and some security features around SSL downloads in the second.
Related
I am trying to create a csv in php with products from magento but my header doesn't show up in the csv file, just the products.
If i put the fputcsv for the headings inside the foreach it display the header then one product then the header again and another product and so on...
##### Print product data ####################################################
$headings = ['category', 'manufacturer', 'productid', 'identifier', 'name', 'description', 'product_url', 'image_url', 'price','show_product', 'availability', 'delivery_cost'];
$fh = fopen('php://output', 'w');
ob_start();
fputcsv($fh, $headings);
foreach($ALL_PRODS as $productId) {
// If we've sent this one, skip the rest - this is to ensure that we do not get duplicate products
if (#$already_sent[$productId] == 1) continue;
$PRODUCT = array();
$PRODUCT = smfeed_get_product_details($productId);
if ($PRODUCT['show_product'] == 1 ) {
fputcsv($fh, $PRODUCT);
$string = ob_get_clean();
$filename = 'csv_' . date('Ymd') . '_' . date('His');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename.csv\";");
header("Content-Transfer-Encoding: binary");
$prod_count ++;
// Debuging
if (isset($_GET['debug'])) {
$cnt_prod ++;
if (#$_GET['stats'] == "off") {
}
else {
echo $cnt_prod . ".";
echo "\t" . number_format(microtime(true) - $time, 3) . "s \n";
$time = microtime(true);
echo "\t" . number_format(memory_get_usage()/1048576, 3) . "Mb\n";
}
}
// Limit displayed products
if ($limit > 0 && $prod_count >= $limit && !isset($_GET['pg'])) {
// Debuging
if (isset($_GET['debug'])) {
echo "\n" . $cnt_prod . "products displayed \n";
echo "\npage loaded in " . number_format(microtime(true) - $time_start, 3) . "s \n";
echo number_format(memory_get_usage()/1048576, 3) . "Mb\n";
}
exit;
}
}
$already_sent[$productId] = 1;
}
exit($string);
ob_start(); starts output buffering.
Buffer contains the header line.
After the first product output is done, output buffering is ended by ob_get_clean();
Since $string = ob_get_clean(); assignment is called in the loop, its content being rewritten by false value (since the buffering was ended before) therefore final exit($string); does not output anything.
There are many other issues in your code. For example, HTTP headers will be set over again and again for each item in the loop.
I am trying to write data from database to a downloadable excel sheet. The code is working in the sense that it downloads the file with the desired name. However if I open the Excel sheet the cells are empty and my data is not in the sheet.
Here is my code
require_once('include/connect_pdo.php');
$myschool = $_POST['country'];
$findschool = $conn->prepare("SELECT Query");
$findschool->execute();
$filename = "Name";
$file_ending = "xls";
//header info for browser
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= $filename.xls");
header("Pragma: no-cache");
header("Expires: 0");
/*******Start of Formatting for Excel*******/
//define separator (defines columns in excel & tabs in word)
$sep = "\t"; //tabbed character
//start of printing column names as names of MySQL fields
for ($i = 0; $i < mysql_num_fields($result); $i++) {
echo mysql_field_name($result,$i) . "\t";
}
print("\n");
//end of printing column names
//start while loop to get data
while($row = mysql_fetch_row($result))
{
$schema_insert = "";
for($j = 0; $j < mysql_num_fields($result); $j++)
{
if(!isset($row[$j]))
$schema_insert .= "NULL".$sep;
elseif ($row[$j] != "")
$schema_insert .= "$row[$j]".$sep;
else
$schema_insert .= "".$sep;
}
$schema_insert = str_replace($sep."$", "", $schema_insert);
$schema_insert = preg_replace("/\r\n|\n\r|\n|\r/", " ", $schema_insert);
$schema_insert .= "\t";
print(trim($schema_insert));
print "\n";
}
This sorted my problem.
Header('Content-Description: File Transfer');
Header('Content-Encoding: UTF-8');
Header('Content-type: text/csv; charset=UTF-8');
Header('Content-Disposition: attachment; filename=' . '$filename' . '.csv');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
$output = fopen("php://output", "w");
fputcsv($output, array('Number1', 'Number 2'));
$findschool = $conn->prepare("SELECT Query Here);
$findschool->execute();
while ($result = $findschool->fetch(PDO::FETCH_ASSOC)) {
fputcsv($output, $result);
}
fclose($output);
XLS is Microsoft's proprietary binary format. What you create with your PHP code is a CSV file. Try changing your file extension to .csv and Content-Type header to text/csv.
I have a php code that selects an query from a postgres db and creates a xls file and downloads the same. The code is as follows :
<?php
$xls_filename = 'filename.xls'; // Define Excel (.xls) file name
$Connect = pg_connect ("host=xxxx port=5432 dbname=xxxx user=xxx password=xxx");
$sql = 'SELECT * FROM "tablename"';
$result = pg_query($sql);
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename=$xls_filename");
header("Pragma: no-cache");
header("Expires: 0");
// Define separator (defines columns in excel & tabs in word)
$sep = "\t"; // tabbed character
// Start of printing column names as names of fields
for ($i = 0; $i<pg_num_fields($result); $i++) {
echo pg_field_name($result,$i) . "\t";
}
print("\n");
// End of printing column names
// Start while loop to get data
while($row = pg_fetch_row($result))
{
$schema_insert = "";
for($j=0; $j<pg_num_fields($result); $j++)
{
if(!isset($row[$j])) {
$schema_insert .= "".$sep;
}
elseif ($row[$j] != "") {
$schema_insert .= "$row[$j]".$sep;
}
else {
$schema_insert .= "".$sep;
}
}
$schema_insert = str_replace($sep."$", "", $schema_insert);
$schema_insert = preg_replace("/\r\n|\n\r|\n|\r/", " ", $schema_insert);
$schema_insert .= "\t";
print(trim($schema_insert));
print "\n";
}
}
?>
I want to zip this xls file which is created rather then just downloading it.
How do I create a xls file in the directory instead of downloading it.
The problem is your variable.when your file name has space you have to use quotes like below:
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename='$xls_filename'");
You can use below code that work fine
$fileNames = WWW_ROOT . 'uploads' . DS . 'export' . DS . 'DYNAMIC_FILE_NAME_'. $ANY_DYNAMIC_PART.'.xls';//Dynamic Path of the directory
if (file_exists($fileNames)) {
$file = $fileNames;
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment; filename=\"NEWFILENAME.xls\"");
header("Content-Transfer-Encoding: binary");
header("Pragma: no-cache");
header("Expires: 0");
readfile($fileNames);exit;
}
I have written the following class to export database results to a CSV file.
<?php
class Export {
public static function tocsv($results = array(), $fields = array()) {
$schema_insert = '"'.implode('","', $fields).'"';
$out .= $schema_insert."\n";
foreach($results as $row) {
$schema_insert = '';
$schema_insert .= '"'.$row->week_ending.'",';
$schema_insert .= '"'.$row->project.'",';
$schema_insert .= '"'.$row->employee.'",';
$schema_insert .= '"'.$row->plots.'",';
$schema_insert .= '"'.$row->categories.'"';
$out .= $schema_insert."\n";
}
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: " . strlen($out));
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=$filename");
echo $out;
exit;
}
}
?>
The output is:
"Week ending","Project name","Plot numbers","Categories","Employee"
"Friday 08 May 2015","Big Road","Tracey Smith","1A, 2A, 3A"," Water meter, 1st fix inc lagging"
However, when I open with Excel everything is in one column. Have I missed something?
Thanks.
Use a semicolon as your fieldterminator instead of a comma, it's an Excel thing really, not a php thing.
I can easily export data as excel file with a simple code but I get a problem when I need to call the export.php by j query code. Data is not downloaded as export.php file. The code is :
<?php
include '../../config.php';
function cleanData(&$str)
{
if($str == 't') $str = 'TRUE';
if($str == 'f') $str = 'FALSE';
if(preg_match("/^0/", $str) || preg_match("/^\+?\d{8,}$/", $str) || preg_match("/^\d{4}.\d{1,2}.\d{1,2}/", $str)) {
$str = "'$str";
}
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
$str = mb_convert_encoding($str, 'UTF-16LE', 'UTF-8');
}
$filename = "website_data_" . date('Ymd') . ".csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: text/csv<span>; charset=UTF-16LE</span>");
$out = fopen("php://output", 'w');
$flag = false;
$result = mysql_query("SELECT * FROM employee") or die('Query failed!');
while(false !== ($row = mysql_fetch_assoc($result))) {
if(!$flag) {
fputcsv($out, array_keys($row), ',', '"');
$flag = true;
}
array_walk($row, 'cleanData');
if($row['photo']!='')
{
$row['photo']="http://localhost/admin/employee_image/".$row['photo'];
}
fputcsv($out, array_values($row), ',', '"');
}
fclose($out);
exit;
Is there any way to call this file by jquery?
No you cannot do this by Javascript using jQuery or any other library, AJAX calls data in Javascript engine inside the browser.
But you can use HTML5 download attribute:
Download Excel
And give proper headers in PHP:
header("Content-Type: application/vnd.ms-excel; charset=utf-8");
header("Content-Disposition: attachment; filename=your_file.xls");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
EDIT:
Although the above will work, I take my words back as I found this:
http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
Made by https://stackoverflow.com/users/455556/john-culviner , ask him for help if you need
Cheers!