PHP - Creating CSV file inserts empty row at the end - php

I am trying to create a CSV file in my php script. It creates the file but each time it inserts an empty row at the end.
My code is below:
$csv_output .= "Header 0,";
$csv_output .= "Header 1,";
$csv_output .= "Header 2,";
$csv_output .= "Header 3,";
$csv_output .= "Header 4,";
$csv_output .= "\r\n";
// db query...
foreach($rows as $row):
if($row["value_3"] == 10)
{
$x = 'low';
}
else if($row["value_3"] == 100)
{
$x = 'high';
}
$csv_output .= "".$row["value_0"].",";
$csv_output .= "".$row["value_1"].",";
$csv_output .= "".$row["value_2"].",";
$csv_output .= "".$x.",";
$csv_output .= "Constant Always Value Goes here (not in db),";
$csv_output .= "\r\n";
endforeach;
$filename = "csv_".date("d-m-Y_H-i",time());
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
print $csv_output;
No matter what my database query is or how many rows the csv contains there is always an empty row at the end. Is there anything causing this?

You can write the CSV directly to the output like so, and you don't need to format it yourself.
// Send correctly formatted headers
header("Content-type: application/vnd.ms-excel");
// Disposition should be "attachment" followed by optional filename.
header(sprintf('Content-disposition: attachment; filename="csv_%s.csv"', date("d-m-Y_H-i")));
// Open a pointer to the output stream
$fp = fopen('php://output', 'w');
// Build header array
$head = array(
"Header 0",
"Header 1",
"Header 2",
"Header 3"
);
// Write the header array in default csv row format.
fputcsv($fp, $head);
// db query...
// Loop rows
foreach($rows as $row) {
// Write the rows in default csv row format
fputcsv($fp, $row);
}
// Close the output stream
fclose($fp);
An additional benefit is it will use less memory on large downloads, for instance with PDO:
$stmt = $pdo->prepare("SELECT ...");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
fputcsv($fp, $row);
}
This will output each row to the browser, directly from the database (more or less), will a very low memory footprint.

Apart from other problems highlighted by Mark Baker, you are adding EOL in the loop. Remove the final one by trim
print trim($csv_output);

Related

Export Mysql Data into MS Excel Using a Link\Button in PHP

I am a newbie to PHP and need help in exporting a selected content from Mysql Table to MS Excel using PHP. I need this done by a click of a button or a link.
Below is a piece of code I have done so far but I am consistently getting a warning as "Cannot modify header information - headers already sent". Also suggest a good way to export table on a click of a button\link. Thanks
//Export Contents
$header = '';
$data = '';
$fields = mysql_num_fields($sql);
//fetch header
for($i=0; $i < $fields; $i++)
{
$header .= mysql_field_name($sql, $i)."\t";
}
//fetch data each row, store on tabular row data
while($row = mysql_fetch_row($sql))
{
$line = '';
foreach($row as $value)
{
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);
}
//Naming the excel sheet
$name = $customerFilter."_".date('d-m-y').".xls";
header("Content-type:application/vnd.ms-excel;name='excel'");
header("Content-Disposition: attachment; filename=$name");
header("Pragma: no-cache");
header("Expires: 0");
//Output Data
echo $header."\n\n".$data;
The mysql query
SELECT <column list>
FROM <table>
INTO OUTFILE '/tmp/somefilename.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
Then redirect to the file
if you got a "headers already sent" you have some output (whitespaces) before sending your excel headers. Please enshure that the <?php tag is the very first in your file.
Please read this thread: How to fix "Headers already sent" error in PHP
You should use a library like this http://phpexcel.codeplex.com/ to be able to output stable excel files.
Here is a hello world example for phpexcel:
http://phpexcel.codeplex.com/wikipage?title=Examples&referringTitle=Home

postgresql query result to csv prints current page's html code also

