I have a mysql row with utf8_general_ci collation, when I export it to csv, instead of correct utf-8 characters I get Ć…ā€¦I etc, how to make excel understand UTF-8 encoding here is my code:
$conn = mysql_connect('localhost', 'root', 'asdfggh') or die(mysql_error());
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET NAMES utf8");
mysql_select_db('table_name', $conn) or die(mysql_error($conn));
$query = sprintf('SELECT * FROM sudraba_birzs');
$result = mysql_query($query, $conn) or die(mysql_error($conn));
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="'.date("d-m-Y_H:i") . '.csv'.'"');
echo "\xef\xbb\xbf";
$row = mysql_fetch_assoc($result);
if ($row) {
echocsv(array_keys($row));
}
while ($row) {
echocsv($row);
$row = mysql_fetch_assoc($result);
}
function echocsv($fields)
{
$separator = '';
foreach ($fields as $field) {
if (preg_match('/\\r|\\n|,|"/', $field)) {
$field = '"' . str_replace('"', '""', $field) . '"';
}
echo $separator . $field;
$separator = ',';
}
echo "\r\n";
}
How to export it to get all characters display correctly (make Excel understand utf-8) and to maintain table layout too(with rows and columns)
You are generating CSV, which is basically a plain text file. There's no way to specify encoding information in such kind of files. Most text editors implement (better or worse) encoding auto-detection. Excel doesn't. Excel will simply assume ANSI when you right-click on a CSV file. (You need to use the "Open" menu in order to be prompted about encoding.)
Your only option left (apart from switching to another output format) is converting data to ANSI, either with mb_convert_encoding() or with iconv(). But now you have another problem: ANSI is not a real encoding, it basically means "whatever encoding is set in my Windows computer". You first have to find out the typical encoding most of your users have. That mostly depends on the country. For instance, many Western Europe countries use Win-1252.
I had the same problem (common problem in databases with spanish language). I wrote this and it worked:
This is a Class that connects with the database and the functions will do whatever you want using mysqli and PHP. In this case, calling this class (require or include), just use the "downloadCsv()" function.
As an example, this would be the "class.php" file:
<?php
class DB{
private $con;
//this constructor connects with the database
public function __construct(){
$this->con = new mysqli("Your_Host","Your_User","Your_Pass","Your_DatabaseName");
if($this->con->connect_errno > 0){
die('There was a problem [' . $con->connect_error . ']');
}
}
//create the function that will download a csv file from a mysqli query
public function downloadCsv(){
$count = 0;
$header = "";
$data = "";
//query
$result = $this->con->query("SELECT * FROM Your_TableName");
//count fields
$count = $result->field_count;
//columns names
$names = $result->fetch_fields();
//put column names into header
foreach($names as $value) {
$header .= $value->name.";";
}
}
//put rows from your query
while($row = $result->fetch_row()) {
$line = '';
foreach($row as $value) {
if(!isset($value) || $value == "") {
$value = ";"; //in this case, ";" separates columns
} else {
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . ";"; //if you change the separator before, change this ";" too
}
$line .= $value;
} //end foreach
$data .= trim($line)."\n";
} //end while
//avoiding problems with data that includes "\r"
$data = str_replace("\r", "", $data);
//if empty query
if ($data == "") {
$data = "\nno matching records found\n";
}
$count = $result->field_count;
//Download csv file
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=FILENAME.csv");
header("Pragma: no-cache");
header("Expires: 0");
echo $header."\n".$data."\n";
}
?>
After creating the "class.php" file, in this example, use that function on "download.php" file:
<?php
//call the "class.php" file
require_once 'class.php';
//instantiate DB class
$export = new DB();
//call function
$export->downloadCsv();
?>
After download, open the file with MS Excel.
I hope this help you, I think I wrote it well, I didn't feel comfortable with the text and code field.
As an alternate and much sipmler solution, you can try this, i am using it for a few years by now, and never had a problem with it.
db_connect.php
<?php
$mysqli = new mysqli($mysqli_host, $mysqli_user, $mysqli_pass, $mysqli_db);
if ($mysqli->connect_errno)
{
$debug = $debug.'<br/>Failed to connect to MySQL: (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error;
}
else
{
$debug = $debug.'<br/>Connected to '. $mysqli->host_info;
}
?>
Export function
function export($query_exp,$name)
{
require '../lib/db_config.php';
require '../lib/db_connect.php';
$filename = $name.' - '.date('Y.m.d').'.xls'; /*set desired output file name here*/
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str);
$str = preg_replace("/\r?\n/", "\\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
if ($str=='') {$str='-';}
}
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
$flag = false;
if ($result = $mysqli->query($query_exp))
{
if ($result->num_rows>0)
{
$result->data_seek(0);
while ($row = $result->fetch_assoc())
{
if(!$flag)
{
print implode("\t", array_keys($row)) . "\r\n";
$flag = true;
}
array_walk($row, 'cleanData');
print implode("\t", array_values($row)) . "\r\n";
}
}
else { $debug = $debug.'<br/>Empty result'; /*DEBUG*/ }
}
else { $debug = $debug.'<br/>Oups, Query error!<br/>Query: '.$query_exp.'<br/>Error: '.$mysqli->error.'.'; /*DEBUG*/ }
require '../lib/db_disconnect.php';
}
You can call the function as:
export('SELECT * FROM SAMPLE WHERE 1;','desired_file_name.extension')
Related
I am exporting to CSV from my php reporting website. I have reports that are more than 80k rows. When I export one of them the whole data set does not get exported. I have tried several times with a report that is 88k+ rows and it exports 87k+ rows and then stops part way through the last row that is exported.
What is going on? The query that pulls the data from MSSQL is correct (I've checked).
Here's my Export file:
error_reporting(E_ALL);
ini_set('display_errors', 1);
include('DBConn.php');
include 'Helper/LogReport.php';
if(isset($_GET['Id']))
{
$id = $_GET['Id'];
$query = $conn->prepare('SELECT QName, tsql from pmdb.QDefs WHERE Id = ' . $id);
$query->execute();
$qdef = $query->fetch(PDO::FETCH_ASSOC);
}
else
{
$query = $conn->prepare("SELECT QName, tsql from pmdb.QDefs WHERE QName = '" .$TableName. "'");
$query->execute();
$qdef = $query->fetch(PDO::FETCH_ASSOC);
}
// Create and open file for writing
$filepath = 'exports/';
$filename = $qdef['QName'] . '.csv';
try
{
header('Content-Encoding: UTF-8');
header('Content-Type: text/csv; charset:UTF-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
}
catch(Exception $e)
{
echo "Something went wrong<br>";
die( print_r( $e->getMessage()));
}
//define separators
$sep = ","; //separator
$br = "\r\n"; //line break
// Use returned tsql field as query for dataset
$tsql = $qdef['tsql'];
if(isset($DataReturn))
{
if(strpos($DataReturn['Order'],'EDIT'))
{
$DataReturn['Order'] = str_replace('EDIT','Id',$DataReturn['Order']);
}
$tsql = $tsql . $DataReturn['WhereClause'] . $DataReturn['Order'] . $DataReturn['Limit'];
}
$query = $conn->prepare($tsql);
$query->execute();
// Output data to CSV file
$headers = NULL;
while ($row = $query->fetch(PDO::FETCH_ASSOC))
{
//Write column headings to file
if (is_null($headers))
{
$headers = array_keys($row);
if ($headers[0] == 'ID')
$headers[0] = 'Id';
foreach($headers as $Header)
{
echo $Header. ",";
}
echo $br;
}
//Write data
$modRow = preg_replace('/ \d{2}:\d{2}:\d{2}\.\d{3}/', '', $row);
$modRow = preg_replace( "/\r|\n/", "", $modRow );
foreach($modRow as $RowPrint)
{
echo '"' .trim(unserialize(serialize($RowPrint))). '"' .$sep;
}
echo $br;
}
I don't see anything that would stop the data stream from completing the export.
EDIT
I have tried the fputcsv() method like this:
error_reporting(E_ALL);
ini_set('display_errors', 1);
include('DBConn.php');
include 'Helper/LogReport.php';
//print_r($_GET);
if(isset($_GET['Id']))
{
$id = $_GET['Id'];
$query = $conn->prepare('SELECT QName, tsql from pmdb.QDefs WHERE Id = ' . $id);
$query->execute();
$qdef = $query->fetch(PDO::FETCH_ASSOC);
}
else
{
$query = $conn->prepare("SELECT QName, tsql from pmdb.QDefs WHERE QName = '" .$TableName. "'");
$query->execute();
$qdef = $query->fetch(PDO::FETCH_ASSOC);
}
// Create and open file for writing
$filepath = 'exports/';
$filename = $qdef['QName'] . '.csv';
try
{
$openFile = fopen($filepath . $filename,'a');
header('Content-Encoding: UTF-8');
header('Content-Type: text/csv; charset:UTF-8');
header('Content-Disposition: attachment; filename="' . $filename . '"');
}
catch(Exception $e)
{
echo "Something went wrong<br>";
die( print_r( $e->getMessage()));
}
//define separators
$sep = ","; //separator
$br = "\r\n"; //line break
// Use returned tsql field as query for dataset
$tsql = $qdef['tsql'];
if(isset($DataReturn))
{
if(strpos($DataReturn['Order'],'EDIT'))
{
$DataReturn['Order'] = str_replace('EDIT','Id',$DataReturn['Order']);
}
$tsql = $tsql . $DataReturn['WhereClause'] . $DataReturn['Order'] . $DataReturn['Limit'];
}
$query = $conn->prepare($tsql);
$query->execute();
// Output data to CSV file
$headers = NULL;
while ($row = $query->fetch(PDO::FETCH_ASSOC))
{
//Write column headings to file
if (is_null($headers))
{
$headers = array_keys($row);
if ($headers[0] == 'ID')
$headers[0] = 'Id';
fputcsv($openFile, $headers);
}
//Write data
$modRow = preg_replace('/ \d{2}:\d{2}:\d{2}\.\d{3}/', '', $row);
$modRow = preg_replace( "/\r|\n/", "", $modRow );
fputcsv($openFile, $modRow, ',','"');//print_r($modRow);
foreach($modRow as $RowPrint)
{
error_log(date("Y/m/d h:i:sa "). ' RowPrint: ' .$RowPrint. '\n',3,'C:\Temp\LogPHP.txt');
}
echo $br;
}
// Close file
fclose($openFile);
This just creates an empty file.
UPDATE
I ran a couple of reports for one that should have 103k+ rows. They both stopped between 61000 and 62000 rows. I did a character count and they both have around 40 million. I don't see anything about a 40million character limit.
I got it working and figured out how to get the fputcsv to work.
I needed to add an exit() to the end of the export. Now it not only sends all the data fputcsv works as well. I got the answer from another question that I ask about getting fputcsv to work.
I am trying to bug fix a PHP script that should export values from a MySQL database to a CSV file.
The PHP file is returning a blank CSV file & I can't figure out why & I've been stuck on this for quite a while, so any help would be much apprwciated.
Code below:
<?
include('../../../inc/config.php');
$period = $_GET['pid'];
$psql = "SELECT month, year FROM survey_period WHERE sid = " . $period;
$pres = mysql_query($psql, $dcon);
$prow = mysql_fetch_array($pres);
$pmonth = $prow['month'];
$pyear = $prow['year'];
$query="SELECT
sid,
date,
stove_id,
name,
gender,
marital_status,
occupation_of_household,
cz_stove AS km_stove,
happy_with_cz_stove AS happy_with_km_stove,
cz_stove_in_use AS km_stove_in_use,
know_how_to_use,
FROM survey_usage WHERE period = " . $_GET['pid'];
$result = mysql_query($query, $dcon);
//header('Content-Disposition: attachment;filename=export.csv');
$filename = 'usage-'.$pid.'-'.$pmonth.'-'.$pyear;
header('Content-Type: text/csv');
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header( "Content-disposition: filename=".$filename.".csv");
$row = mysql_fetch_assoc($result);
if ($row) {
echocsv(array($title));
echo "\r\n";
echocsv(array_keys($row));
}
while ($row) {
echocsv($row);
$row = mysql_fetch_assoc($result);
}
function echocsv($fields)
{
$separator = '';
foreach ($fields as $field) {
if (preg_match('/\\r|\\n|,|"/', $field)) {
$field = '"' . str_replace('"', '""', $field) . '"';
}
echo $separator . $field;
$separator = ',';
}
echo "\r\n";
}
?>
hey i have a code you can use it like this
<?PHP
// Define database connection variable dynamically
$DB_Server = "localhost"; //MySQL Server
$DB_Username = "root"; //MySQL Username
$DB_Password = ""; //MySQL Password
$DB_DBName = "test1"; //MySQL Database Name
$DB_TBLName = "tabletest"; //MySQL Table Name
$filename = "excelfilename"; //File Name
//create MySQL connection
$sql = "Select * from csvtable";
$Connect = #mysqli_connect($DB_Server, $DB_Username, $DB_Password) or die("Couldn't connect to MySQL:<br>" . mysqli_error() );
//select database
$Db = #mysqli_select_db( $Connect,$DB_DBName) or die("Couldn't select database:<br>" . mysqli_error() );
//execute query
$result = #mysqli_query( $Connect,$sql) or die("Couldn't execute query:<br>" . mysqli_error() );
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) . '"';
}
// filename for download
$filename = "file_" . date('Ymd') . ".csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: text/csv;");
$out = fopen("php://output", 'w');
$flag = false;
while ($row = mysqli_fetch_assoc($result))
{
if (!$flag)
{
// display field/column names as first row
fputcsv($out, array_keys($row), ',', '"'); $flag = true;
}
array_walk($row, 'cleanData');
// insert data into database from here
fputcsv($out, array_values($row), ',', '"');
}
fclose($out);
exit;
//end
?>
The issue is that you are not writing anything to the csv file before opening it.
Use this code
$fp = fopen($filename, 'w');
$result = mysql_query($query);
$num_fields = mysql_num_fields($result);
$headers = array();
for ($i = 0; $i < $num_fields; $i++) {
$headers[] = mysql_field_name($result , $i);
}
fputcsv($fp, $headers);
while($row = mysql_fetch_assoc($result)) {
fputcsv($fp, $row);
}
fclose($fp);
header('Content-Type: text/csv');
header( "Content-disposition: filename=".$filename);
readfile($filename);
Thanks to everyone for your suggestions, problem now solved, turned out to be a simple comma in the wrong place - "know_how_to_use," changed to " know_how_to_use" solved the problem. Thanks #Tintu C Raju for pointing me in the right direction
I have a php script that exports a data from mysql into the csv. Everything worked fine, when the script was smaller but now, when it reaches a numerous code lines it doesn't do the job.
PROBLEM: it export csv file regularly, but all the tables results are in the first cell of excel. It is supposed to fill each cell - it should recognize in database where there is a comma, then use delimiter and split into cells separately.
So, the delimiter is not working and I don't know why. It should use commas and split it, and it should use | to split again.
This is the code:
$link = mysql_connect($host, $user, $pass) or die("Can not connect." . mysql_error());
mysql_select_db($db) or die("Can not connect.");
$result = mysql_query("SHOW COLUMNS FROM ".$table."");
$columnName = array();
if (mysql_num_rows($result) > 0)
{
while ($row = mysql_fetch_assoc($result))
{
$columnName[] = $row['Field'];
$i++;
}
}
$columnName[] .= "\n";
$needle = '|';
$values = mysql_query("SELECT * FROM ".$table." where id=".$id."");
while ($rowr = mysql_fetch_row($values))
{
for ($j=0;$j<$i;$j++)
{
$colName = $columnName[$j];
$count = strlen($rowr[$j]) - strlen(str_replace(str_split($needle), '', $rowr[$j]));
if ($count > 1)
{
for($p=0;$p<$count;$p++)
{
$colName .= ",";
}
$columnName[$j] = $colName;
$csv_output_column_names .= $columnName[$j].", ";
$csv_output_column_values .= str_replace('|',',',$rowr[$j]).", ";
}
else
{
$csv_output_column_names .= $columnName[$j].", ";
$csv_output_column_values .= $rowr[$j] .", ";
}
}
$csv_output_column_values .= "\n";
}
$csv_output = $csv_output_column_names."\n".$csv_output_column_values;
$filename = $file."_".date("Y-m-d");
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;
?>
Your issue is that you're not quoting fields as Excel expects it.
Instead of reinventing the wheel, you should use the already existing fgetcsv and fputcsv functions.
Normally these are used to write to files, but you can create a file handle to standard out so that they're printed to screen. For example:
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: csv" . date("Y-m-d") . ".csv");
header("Content-disposition: filename=".$filename.".csv");
// $lines is a 2D array with all rows and their column data
// $columns is a 1D array with each row's columns (see examples from fputcsv documentation)
$out = fopen("php://stdout", "w");
foreach ($lines as $columns) { fputcsv($out, $columns); }
fclose($out);
You need to care about memory to begin with, including this solves the problem delimited CSV.
Example:
$file = new SplFileObject('php://output', 'w');
$file->fputcsv($rowr, ';', '"');
Working on PHP converting to excel, but having problems in the excel file where it doesn't add each row in its own cell. Here is how it looks: https://www.dropbox.com/s/64lz7lqy8z7x72j/export.csv
It writes it on the first cell and it looks like it has written to all of the cell.
And here is the PHP code:
<?php
$conn = mysql_connect('localhost', 'root', '') or die(mysql_error());
mysql_select_db('chart', $conn) or die(mysql_error($conn));
$result = mysql_query('SELECT * FROM chartgoogle', $conn) or die(mysql_error($conn));
header('Content-Type: text/csv'); // tell the browser to treat file as CSV
header('Content-Disposition: attachment;filename=export.csv'); // tell browser to download a file in user's system with name export.csv
$row = mysql_fetch_assoc($result); // Get the column names
if ($row) {
outputcsv(array_keys($row)); // It wil pass column names to outputcsv function
}
while ($row) {
outputcsv($row); // loop is used to fetch all the rows from table and pass them to outputcsv func
$row = mysql_fetch_assoc($result);
}
function outputcsv($fields) {
$separator = '';
foreach ($fields as $field) {
echo $separator . $field;
$separator = ','; // Separate values with a comma
}
echo "\r\n"; //Give a carriage return and new line space after each record
}
?>
Try this :
function outputcsv($fields) {
$csv = '';
foreach ($fields as $field) {
$csv .= '"' . $field . '",';
}
$csv .= "\r\n"; //Give a carriage return and new line space after each record
echo $csv;
}
Take a look at the double quotes placed before and after the field. CSV files usually use double quotes as closures. They call it text qualifier.
Using PHP, I can convert MySQL data or static table data to csv, Excel, JSON, MySQL etc but is there a useful conversion script or tool that can convert table data into other formatted/styled formats such as PDF and/or JPG/PNG using the PHP GD Library or other?
I've used this before to turn a HTML table into a PDF. I generated the table from a MySQL query.
To export to Excel I use the following code:
<?php
/* Define our Database and Table Info */
$username="";
$password="";
$database="";
$table="";
mysql_connect(localhost,$username,$password);
#mysql_select_db($database) or die( "Unable to select database");
$select = "SELECT * FROM $table";
$export = mysql_query($select);
$fields = mysql_num_fields($export);
for ($i = 0; $i < $fields; $i++) {
$header .= mysql_field_name($export, $i) . "\t";
}
while($row = mysql_fetch_row($export)) {
$line = '';
foreach($row as $value) {
if ((!isset($value)) OR ($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/x-msdownload");
header("Content-Disposition: attachment; filename=mailinglist.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";
?>
Now be careful with how you include this. It's using the Headers to send the file information to force a download, by doing this you can't have any white space anywhere before these headers are sent otherwise it may throw an error. I usually have this link open as a new window to prevent anything from happening... Again this is just a pretty basic script that can be expanded greatly. Hope this Helps!
<?php
/ Define our Database and Table Info /
$username="";
$password="";
$database="";
$table="";
mysql_connect(localhost,$username,$password);
#mysql_select_db($database) or die( "Unable to select database");
$select = "SELECT * FROM $table";
$export = mysql_query($select);
$fields = mysql_num_fields($export);
for ($i = 0; $i < $fields; $i++) {
$header .= mysql_field_name($export, $i) . ",";
}
while($row = mysql_fetch_row($export)) {
$line = '';
foreach($row as $value) {
if ((!isset($value)) OR ($value == "")) {
$value = ",";
} else {
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . ",";
}
$line .= $value;
}
$data .= trim($line)."n";
}
$data = str_replace("r","",$data);
if ($data == "") {
$data = "n(0) Records Found!n";
}
header("Content-type: application/x-msdownload");
header("Content-Disposition: attachment; filename=mailinglist.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$headern$data";
?>