Reputation: 998
I am using this code to export selected data from MySQL to CSV using PHP, I am facing a little problem that when data exported to the csv file it looks like below:
First line in its correct place, but starting from the second row data shifts to the right one space, if I open the csv file in Excel, I can see the most left cell after the first row is empty.
parts destination
===================
1 9.71504E+11
1 9.71504E+11
1 96656587662
1 9.71504E+11
This is my code :
$values =mysql_query( "SELECT parts,destination from log");
$rown = 0;
$row = array();
$row[] = 'parts';
$row[] = 'destination'."\n";
$data .= join(',', $row)."\n";
while( $row_select = mysql_fetch_assoc($values) ) {
if($rown++==0)
$row = array();
$row[] = $row_select['parts'];
$row[] = $row_select['destination']."\n";
}
$data .= join(',', $row)."\n";
$filename = $file."_".date("Y-m-d_H-i",time());
header("Content-type: text/csv");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
print $data;
exit();
Would you please help?
Regards,
Upvotes: 1
Views: 2393
Reputation: 984
The problem is in the following line
$data .= join(',', $row)."\n";
You're concatenating all the elements in $row
with commas. So the destination of one row is concatenated with the parts of the next row with a comma in between, so you get something like this:
$data = $row_select['parts'] . ',' . $row_select['destination']."\n" . ',' . $row_select['parts'] etc...
The comma after the newline creates an empty cell at the beginning of the row.
UPDATE It should work with the following
while( $row_select = mysql_fetch_assoc($values)){
$row = array();
$row[] = $row_select['parts'];
$row[] = $row_select['destination']."\n";
$data .= join(',', $row);
}
Upvotes: 1
Reputation: 1481
Like @ChrisPatrick points out, the line
$data .= join(',', $row)."\n";
is causing the problem, you should move this to inside the while loop and then you'll get rid of the cell skipping.
Upvotes: 2
Reputation: 18859
First line in its correct place, but starting from the second row data shifts to the right one space, if I open the csv file in Excel, I can see the most left cell after the first row is empty.
I've found out the hard way that writing CSV is more complex than one would imagine. Take, for example, escaping the values so that the delimiter is properly escaped inside values. I've created a simple class that utilises fwritecsv( ) instead of trying to render CSV myself:
EDIT: I've changed the example to your usage scenario.
<?php
/**
* Simple class to write CSV files with.
*
* @author Berry Langerak <[email protected]>
*/
class CsvWriter {
/**
* The delimiter used. Default is semi-colon, because Microsoft Excel is an asshole.
*
* @var string
*/
protected $delimiter = ";";
/**
* Enclose values in the following character, if necessary.
*
* @var string
*/
protected $enclosure = '"';
/**
* Constructs the CsvWriter.
*/
public function __construct( ) {
$this->buffer = fopen( 'php://temp', 'w+' );
}
/**
* Writes the values of $line to the CSV file.
*
* @param array $line
* @return CsvWriter $this
*/
public function write( array $line ) {
fputcsv( $this->buffer, $line, $this->delimiter, $this->enclosure );
return $this;
}
/**
* Returns the parsed CSV.
*
* @return string
*/
public function output( ) {
rewind( $this->buffer );
$output = $this->readBuffer( );
fclose( $this->buffer );
return $output;
}
/**
* Reads the buffer.
* @return type
*/
protected function readBuffer( ) {
$output = '';
while( ( $line = fgets( $this->buffer ) ) !== false ) {
$output .= $line;
}
return $output;
}
}
/**
* Example usage, in your scenario:
*/
$values = mysql_query( "SELECT parts,destination from log" );
$csv = new CsvWriter( );
$csv->write( array( 'parts', 'destination' ) ); // write header.
while( $line = mysql_fetch_assoc( $values ) ) {
$csv->write( $line );
}
$filename = $file."_".date("Y-m-d_H-i",time());
header("Content-type: text/csv");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
print $csv->output( );
exit();
Upvotes: 3