Cakephp CSV helper generating leading space - php

I'm creating a CSV file using CakePHP CSV helper.
I'm always getting one space at the beginning of the column. I have used trim, ltrim but nothing works.
I have also added ob_start and ob_end_clean but nothing works.
My CSV code is
<?php
class CsvHelper extends AppHelper {
var $delimiter = ',';
var $enclosure = '"';
var $filename = 'Export.csv';
var $line = array();
var $buffer;
function CsvHelper() {
$this->clear();
}
function clear() {
$this->line = array();
$this->buffer = fopen('php://temp/maxmemory:' . (5 * 1024 * 1024), 'r+');
}
function addField($value) {
$this->line[] = $value;
}
function endRow() {
$this->addRow($this->line);
$this->line = array();
}
function addRow($row) {
fputcsv($this->buffer, $row, $this->delimiter, $this->enclosure);
}
function renderHeaders() {
ob_start();
header('Content-Encoding: UTF-16LE');
header('Content-Type: text/csv; charset=UTF-8');
header("Content-type:application/vnd.ms-excel");
header('Content-Disposition: attachment; filename="' . $this->filename . '"');
header("Pragma: no-cache");
header("Expires: 0");
ob_end_clean();
}
function setFilename($filename) {
$this->filename = $filename;
if (strtolower(substr($this->filename, -4)) != '.csv') {
$this->filename .= '.csv';
}
}
function render($outputHeaders = true, $to_encoding = null, $from_encoding = "auto") {
if ($outputHeaders) {
if (is_string($outputHeaders)) {
$this->setFilename(trim($outputHeaders));
}
$this->renderHeaders();
}
rewind($this->buffer);
$output = stream_get_contents($this->buffer);
if ($to_encoding) {
$output = mb_convert_encoding($output, $to_encoding, $from_encoding);
}
return $this->output(trim($output));
}
}
?>
I'm calling this helper from this ctp file to download and generate report.
<?php
$line = $gen_reports[0]['Report'];
$arrayKeys = array_keys($line);
$this->CSV->addRow($arrayKeys);
echo $this->CSV->render("filename");die;
?>
and the result I'm getting always a leading space at the very first column:
How can I get rid of this space?

Not sure if only a copy-paste error but you have an extra space right before your CsvHelper opening php tag which could result in a space in the output buffer.

Related

Exported Excel store on local folder of project

