I have troble geting this work and I can't figure it out what is the issue.
I download a xls file, but it doesent opens.
I had a mysql script like this, working, and I tried to convert it into mysqli and probably something is wrong...
Thanks in advance
$sqlExp = "SELECT * FROM table";
$countQryExp = mysqli_query($link, $sqlExp );
$filename = "sampledata.xls"; // File Name
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
$flag = false;
while($row=mysqli_fetch_array($countQryExp,MYSQLI_ASSOC))
{
if(!$flag) {
// display field/column names as first row
echo implode("\t", array_keys($row)) . "\r\n";
$flag = true;
}
echo implode("\t", array_values($row)) . "\r\n";
}
There's a lot more to generating an Excel file than giving it a content type of application/vnd.ms-excel. Excel is a very particular format, whereas you're generating a TSV file - tab separated values, and in a pretty breakable manner (what happens if someone puts a \t in one of your site's fields, or a new line?).
If you want to generate real Excel files, you'll want one of the various libraries for doing so. If a CSV/TSV are fine, just export a .csv/.tsv file with proper headers.
Related
I've searched all the posts, but still couldn't get it to work. With button press I want to export "page preset" to be precise it's restaurant menu preset, it includes css files, mysql tables etc. I want to be able to import it to another 'menu'. First I'm trying to export mysql database. Should I use mysqldump or SELECT * INTO OUTFILE ?
I'm using this line:
exec("mysqldump --user=$dbusername --password=$dbpassword restaurantsdb meal --where=restaurant_id=$restId > tables/meal.sql");
restaurantsdb is database name and meal = table name. I also want rows WHERE 'restaurant_id' = {id}
I'm trying to understand how mysqldump works, should this line work for me?
Next I'm creating zipArchive file, adding some directories, I tried adding .txt file, that one works, but it doesn't seem to find meal.sql file.
$zip = new ZipArchive();
if ( $zip->open($zip_file, ZipArchive::CREATE) !== TRUE) {
exit("error");
}
$zip->addEmptyDir('TestFiles');
$zip->addEmptyDir('tables');
$fileToZip = __DIR__.'/hello.txt';
$zip->addFile($fileToZip, "TestFiles/text.txt");
$fileToZip = __DIR__.'/tables/meal.sql';
$zip->addFile($fileToZip, "tables/meal.sql");
$download_file = file_get_contents( $file_url );
$zip->addFromString(basename($file_url),$download_file);
$zip->close();
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($zip_file).'"');
header("Content-length: " . filesize($zip_file));
header("Pragma: no-cache");
header("Expires: 0");
ob_clean();
flush();
readfile($zip_file);
unlink($zip_file);
exit;
Also, is it better to export as .sql or .csv ? Later when importing, I need to be able to change id's of all rows to specified, just before importing to database. It's basically cloning same data, but different id's.
I'm trying to convert HTML tables to CSV with my PHP-Script.
I have a lot of HTML files and each of them contains just one table with very simple structure
<table><th></th><tr><td></td></tr></table>
The HTML tables in the different files have between 300 and 2000 rows. My PHP script converts all of them with about 800 rows in under a second to CSV and everything works. But the others (with 900 rows a more) don't work. I always get an empty CSV File with just "" in it (opening it in Excel).
I run the script local on MAMP and the PHP error log says for that non-working files:
PHP Fatal error: Uncaught Error: Call to a member function find() on boolean in /Applications/MAMP/htdocs/convertcsv.php:29
Thats my single fucntion in convertcsv.php script which makes the whole conversion:
function convertToCSV($input,$output) {
$newFileContent = "";
file_put_contents($output, $newFileContent);
echo "File created (" . $output . ")";
$table = file_get_contents($input);
$html = str_get_html($table);
//Generate the CSV file header
header("Content-type: application/vnd.ms-excel");
header("Content-Encoding: UTF-8");
header("Content-type: text/csv; charset=UTF-8");
$fp = fopen($output, "w");
fwrite($fp,"\xEF\xBB\xBF");
foreach($html->find('tr') as $element) {
$td = [];
$kinder = $element->children();
foreach( $kinder as $kind) {
$td[] = $kind->plaintext;
}
fputcsv($fp, $td, ';');
}
fclose($fp);
}
Line 29 is the foreach-Loop.
Maybe you know why the script does work perfectly with tables with up to ~ 800 rows and not with bigger ones?
Thanks a lot guys
I found the problem. I just have to increase the MAX_FILE_SIZE in the included simplehtmldom.php - Greetings
my client asked me to build an export system that export the whole SQL database into csv file that works on excel. I found PHPexcel and it's great, but I thought I can do stuff way more easier and faster using my own functions.
After struggling with Excel encoding, I finally succeeded to export the CSV that will work on Excel using the following code:
<?php
$data = showData("price"); //Function that loads all the SQL database into an array.
function array2csv(array &$array)
{
if (count($array) == 0) {
return null;
}
ob_start();
$df = fopen("php://output", 'w');
fputcsv($df, array_keys(reset($array)));
foreach ($array as $row) {
fputcsv($df, $row);
}
fclose($df);
return ob_get_clean();
}
function download_send_headers($filename) {
// disable caching
$now = gmdate("D, d M Y H:i:s");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
header ( 'HTTP/1.1 200 OK' );
header ( 'Date: ' . date ( 'D M j G:i:s T Y' ) );
header ( 'Content-Type: application/vnd.ms-excel') ;
header ( 'Content-Disposition: attachment;filename=export.csv' );
}
download_send_headers("export.csv");
$final = array2csv($data);
print chr(255) . chr(254) . mb_convert_encoding($final, 'UTF-16LE', 'UTF-8');
die();
?>
The problem is that when I try to open the file in Excel there are no columns. Each row is a large column that contains the whole data of the specific row, separated by a comma.
I figured out that I would need to replace those commas with something that Excel can read as a "new column". But I still need to keep my CSV to work as it is.
I searched SO and Google with no luck whatsoever finding a solution that will keep my CSV intact and yet split the data into columns Excel. If there is no way to do both, I think the more important thing to my client is that the Excel version will work as it should (each row separated into columns).
This is a picture of how it looks on CSV (using numbers on Mac)
And this is a picture of how it looks on Excel 2007 on Windows
It's all in the fputcsv() function:
http://php.net/manual/en/function.fputcsv.php
Try to choose the correct $delimiter, $enclosure and $escape_char.
The default character that is used as the field-separator in excel is set by the locale settings. That means: Importing CVS files can be language dependent. Export to CSV from excel to see what it does on your system, and check that your client system has the same settings.
It's better to export to XML instead of CSV, because that will circumvent this problem:
http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
I have a session multidimensional array that is being populated correctly labeled $_SESSION['data'] that the user can export as a .csv. I have tested this on localhost and it works properly 100% of the time.
I have uploaded to webserver and it is no longer working properly
I have confirmed the array is being populated with real data by print_r($_SESSION['data']); and the results are displayed on the page with the data of interest every time. (i've currently disabled the output on the site itself to reduce the load time)
however the really weird thing that has been driving me nuts for a solid day now is it DOES work, but only after trying to export it once (which exports a blank file), run the page again and then hit export again (and it populates with the correct data)
here is the export code i am using
<?PHP
session_start();
$tdata = array();
$tdata = $_SESSION['data'];
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str);
$str = preg_replace("/\r?\n/", "\\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// file name for download
$filename = "CSVOutput" . date('Ymd') . ".csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
$flag = false;
foreach($tdata as $row) {
if(!$flag) {
// display field/column names as first row
echo implode(",", array_keys($row)) . "\n";
$flag = true;
}
array_walk($row, 'cleanData');
echo implode(",", array_values($row)) . "\n";
}
exit;
?>
and here is the link to my page that is misbehaving:
http://mathdraft.com/FootballCalculator.php
after you open the page if you do the following you will create what i am experiencing
hit calculate
hit export
open up the csv - see that it is empty
hit calculate
hit export
open up the csv - it has the data
i have built this on wamp server using php 5.5.12 my host has php 5.3.29
http://mathdraft.com/phpinfo.php
is there some type of blatant error i am making in the above export code? or is it some server configuration? or is it (and i'm guessing it is this one) some function of my spaghetti code that is causing this error. it just baffles me that it would work half the time like this when the session array is being populated properly every time. it works 100% correct every time/calculation/iteration after this initial calculation
here is the html to call the CSVout procedure
<createcsv>
<FORM NAME ="form2" METHOD ="POST" ACTION = "csvout.php">
<INPUT TYPE = "Submit" Name = "Submit2" style="height:24px; width:145px; background-color:#FFFFCC; border-color: #556C55" VALUE = "Export Results">
</form>
</createcsv>
and the session creation $_SESSION['data'] = $data;
i'm really pulling my hair out on this one, any advice would be appreciated. this is my PHP learning project and i will be doing a redesign of the code but i just can't seem to let this minor bug go before starting it since this is the only thing that is holding me up from considering this version 1 "done"
I'm having a bit of trouble exporting a csv file that is created from one of my mysql tables using php.
The code I'm using prints the correct data, but I can't see how to download this data in a csv file, providing a download link to the created file. I thought the browser was supposed to automatically provide the file for download, but it doesn't. (Could it be because the below code is called using ajax?)
Any help greatly appreciated - code below, S.
include('../cofig/config.php'); //db connection settings
$query = "SELECT * FROM isregistered";
$export = mysql_query($query) or die("Sql error : " . mysql_error());
$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) ) || ( $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"); //have tried all of these at sometime
//header("Content-type: text/x-csv");
header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=export.csv");
//header("Content-Disposition: attachment; filename=export.xls");
header("Pragma: no-cache");
header("Expires: 0");
echo 'Download Exported Data'; //want my link to go in here...
print "$header\n$data";
In essence, you can't output the CSV file and the link to it in one go. (You need to introduce the concept of a page "mode" and activate the download mode via a ...pagename.php?mode=download or similar. You could then use PHP's switch statement to switch on $_GET['mode'] in your script.)
That said, the text/csv content type header you were using is correct, although you may also want to output the Content-Length and Content-Disposition headers. After you've output the file data, also be sure to stop any additional script processing via PHP's exit function.
Additionally, it would probably be a lot less hassle (and will certainly be faster/more memory efficient) to use MySQL SELECT ... INTO OUTFILE facility (if you have the permissions) rather than use PHP to gather the data.
You can't have text and a download on the same page. You need to have a link to the download area, which could just be a GET parameter leading to a function, which then does all the processing, displays headers, and echoes the content of the CSV.
For example, you could have Click here to download CSV, then in your code have if ($_GET['action'] === 'download'), get the data from the database, format it, send the headers, and echo the data. And then die(), because that part of the script can accomplish no more.
You should not put the link in the same file that generates the csv, as the link will not be in the csv itself!
Do something like:
Download CSV
and it should work
Three things to consider:
You're sending headers indicating that the user is going to be downloading a CSV file, but then you send create a link to download it? This isn't correct, you should be linking to this page, and then only outputting the CSV data itself after the headers.
MySQL has the ability to generate CSV output, and you should definitely take advantage of this instead of trying to do it yourself. You can use SELECT INTO ... OUTFILE to do this.
If you must create the CSV using PHP, please use fputcsv to do so. This will handle all the complications of CSV such as escaping and proper formatting. Since fputcsv writes to a file, you could either write it to a temporary file and then output it after you send your headers, or use the following trick to output it directly:
Do this after sending headers:
$fp = fopen('php://output', 'w');
while( $row = mysql_fetch_row( $export ) ) {
fputcsv($fp, $row);
}
I think the mySQL => CSV is common problem which is part of each PHP forum.
I have try to solve this issue in a common way and implement an free export
lib for PHP which is very similar to the Google AppInventor philosophie.
DragDrop and hide the coding stuff.
Use the lib and create your Export via Click&Point.
Common Demos: http://www.freegroup.de/software/phpBlocks/demo.html
Link to editor: http://www.freegroup.de/test/editor/editor.php?xml=demo_sql.xml
worth a look
Greetings
Andreas