I am trying to output the results of a PostgreSQL query to CSV format using PHP.
On the main page is a link that sends the SQL statements as a string to another function in another PHP class, which in turn takes the SQL and executes the query using pg_query() and return the result sets.
My problem is that when I open the CSV file, all the results of my query are there, but at the end of the file I see the HTML code from the page that sent the query.
I looked at several StackOverflow posts, but to no avail.
Here is my code:
Main class:
$o .= '<p>You can convert the result set to CSV format to be opened in Excel.</p>';
$link = array('op1' => 'PatternExport', 'op2' => 'outputToCSV', 'id' => $pattern_id, 'data' => $pattern_SQL);
$o .= 'Download Query Results as CSV File';
Receiving class:
function outputToCSV()
{
$ptid = $this->oQS->getValue('id');
$sql = $this->oQS->getValue('data');
$href = $this->oQS->buildEncryptedURL(array('op1'=>'PatternManager', 'op2'=>'listPatterns'),'/aatsc/index.php');
$result = pg_query($sql);
// filename for download
$filename = "query_results_" . date('Ymd') . "_" . $ptid . ".csv";
$output = fopen('php://temp/maxmemory:' . (12*1024*1024), 'rw+');
foreach(pg_fetch_assoc($result,0) AS $field=>$value)
{
$output .= '' . $field . ',';
}
$output = rtrim($output,',') . "\n";
for($i=0;$i<pg_num_rows($result);$i++)
{
foreach(pg_fetch_assoc($result,$i) AS $field=>$value)
$output .= '' . $value . ',';
$output = rtrim($output,',') . "\n";
}
header("Content-Type: application/vnd.ms-excel;");
header("Content-Disposition: attachment; filename=\"$filename\";");
header("Pragma: no-cache");
print($output);
//$href = $this->oQS->buildEncryptedURL(array('op1'=>'PatternManager', 'op2'=>'listPatterns'),'/aatsc/index.php');
//header("Location: $href");
}
Could you tell me whether I am using the right approach to export query results to CSV, and what in my code is causing the whole HTML code to be streamed?
Thanks
You're generating $output twice, if you remove the foreach loop & fopen line, it should work.
You merely just need to issue the SQL COPY statement as follows:
COPY (select * from tbl) to stdout with csv header
resulting in:
col1,col2,col3
2013-05-22 07:28:59.732,192.168.1.67,3

writing header into csv using php

i have a requirement where i am logging each page visit and activities into csv log file. how can i write so that the header should be written for the first time only not every time.
fputcsv($fh1, array(date,id1,page,id2,request,ip));
fputcsv($fh1, array($date,$mid,$page,$aid,$request,$ip));
The first array should be written once only for a particular date log file. Please Suggest.
You're going to kick yourself when you see this ...
if (!file_exists('log.csv'))
{
// Make the file & Write the header
}
// Write the log entry.
I hope you are trying to arrange the record with header when you download CSV. If YES then please have a look on this example below, where I am showing it in small example which works in Drupal-
<?php
function getUsersDetails(){
$csv_output = '';
$all_users_entry = db_query("SELECT * FROM users");
while($users = db_fetch_object($all_users_entry)){//suppose these fname,lname etc are column name of your table.
$fname = $users->fname;
$lname = $users->lname;
$date = $users->joining_date;
$role = $users->role;
$location = $users->location;
$csv_output .= "\"".$fname."\"".","."\"".$lname ."\"".","."\"".$date."\"".","."\"".$role."\"".","."\"".$location."\""."\r";
}
return $csv_output;
}
function download_details(){
$csv_output = '';
$csv_output .= "First Name,Last name,Member Since,Role,Place\n";
$csv_output .= getUsersDetails();
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename="Usera_Details.csv"');
print $csv_output;
exit;
}
?>
Now you can call this function download_details() from any place and you will have users table details in the downloaded CSV

exporting data from mysql to ms excel