I have code which download the excel file.
I want to save this file in folder.
if($array_count > 0)
{
$fileName = "export_data" . rand(1,100) . ".xls";
if ($error_array) {
function filterData(&$str) {
$str = preg_replace("/\t/", "\\t", $str);
$str = preg_replace("/\r?\n/", "\\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// headers for download
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Type: application/vnd.ms-excel");
$flag = false;
foreach($error_array as $row) {
if(!$flag) {
// display column names as first row
// echo implode("\t", array_keys($row)). "\r\n";;
$flag = true;
}
// filter data
//header_remove('require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php")');
array_walk($row, 'filterData');
echo implode("\t", array_values($row)). "\r\n"; ;
}
//exit;
}
}
Please some one help me to change my code to save file in folder.
Here I have made one sample for you with static array data. We can save the file in the folder.
You can make changes in this code as per your requirement.
<?php
$data_array = array (
array ('1','2'),
array ('2','2'),
array ('3','6'),
array ('4','2'),
array ('6','5')
);
$sep = "\t";
$xls = "col1".$sep."col2 \n";//Column headers
foreach ($data_array as $record){
$xls.= $record[0].$sep.$record[1]."\n"; //Append data to xls
}
$xls_handler = fopen ('xlsfile.xls','w');
fwrite ($xls_handler,$xls);
fclose ($xls_handler);
echo 'Data saved to xlsfile.xls';
?>

export mysql data to excel using php ajax call

i am doing an ajax call and called a php page which is extracting data from a mysql table and need to convert it to excel and need to store in server folder only.
Now the problem is while doing the ajax call, its going to that php page and returning to the main page without creating the excel file.
But when i tested the php page directly then its creating the excel file and downloading it. But why its not working via ajax call.
This is my ajax call from previous page --
$.ajax({
type: "POST",
url: "admin-advertiser-details-exports.php?selectedColumns="+selectedColumns+"&excelColumn="+excelColumn,
contentType:false,
processData:false,
success:function(data){
alert('Export done');
}
});
And this is my php page which is exporting to excel --
<?php
session_start();
include 'db.php';
if(!isset($_SESSION))
{
$uname=$_SESSION['uname'];
}
else if(empty($_SESSION['uname']))
{
header('Location: index.php',TRUE);
}
$UserName = $_SESSION['uname'];
$UserID = $_SESSION['uid'];
$UserType = $_SESSION['utype'];
$selectedColumns = $_GET['selectedColumns'];
$excelColumn = $_GET['excelColumn'];
$array = explode('\t',$excelColumn);
$sql = "select ".$selectedColumns." from advertisers_details ad join user_details ud on ad.adv_manager=ud.user_id order by ad.adv_id asc";
$setRec = mysqli_query($linkID1, $sql);
$columnHeader = '';
foreach ($array as $value) {
$value = '"' . $value . '"' . "\t";
$columnHeader .= $value;
}
$setData = '';
while ($rec = mysqli_fetch_row($setRec))
{
$rowData = '';
foreach ($rec as $value)
{
$value = '"' . $value . '"' . "\t";
$rowData .= $value;
}
$setData .= trim($rowData) . "\n";
}
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=advertiser_detail.xls");
header("Pragma: no-cache");
header("Expires: 0");
echo ucwords($columnHeader) . "\n" . $setData . "\n";
?>
If i am running this php page directly the i am getting the excel file, but via ajax call its not working.
Hope this example work best for you.
I have used window.open and set url of target file with parameter.
JS code used
/* Export Orders */
$(document).on('click','#btn_export_delivery_order',function(){
var first_input = $('#name_email_order_search').val();
var date_range = $('#reportrangeorder').val();
var order_status = $('#order_status').val();
window.open("ajax_responce.php?method_name=export_orders&shop="+ shop+"&first_input=" + first_input + "&date_range=" + date_range + "&order_status=" + order_status + "", '_blank');
});
Code used in ajax_response.php
public function export_orders(){
ob_start();
if (isset($_GET['shop']) && $_GET['shop'] != '') {
$export = array();
$export_data = array();
$shopinfo = $this->get_settings($_GET['shop']);
$store_client_id = $shopinfo['store_client_id'];
$date_format = $shopinfo['date_format_first'];
$options_arr = array("skip" => 0, "limit" => 99999);
$where = $this->where_to_clause_export_search($store_client_id, $_GET);
$fullfilment_status_array = array('Unfulfilled','Fullfill','Partially fullfill','Cancelled');
$export_result = $this->select_result(TABLE_ORDERS, '*', $where, $options_arr);
foreach($export_result['data'] as $row){
$export['Name'] = $row['order_name'];
$export['Billing Name'] = $row['first_name'] . ' ' . $row['last_name'];
$export['Email'] = $row['email'];
$export['Fulfillment Status'] = $fullfilment_status_array[$row['status']];
$export['Total'] = $row['total'];
$export['Created at'] = date($date_format, strtotime($row['created_at']));
$export['Delivery Status'] = $row['delivery_status'] == 0 ? 'Pending' : 'Delivered';
$export['Delivery Date'] = date($date_format, strtotime($row['delivery_date']));
$export['Delivery Time'] = (isset($row['delivery_time']) && $row['delivery_time'] != '') ? $row['delivery_time'] : '-';
$export_data[] = $export;
}
/* Export Data */
$filename = "orders_export.csv";
$f = fopen('php://output', 'w');
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename=' . $filename);
$outputdata = $export_data;
$firstLineKeys = false;
foreach ($outputdata as $row) {
if (empty($firstLineKeys)) {
$firstLineKeys = array_keys($row);
fputcsv($f, $firstLineKeys);
$firstLineKeys = array_flip($firstLineKeys);
}
fputcsv($f, $row);
}
fclose($f);
ob_end_flush();
exit();
}
}
This code is tested well and working fine.

Export CSV file from Codeigniter

I am using csv_helper.php file in helpers for exporting. It is grabing the results from mysql but showing the results only instead of downloading !
Here's the csv_helper
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('array_to_csv'))
{
function array_to_csv($array, $download = "")
{
if ($download != "")
{
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="' . $download . '"');
}
ob_start();
$f = fopen('php://output', 'w') or show_error("Can't open php://output");
$n = 0;
foreach ($array as $line)
{
$n++;
if ( ! fputcsv($f, $line))
{
show_error("Can't write line $n: $line");
}
}
fclose($f) or show_error("Can't close php://output");
$str = ob_get_contents();
ob_end_clean();
if ($download == "")
{
return $str;
}
else
{
echo $str;
}
}
}
if ( ! function_exists('query_to_csv'))
{
function query_to_csv($query, $headers = TRUE, $download = "")
{
if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
{
show_error('invalid query');
}
$array = array();
if ($headers)
{
$line = array();
foreach ($query->list_fields() as $name)
{
$line[] = $name;
}
$array[] = $line;
}
foreach ($query->result_array() as $row)
{
$line = array();
foreach ($row as $item)
{
$line[] = $item;
}
$array[] = $line;
}
echo array_to_csv($array, $download);
}
}
And here's the controller function:
public function exportUser() {
$this->load->database();
$query = $this->db->get('user');
$this->load->helper('csv');
query_to_csv($query, TRUE, 'toto.csv');
}
And in the view page it is showing the results:
user_id,user_name,user_email,user_pass,user_phone,user_country,user_city,user_zip,user_address,user_type,user_status 53,abcdef,abcd#yahoo.com,12,1,,0,,,Student,1 54,aws,abc#yahoo.com,12,12,Afghanistan,Kapisa,,,"Resource Person",0 55,onti,ontika#ya.com,12,12,,0,,,"Registered User",1 56,edf,df#abc.com,12,12,Albania,Bulqize,,dewde,"Admin User",1 58,meena,meena#abc.com,,,,,,,"Registered User",0
61,nisat,nisat#abc.com,,,,,,,"Registered User",0
but not downloading ! Tried Chrome and mozilla both....
What to do???
Thank you in advance !
Try modifying the headers in array_to_csv() funtion:
// Disable caching
$time = gmdate('D, d M Y H:i:s');
header('Expires: Tue, 03 Jul 2001 06:00:00 GMT');
header('Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate');
header('Last-Modified: ' . $time . ' GMT');
// Force download
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
// Set encoding
header('Content-Disposition: attachment;filename=' . $download);
header('Content-Transfer-Encoding: binary');
Then after the output section, add an exit:
if ($download == "")
{
return $str;
}
else
{
echo $str;
}
exit;
Or try using CodeIgniter's built-in functions:
public function exportUser() {
// Load database and query
$this->load->database();
$query = $this->db->get('user');
// Load database utility class
$this->load->dbutil();
// Create CSV output
$data = $this->dbutil->csv_from_result($query);
// Load download helper
$this->load->helper('download');
// Stream download
force_download('toto.csv', $data);
}
Thanks,
Andrew

Html Codes In Exported Data [PHP]

I am trying to export the data got from my database.
The problem is that the data comes with html codes.
I just want to export the data without html codes.
Note: My database doesn't have any html code.
$exported_db_datas (global array variable) is created like this:
while($row = mysql_fetch_array($resultset,MYSQL_ASSOC))
{
$resultsarray[$rowcount] = $row;
$exported_db_datas[$rowcount] = $row;
/*foreach($resultsarray[$rowcount] as $column)
{
$resultsarray2[$rowcount][] = $column;
}*/
$rowcount++;
}
Export codes :
$export_file = "export_phisto";
if ($format == "CSV")
{
$file = $export_file.".csv";
$separator = ",";
}
elseif ($format == "TAB")
{
$file = $export_file.".tab";
$separator = "\t";
}
elseif ($format == "TXT")
{
$file = $export_file.".txt";
$separator = "\t";
}
else// XLS
{
$file = $export_file.".xls";
$separator = "\t";
}
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Type: text/plain");
$flag = false;
foreach($exported_db_datas as $row)
{
if(!$flag)
{
// display field/column names as first row
echo implode($seperator, array_keys($row)) . "\r\n";
$flag = true;
}
echo implode($seperator, array_values($row)) . "\r\n";
}
Note: Even if I don't use print $data, exported data has html codes of the web site without data.
How can I just export the data I get from database?
Example exported data is was here.
Use strip_tags
$exported_db_datas[$rowcount] = strip_tags($row);
just use strip_tags() in this line $exported_db_datas[$rowcount] = $row; like so: $exported_db_datas[$rowcount] = strip_tags($row);
PS: don't use the mysql_* extension, it was deprecated, see the red warning box here

PHP Array to CSV

I'm trying to convert an array of products into a CSV file, but it doesn't seem to be going to plan. The CSV file is one long line, here is my code:
for($i=0;$i<count($prods);$i++) {
$sql = "SELECT * FROM products WHERE id = '".$prods[$i]."'";
$result = $mysqli->query($sql);
$info = $result->fetch_array();
}
$header = '';
for($i=0;$i<count($info);$i++)
{
$row = $info[$i];
$line = '';
for($b=0;$b<count($row);$b++)
{
$value = $row[$b];
if ( ( !isset( $value ) ) || ( $value == "" ) )
{
$value = "\t";
}
else
{
$value = str_replace( '"' , '""' , $value );
$value = '"' . $value . '"' . "\t";
}
$line .= $value;
}
$data .= trim( $line ) . "\n";
}
$data = str_replace( "\r" , "" , $data );
if ( $data == "" )
{
$data = "\n(0) Records Found!\n";
}
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=your_desired_name.xls");
header("Pragma: no-cache");
header("Expires: 0");
array_to_CSV($data);
function array_to_CSV($data)
{
$outstream = fopen("php://output", 'r+');
fputcsv($outstream, $data, ',', '"');
rewind($outstream);
$csv = fgets($outstream);
fclose($outstream);
return $csv;
}
Also, the header doesn't force a download. I've been copy and pasting the output and saving as .csv
EDIT
PROBLEM RESOLVED:
If anyone else was looking for the same thing, found a better way of doing it:
$num = 0;
$sql = "SELECT id, name, description FROM products";
if($result = $mysqli->query($sql)) {
while($p = $result->fetch_array()) {
$prod[$num]['id'] = $p['id'];
$prod[$num]['name'] = $p['name'];
$prod[$num]['description'] = $p['description'];
$num++;
}
}
$output = fopen("php://output",'w') or die("Can't open php://output");
header("Content-Type:application/csv");
header("Content-Disposition:attachment;filename=pressurecsv.csv");
fputcsv($output, array('id','name','description'));
foreach($prod as $product) {
fputcsv($output, $product);
}
fclose($output) or die("Can't close php://output");
Instead of writing out values consider using fputcsv().
This may solve your problem immediately.
Note from comment: I should mention that this will be making a file on your server, so you'll need to read that file's contents before outputting it, also if you don't want to save a copy then you'll need to ùnlink`the file when you are done
This is a simple solution that exports an array to csv string:
function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
{
$f = fopen('php://memory', 'r+');
foreach ($data as $item) {
fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
}
rewind($f);
return stream_get_contents($f);
}
$list = array (
array('aaa', 'bbb', 'ccc', 'dddd'),
array('123', '456', '789'),
array('"aaa"', '"bbb"')
);
var_dump(array2csv($list));
Reference
Try using;
PHP_EOL
To terminate each new line in your CSV output.
I'm assuming that the text is delimiting, but isn't moving to the next row?
That's a PHP constant. It will determine the correct end of line you need.
Windows, for example, uses "\r\n". I wracked my brains with that one when my output wasn't breaking to a new line.
how to write unified new line in PHP?
I know this is old, I had a case where I needed the array key to be included in the CSV also, so I updated the script by Jesse Q to do that.
I used a string as output, as implode can't add new line (new line is something I added, and should really be there).
Please note, this only works with single value arrays (key, value). but could easily be updated to handle multi-dimensional (key, array()).
function arrayToCsv( array &$fields, $delimiter = ',', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');
$output = '';
foreach ( $fields as $key => $field ) {
if ($field === null && $nullToMysqlNull) {
$output = '';
continue;
}
// Enclose fields containing $delimiter, $enclosure or whitespace
if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
$output .= $key;
$output .= $delimiter;
$output .= $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
$output .= PHP_EOL;
}
else {
$output .= $key;
$output .= $delimiter;
$output .= $field;
$output .= PHP_EOL;
}
}
return $output ;
}
In my case, my array was multidimensional, potentially with arrays as values. So I created this recursive function to blow apart the array completely:
function array2csv($array, &$title, &$data) {
foreach($array as $key => $value) {
if(is_array($value)) {
$title .= $key . ",";
$data .= "" . ",";
array2csv($value, $title, $data);
} else {
$title .= $key . ",";
$data .= '"' . $value . '",';
}
}
}
Since the various levels of my array didn't lend themselves well to a the flat CSV format, I created a blank column with the sub-array's key to serve as a descriptive "intro" to the next level of data. Sample output:
agentid fname lname empid totals sales leads dish dishnet top200_plus top120 latino base_packages
G-adriana ADRIANA EUGENIA PALOMO PAIZ 886 0 19 0 0 0 0 0
You could easily remove that "intro" (descriptive) column, but in my case I had repeating column headers, i.e. inbound_leads, in each sub-array, so that gave me a break/title preceding the next section. Remove:
$title .= $key . ",";
$data .= "" . ",";
after the is_array() to compact the code further and remove the extra column.
Since I wanted both a title row and data row, I pass two variables into the function and upon completion of the call to the function, terminate both with PHP_EOL:
$title .= PHP_EOL;
$data .= PHP_EOL;
Yes, I know I leave an extra comma, but for the sake of brevity, I didn't handle it here.
The easiest way to create csv file from an array is to use implode() function:
<?php
$arr = array('A','B','C','D');
echo implode(",",$arr);
?>
The output of the above code will give:
A,B,C,D
Arrays of data are converted into csv 'text/csv' format by built in php function fputcsv takes care of commas, quotes and etc..
Look at
https://coderwall.com/p/zvzwwa/array-to-comma-separated-string-in-php
http://www.php.net/manual/en/function.fputcsv.php
It worked for me.
$f=fopen('php://memory','w');
$header=array("asdf ","asdf","asd","Calasdflee","Start Time","End Time" );
fputcsv($f,$header);
fputcsv($f,$header);
fputcsv($f,$header);
fseek($f,0);
header('content-type:text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
fpassthru($f);```
I use this simple function to create every single array entry as csv:
function arrayToCsv($fields, $delimiter = ",", $enclosure = "\"", $escapeChar = "\"")
{
$fp = fopen('php://temp', 'r+');
fputcsv($fp, $fields, $delimiter, $enclosure, $escapeChar);
rewind($fp);
$ret = fgets($fp);
fclose($fp);
return $ret;
}
You can try below code to export csv from array using fputcsv
ob_start();
$outputCsv = fopen('php://output', 'w');
fputcsv($outputCsv, ['column 1', 'column 2' 'column 3'], ",");
fputcsv($outputCsv, ['','',''], ",");
fputcsv($outputCsv, ['value 1', 'value 2' 'value 3'], ",");
fputcsv($outputCsv, ['value 11', 'value 21' 'value 31'], ",");
fputcsv($outputCsv, ['value 12', 'value 22' 'value 31'], ",");
header('Cache-Control: max-age=0');
header("Expires: 0");
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header('Pragma: public'); // HTTP/1.0
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-type: application/csv');
header('Content-Disposition: attachment;filename="doc_logs.csv"');
header("Content-Transfer-Encoding: binary");
fpassthru($outputCsv);
fclose($outputCsv);

Categories