I have the following code which I am using to export data from mysql database to microsoft excel
$result = $this->db->query($sql);
$num_fields = mysql_num_fields($result);
$header = "";
for($i = 0; $i < $num_fields; $i++ )
{
$header .= mysql_field_name($result,$i)."\t";
}
$data = "";
while($row = mysql_fetch_row($result))
{
$line = '';
foreach($row as $value)
{
if((!isset($value)) || ($value == ""))
{
$value = "\t";
}
else
{
$value = str_replace( '"' , '""' , $value );
$value = '"' . $value . '"' . "\t";
}
$line .= $value;
}
$data .= trim( $line ) . "\n";
}
/*if($code=="M"||$code=='m'){
$value="\n Total \t $total \t";
$data .=trim($value)."\n";
}*/
$data = str_replace("\r" , "" , $data);
if ($data == "")
{
$data = "\n No Record Found!n";
}
header("Cache-Control: ");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$label.xls\"");
header("Pragma: ");
header("Expires: 0");
print "$header\n$data";
where $result is a mysql resource.
When I run the program, before opening, excel issues a warning "the file you are trying to open, filename.xls, is in different format than specified by the extension, verify that the file is not corrupted and is from a trusted source before opening. Do you want to open the file now?"
I am stranded because after accepting to open the file, I see the data that I require, what I want is a way of making the format of data sent match the xls extension format. What should I do?. I am using ms office 2007
If you want to produce a real Excel file, use PHPExcel.
Your code produces a tab seperated ascii file - not an XLS file as you are claiming in the header.
Return the correct mimetype ("Content-Type: text/csv") and an appropriate file extension (e.g. ${label}.txt) and MSEscel will stop complaining.
(NB I'd stay well away from anything which writes native MSExcel files - even using MS's "open" xaml formats - sooner or later you'll run into horrible compatability problems).

html table to CSV or Excel

Alright, I'm starting to go a little crazy...
jQuery Table to CSV export
I'm looking at that thread.
It does work, but the output does everything by each LINE not by the HTML table rows. For example, I have an address that is in one HTML cell:
1234 Berryman Lane
Atlanta, GA 12345
Unit # 54A
That will be THREE rows when it outputs to excel, instead of one cell, with returns in it.
Further, there's no way to strip out the HTML that is inside of the HTML cells with that solution, as far as I know...
Finally, Excel gives a warning when opening that file.
What I'm getting at, is that I'd rather just have something that can take the inner most data in the HTML cells (not including HTML inside of a cell), and rip it to CSV. Is there anything that does this well these days?
UPDATE
Well, I just found the best thing yet, this is pretty perfect:
$table = 'myTable';
$file = 'exportFile';
$result = mysql_query("SHOW COLUMNS FROM ".$table."");
$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output .= "\"" . $row['Field']."\",";
$i++;
}
}
$csv_output .= "\n";
$values = mysql_query("SELECT * FROM ".$table."");
while ($rowr = mysql_fetch_row($values)) {
for ($j=0;$j<$i;$j++) {
$csv_output .= "\"" . $rowr[$j]."\",";
}
$csv_output .= "\n";
}
$filename = $file."_".date("Y-m-d_H-i",time());
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
print $csv_output;
exit;
I think this is my keeper. It goes to a CSV file with no issues, loads in Excel with no issues, it's my dream come true!
well, you can always use the same markup in excel as it can render html if you use the .xls file type, render the html table and change the content type to "application/vnd.ms-excel" specify a filename for that response as *.xls and you should have a usable excel sheet.
If there are no dobule quotes in the data, you can wrap the content of each cell in double quotes so your data looks like:
"...","...","..."
Now you can have commas in the data. You may also need to deal with new lines and returns in the data, probably best to remove them completely but that's up to you.
Thanks for all suggestions. As stated in my edited post, this script below was a great solution:
$table = 'myTable';
$file = 'exportFile';
$result = mysql_query("SHOW COLUMNS FROM ".$table."");
$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output .= "\"" . $row['Field']."\",";
$i++;
}
}
$csv_output .= "\n";
$values = mysql_query("SELECT * FROM ".$table."");
while ($rowr = mysql_fetch_row($values)) {
for ($j=0;$j<$i;$j++) {
$csv_output .= "\"" . $rowr[$j]."\",";
}
$csv_output .= "\n";
}
$filename = $file."_".date("Y-m-d_H-i",time());
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
print $csv_output;
exit;
I think this is my keeper. It goes to a CSV file with no issues, loads in Excel with no issues, it's my dream come true!

Categories